gpui-rsx 0.2.2

A JSX-like macro for GPUI - simplify UI development with HTML-like syntax
Documentation
# Getting Started with GPUI-RSX

GPUI-RSX is a JSX-like macro for GPUI that makes UI development more intuitive and concise.

## Installation

Add GPUI-RSX to your `Cargo.toml`:

```toml
[dependencies]
gpui = "0.1"  # or your GPUI version
gpui-rsx = "0.1"
```

## Basic Usage

### Importing the Macro

```rust
use gpui::*;
use gpui_rsx::rsx;
```

### Your First Element

The simplest RSX creates a div:

```rust
impl Render for MyView {
    fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
        rsx! {
            <div>"Hello, GPUI!"</div>
        }
    }
}
```

### Adding Attributes

RSX supports both flag attributes and value attributes:

```rust
rsx! {
    <div
        flex
        flex_col
        gap={px(16.0)}
        bg={rgb(0x3b82f6)}
    >
        "Styled content"
    </div>
}
```

#### Flag Attributes

Flag attributes are method calls without arguments:

- `flex``.flex()`
- `rounded_md``.rounded_md()`
- `cursor_pointer``.cursor_pointer()`

#### Value Attributes

Value attributes take expressions:

- `gap={px(16.0)}``.gap(px(16.0))`
- `bg={rgb(0xff0000)}``.bg(rgb(0xff0000))`
- `onClick={handler}``.on_click(handler)`

### Class Attribute

The `class` attribute provides Tailwind-like syntax:

```rust
rsx! {
    <div class="flex flex-col gap-4 p-4 bg-blue-500">
        "Content"
    </div>
}
```

Supported class patterns:

- **Layout**: `flex`, `flex-col`, `flex-row`, `grid`
- **Spacing**: `gap-4`, `p-4`, `px-2`, `py-1`, `m-4`, `mx-auto`
- **Sizing**: `w-full`, `h-screen`, `min-w-0`, `max-h-full`
- **Colors**: `bg-blue-500`, `text-red-600`, `border-gray-300`
- **Typography**: `text-xl`, `font-bold`, `text-center`
- **Borders**: `border`, `border-2`, `rounded-md`, `rounded-lg`

### Nesting Elements

Elements can be nested naturally:

```rust
rsx! {
    <div>
        <header>
            <h1>"Title"</h1>
        </header>
        <main>
            <p>"Content"</p>
        </main>
    </div>
}
```

### Expressions

Use `{...}` to embed Rust expressions:

```rust
rsx! {
    <div>
        {format!("Count: {}", self.count)}
        {self.render_child()}
    </div>
}
```

### Event Handlers

Event handlers use camelCase or snake_case:

```rust
rsx! {
    <button
        onClick={cx.listener(|view, _event, cx| {
            view.count += 1;
            cx.notify();
        })}
    >
        "Click me"
    </button>
}
```

Common event handlers:

- `onClick` / `on_click`
- `onMouseDown` / `on_mouse_down`
- `onKeyDown` / `on_key_down`
- `onHover` / `on_hover`

### Conditional Rendering

Use regular Rust `if` expressions:

```rust
rsx! {
    <div>
        {if self.show_message {
            rsx! { <span>"Visible"</span> }
        } else {
            rsx! { <span>"Hidden"</span> }
        }}
    </div>
}
```

Or use the `when` attribute:

```rust
rsx! {
    <div
        when={(self.is_active, |el| el.bg(rgb(0x00ff00)))}
    >
        "Conditionally styled"
    </div>
}
```

### Lists and Iteration

Use `for` loops to render lists:

```rust
rsx! {
    <ul>
        {for item in &self.items {
            <li>{item.clone()}</li>
        }}
    </ul>
}
```

### Fragments

Render multiple root elements with fragments:

```rust
rsx! {
    <>
        <div>"First"</div>
        <div>"Second"</div>
    </>
}
```

### Self-Closing Tags

Elements without children can use self-closing syntax:

```rust
rsx! {
    <div flex flex_col />
}
```

## Complete Example

```rust
use gpui::*;
use gpui_rsx::rsx;

struct CounterView {
    count: usize,
}

impl Render for CounterView {
    fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
        rsx! {
            <div class="flex flex-col gap-4 p-8 bg-gray-100">
                <h1 class="text-3xl font-bold">"Counter App"</h1>

                <div class="text-xl">
                    {format!("Count: {}", self.count)}
                </div>

                <div class="flex gap-2">
                    <button
                        class="px-4 py-2 bg-blue-500 text-white rounded-md cursor-pointer"
                        onClick={cx.listener(|view, _, cx| {
                            view.count += 1;
                            cx.notify();
                        })}
                    >
                        "Increment"
                    </button>

                    <button
                        class="px-4 py-2 bg-red-500 text-white rounded-md cursor-pointer"
                        onClick={cx.listener(|view, _, cx| {
                            view.count = view.count.saturating_sub(1);
                            cx.notify();
                        })}
                    >
                        "Decrement"
                    </button>
                </div>
            </div>
        }
    }
}
```

## Next Steps

- Check out the [API Reference]api-reference.md for complete documentation
- Read [Best Practices]best-practices.md for tips and patterns
- See [Troubleshooting]troubleshooting.md if you encounter issues