# Elements

`render` returns elements. An element is a description rather than a widget. It says what should
exist, and the reconciler decides what to create, keep, or remove. `use nd::prelude::*;` brings the
whole vocabulary into scope.

> **Example: Hello.** Source in [examples/hello](https://github.com/FormalStudio/NativeDesktop/blob/main/examples/hello). Live on the web and captured on macOS, Linux and Windows in the docs app.


## The building blocks

- `div()` is a box. `v_flex()` and `h_flex()` are each a `div` with a column or row flex direction.
- `text("..")` is a run of text.
- `button(id, label)`, `text_field(id)`, `list(..)`, and the other
  [components](https://native.formalsnake.dev/components/index.md) are elements that become native controls where the platform has one.
- `scaffold()`, `toolbar()`, and `sidebar()` describe window structure rather than boxes. The OS
  draws its own version of each.

Add one child with `.child(x)` and many with `.children(iter)`. Anything that implements
`IntoElement` can be a child, and so can an `Entity<V>` of a view, which renders on its own.

```rust
pub struct Counter {
    count: u32,
}

impl Render for Counter {
    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        let theme = cx.theme();
        scaffold()
            .toolbar(toolbar().item(button("add", "Add one").on_click(cx.listener(
                |this, _: &ClickEvent, _window, cx| {
                    this.count += 1;
                    cx.notify();
                },
            ))))
            .content(
                v_flex()
                    .size_full()
                    .items_center()
                    .justify_center()
                    .gap_2()
                    .child(window_controls().at(point(px(16.), px(10.))))
                    .child(text(self.count.to_string()).text_size(px(48.)).tabular_nums())
                    .child(text("clicks").text_color(theme.text.secondary)),
            )
    }
}
```

<sub>From [examples/hello/src/lib.rs](https://github.com/FormalStudio/NativeDesktop/blob/main/examples/hello/src/lib.rs), line 4.</sub>


## Styling

Elements take GPUI's `Styled` methods: `size_full()`, `gap_2()`, `px_3()`, `items_center()`,
`justify_center()`, `flex_1()`, `min_h_0()`, `text_size(px(48.))`, `text_color(..)`, and others. Each
method writes one field of the element's style. Text has a few methods of its own, such as
`tabular_nums()` for digits that don't shift as a count changes.

Take colors, spacing, and type sizes from `cx.theme()`: `theme.text.secondary`,
`theme.spacing.content_margin`, `theme.type_scale.title`. A literal color fails `nd check`. The
tokens follow the platform's light and dark appearance and a matugen palette. For the full list,
see the [theming page](https://native.formalsnake.dev/concepts/theming.md).

## Layout

Layout is flexbox. Taffy computes it with the same style mapping on every backend. A `v_flex` stacks
children from top to bottom, `.flex_1()` gives a child the remaining space, and `.min_w_0()` lets a
child shrink below its content width. Native controls report their own size (`measure`), so a button
keeps the size the OS gives it.

Some containers lay out their own children: a native list's rows, a split view's panes, a
toolbar's items, and a scroll view's document. Those are layout boundaries. The container tells the
child how much room it has, the framework lays out inside, and the child's height or intrinsic size
goes back to the container.

## Identity

The reconciler matches each new element to a retained node by identity:

- With an explicit id, by element type and that id: `text("..").id("status")`, `button("add", ..)`.
- Without one, by element type, the source location of the constructor and the occurrence index
  among siblings that share that location.

Location-based identity makes `.when(..)` safe. A conditional child leaves no hole in the child
list, so when the condition flips, a sibling stays the same native node and keeps its focus, text
selection, and scroll position.

```rust
Some(tab) => v_flex()
    .size_full()
    .when(loading, |d| d.child(progress(Some(fraction as f32)).id("progress").w_full()))
    .child(div().flex_1().w_full().child(self.page_view(tab, cx)))
    .when(!self.status.is_empty(), |d| {
        d.child(text(self.status.clone()).id("status").text_color(secondary).p(margin))
    })
    .into_any_element(),
```

<sub>From [examples/browser/src/lib.rs](https://github.com/FormalStudio/NativeDesktop/blob/main/examples/browser/src/lib.rs), line 329.</sub>


Here, the progress bar appears and disappears without touching the page view below it. Give an
explicit id to anything stateful that you create in a loop or a helper function: text fields, lists,
tables, web views. An explicit id is also the element's test id, which is how
`click(cx, window, "add")` finds a node.
