# Declarative XUI

The `.xui` language describes a retained control tree with C# state and behavior.
The compiler generates C# that uses the existing XUI bindings.
It does not add a runtime parser, virtual tree, or reconciler.

The implementation supports fixed compositions.
It supports named control styles, named visual parts, state rules, typography, and color resources.
The [control inventory](control-styling-inventory.md) describes the available presentation surfaces.
It does not support arbitrary dynamic children, control templates, or custom row templates.
The [engineering plan](https://github.com/zadjii-msft/xui/blob/9e6673cffbb2f4fb320da652937729f1b7a03099/docs/llm/xui-language-plan.md) defines the implementation and acceptance checks.
The [XUI Designer](../samples/designer.md) provides a native editor and live preview for a self-contained component.

## Author a component

```text
namespace Demo;

component Counter {
    state int Count = 0;

    view {
        VStack(spacing: 8, padding: 16) {
            Text($"Count: {Count}", id: "count");
            Button("Increment", click: Increment, id: "increment");
        }
    }

    code csharp {
        void Increment() => Count++;
    }
}
```

The namespace is optional.
Each file declares one component.
A component produces a C# class.
The `view` block describes the native tree.
The `code csharp` block supplies C# methods.
Fields belong in `state` declarations.

Leaf controls end with a semicolon, for example `Text("Hello");`.
Containers have a child block and end with its closing brace, for example `HStack() { Text("Hello"); }`.
Do not add a semicolon after a child block or after a `view`, `resources`, `style`, or `code csharp` block.

Native layout nodes are `VStack`, `HStack`, `Grid`, `AdaptiveLayout`, `ScrollView`, `Popup`, `SplitView`, and `Reveal`.
Basic nodes are `Text`, `Button`, `Toggle`, `ToggleSwitch`, `ToggleButton`, `CheckBox`, `HyperlinkButton`, `InfoBadge`, and `TextInput`.
Other native nodes are `DataGrid`, `NavigationView`, `ItemsView`, `RangeInput`, `Progress`, `ProgressRing`, `SelectorBar`, and `MenuBar`.
`SwapChainPanel` is a Windows-only graphics leaf. Its generated reference exposes the [native graphics contract](swap-chain-panel.md).
`Content` embeds an existing element.
Stacks have no positional argument.
Each other native node requires a string argument.
Most arguments use C# expressions.
Style arguments use the bounded style syntax described below.

All nodes support `ref: Identifier`, `size: (width, height)`, and `preferredSize: (width, height)`.
Size values use DIPs.
`ref` produces a typed public property for the native element.
Reference names cannot conflict with parameters, state, methods, the component name, or `Root`.
Names that start with `__xui` are reserved.

Stacks support `spacing` and uniform `padding`.
Controls support `id`, `enabled`, `visible`, and `help`.
Hidden `ScrollView` controls reserve no desired layout space, including passthrough hosts.
The `id` argument supplies the automation ID.
`help` supplies native help text.
`Stack`, `Grid`, `AdaptiveLayout`, and `Content` are elements, not controls, so they do not support those four arguments.
For example, `Button("?", size: (36, 36), help: "Row 1, column 1: covered.");` declares a square cell.

`Text`, `Button`, `Toggle`, `ToggleSwitch`, and `ToggleButton` use their positional string for both text and the accessible name.
They do not accept a separate `name` argument because those native properties share storage.
`TextInput` has a separate accessible name and text value.
Its `text`, `change`, and `submit` arguments configure that input.
It also supports `captionVisible` and `placeholder`.
`Toggle` and `ToggleSwitch` support `checked` and `change`.
`ToggleSwitch` keeps the Toggle model and accessibility role, with a switch pill and thumb.
`ToggleButton` supports `checked`, `change`, and `icon`.
It selects Button toggle behavior by default.
Its `change` handler receives the checked state as a `bool`.
Toggle actions do not also emit a click event. The node does not accept `click`.
Checked-state setters are silent for both toggle presentations.
Event arguments name C# methods.
`Button` supports `icon: global::Xui.ButtonIcon.Refresh` through the native `SetIcon` method.
`Button` also accepts the reactive boolean `verticalText` (default false).
For example, `Button("Hierarchy", verticalText: true, size: (32, 112));` draws a sideways edge tab:
the full label rotates clockwise, while its accessible name and keyboard behavior remain unchanged.
`ButtonIcon.Pin` and `ButtonIcon.PinFilled` supply outlined and filled pushpins.
`NavigationView` supports `headerVisible`.
Its `searchId` and `searchHelp` arguments configure the native search input.
Its optional reactive `duration` argument is a `uint` from zero through 10,000 milliseconds.
Omission preserves the zero-duration default. Changed values call `SetDuration` without replacing the native search input.
The [group animation contract](animations.md#navigation-group-transitions) describes logical state, focus, and interruption.
`SplitView` supports `secondVisible`.
Its optional reactive `duration` argument accepts a `uint` from zero through 10,000 milliseconds.
Zero disables motion. The compiler initializes duration before secondary visibility.
The [animation contract](animations.md#split-pane-transitions) describes pane geometry, focus, and interruption.
`Popup` supports `placement: global::Xui.PopupPlacement.Right` and `windowBackground`.
`AdaptiveLayout` takes navigation first and content second, with exactly two retained children.
It supports reactive `presentation`, `navigationSide`, `navigationExtent`, `navigationOpen`, `dismissOnFocusOutside`, `breakpoint`, and `compactNavigation`.
Its positional name is a fixed constructor input, not reactive state.
See the [layout examples](../choose-a-control/controls/layout.md#adaptivelayout) for responsive and pinned/overlay presentation.
`DataGrid` accepts a `global::Xui.GridColumn[]` expression in `columns`.
The compiler calls `SetColumns` when the authored column values change.

## Compiler diagnostics

XUI syntax and validation errors use `XUI001` and point to the authored `.xui` file, line, and column.
Messages identify the relevant declaration, control, argument, or style part and explain the correction.
For example, a semicolon after `HStack() { ... }` reports:

```text
Unexpected ';' after the child block of 'HStack'. Remove the semicolon: blocks end with '}', not '};'.
```

The location points to the extra semicolon, outside the child block.
Missing delimiters name the block or argument list being parsed and identify the unexpected token, including end of file.
Unknown arguments and unsupported style keywords list the choices allowed in that context.
Value errors describe the required literal form or numeric bounds.
Duplicate names and mismatched style references identify the conflicting declaration or target.

Builds and Designer previews use the same compiler diagnostics.
Invalid source still blocks compilation; a helpful message does not silently accept or repair invalid syntax.
C# type and name errors retain their C# diagnostic codes and map back to the authored expression or method.
C# syntax errors reported through XUI retain the compiler's explanation with added declaration or expression context.

## Opt-in bottom reveal

`Reveal` retains exactly one child and slides it within a native clip.
Its positional string supplies the accessible name.
The `open` argument is a reactive `bool`.
The `duration` argument is a reactive `uint` in milliseconds.
The reactive `layout` and `direction` arguments accept `global::Xui.RevealLayout` and `global::Xui.RevealDirection`.
Their defaults are `Fixed` and `Bottom`.
The compiler initializes duration, layout, and direction before open state.
Zero is the default duration and disables motion.
The native setter rejects values greater than 10,000 without changing the previous duration.

```text
component FindExample {
    state bool FindOpen = false;
    view {
        VStack() {
            Button("Open Find", ref: OpenFind, click: ShowFind);
            Reveal("Find bar", open: FindOpen, duration: 180,
                layout: global::Xui.RevealLayout.Expand, ref: FindReveal) {
                HStack(padding: 6, spacing: 8) {
                    TextInput("Find", ref: Find, captionVisible: false,
                        placeholder: "Find", preferredSize: (320, 44), flex: 1);
                    Button("Close Find", click: HideFind, size: (44, 44));
                }
            }
        }
    }
    code csharp {
        void ShowFind() { FindOpen = true; Find.Focus(); }
        void HideFind() { FindOpen = false; OpenFind.Focus(); }
    }
}
```

This example animates the reserved height together with the content position.
An automatic grid row or non-flex stack child follows that measurement.
The default `Fixed` layout instead reserves full height at entry start and releases it after exit.
`Top`, `Left`, and `Right` select other entry edges.
Horizontal expansion needs content with a bounded natural width.
The application does not bind child visibility to the open state, because outgoing content remains visible during exit.
The application still chooses focus immediately.
Reversal, reduced motion, native input, and performance limits follow the [reveal contract](animations.md).
The typed reference exposes read-only `Progress` and `Animating` properties.
These properties are not `.xui` arguments.
Reveal has no style target or arbitrary transform arguments.

## CheckBox, links, selectors, badges, and menu bars

`CheckBox` accepts `checkState`, `threeState`, and `change`.
The state type is `global::Xui.CheckState`, with `Unchecked`, `Checked`, and `Indeterminate` values.
The `change` method accepts one CheckState parameter.
The default state is unchecked, and three-state input is off.
This node does not change the binary `checked` and boolean `change` contracts of Toggle and ToggleSwitch.

`HyperlinkButton` accepts `click` and `icon`.
Its callback does not imply URI or browser navigation.
The application owns any external action.

`SelectorBar` accepts a `global::Xui.Choice[]` expression in `items` and a nullable `ulong` expression in `selected`.
Its `change` method accepts one `ulong` parameter.
The compiler applies items and selection as one native snapshot.
For joint reactive replacements, use one tuple state that contains both values.
Separate state assignments refresh immediately and can expose an invalid intermediate selection.
The [SelectorBar example](../choose-a-control/controls/choices.md#selectorbar) shows the tuple pattern.

`InfoBadge` accepts `count` as a `uint`, or `icon` as a `global::Xui.ButtonIcon`.
The compiler rejects both arguments on one node.
Without either argument, the badge uses its default dot presentation.
The badge has no action event.

`MenuBar` accepts a `global::Xui.Command[]` expression in `commands`.
Its `invoke` and `pin` methods each accept one `ulong` command ID.
Root records must have `Kind: global::Xui.CommandKind.Submenu`.
Malformed snapshots preserve the previous commands.
The native window manages submenu popups and keyboard input.

All five nodes require a positional accessible-name string.
They accept common layout, identity, visibility, help, reference, and style arguments.
Style aliases map CheckBox to Toggle, HyperlinkButton to Button, SelectorBar to ChoiceList, InfoBadge to InlineStatus, and MenuBar to CommandBar.
InfoBadge count text uses `part message`, not `part title`.
The [control guides](../choose-a-control/controls/index.md) include complete examples.

## Range input and progress

`RangeInput` is the native slider control.
Its name is not `Slider`.
`Progress` is a read-only native progress control.
`ProgressRing` uses the same range, value, and state model with a circular presentation.
All three require a positional accessible-name string and accept the common control, layout, reference, and style arguments.
All three are leaf nodes.

```text
component VolumeMeter {
    state double Level = 25;
    view {
        VStack(spacing: 8) {
            RangeInput("Volume",
                range: new global::Xui.NumericRange(0, 100, 1, 10),
                currentValue: Level,
                orientation: global::Xui.Axis.Horizontal,
                reversed: false,
                change: SetLevel);
            Progress("Volume level",
                currentValue: Level,
                progressState: global::Xui.ProgressState.Determinate);
        }
    }
    code csharp {
        void SetLevel(double value) { Level = value; }
    }
}
```

| Argument | Type | Controls |
| --- | --- | --- |
| `range` | `global::Xui.NumericRange` | RangeInput, Progress, ProgressRing |
| `currentValue` | `double` | RangeInput, Progress, ProgressRing |
| `orientation` | `global::Xui.Axis` | RangeInput |
| `reversed` | `bool` | RangeInput |
| `change` | Method with one `double` parameter | RangeInput |
| `progressState` | `global::Xui.ProgressState` | Progress, ProgressRing |

The `currentValue` argument sets the numeric value.
The language reserves `value` for the positional accessible-name operand, so `value:` remains invalid.
Numeric values, orientation, reversal, and progress state support ordinary reactive expressions.
The compiler checks expression and handler types through C#.
Progress states are `Determinate`, `Indeterminate`, `Paused`, `Error`, and `Unknown`.
Indeterminate progress uses native, window-owned animation while attached, visible, and effectively enabled.
Hidden or minimized windows stop that animation.
The system client-area animation preference suppresses motion.
Unknown states and capacity displays remain static.
The [progress contract](foundation-controls.md#progress-presentations-and-animation) defines timer ownership and lifecycle.

The optional `range` expression runs once during component construction, before the first numeric value setter.
It cannot depend on component state or call component methods.
It can use constructor parameters and supported state-free C# expressions.
This rule does not make parameter objects or external objects immutable.
Later external changes do not trigger a range update.
Changes to the authored range expression require structural replacement during hot reload.

An omitted range retains native bounds from 0 through 100, with small step 1 and large step 10.
An omitted numeric value retains the native initial value.
With a supplied range, native construction can clamp that initial value to its bounds.
The generator does not subsequently write a synthetic zero.
The omitted orientation is horizontal, and reversal is false.
Progress defaults to determinate state. ProgressRing defaults to indeterminate state.

Native setters require finite increasing bounds, a finite interval span, and positive finite steps.
Numeric values must be finite and inside the range.
Progress and ProgressRing check the supplied range structure but use only its minimum and maximum for display.
Invalid values and enum values produce native errors, without generator coercion or silent recovery.
As with other reactive bindings, a failed native setter does not roll back the authored C# state assignment.
The next valid state update can restore the control value.

The `change` handler receives committed RangeInput changes as a `double`.
Property setters do not call this handler.
The generated component registers the handler once, not during property refresh.
Native drag previews and cancellation retain their existing behavior but do not call this committed-change handler.
This language extension does not add preview or cancellation handlers.
Progress and ProgressRing do not accept a change handler.

Named styles use the existing `RangeInput` and `Progress` catalog targets and named parts.
ProgressRing also uses the `Progress` target.
ToggleSwitch and ToggleButton use the existing `Toggle` and `Button` targets.
The [foundation reference](foundation-controls.md) describes the native range, input, and progress contracts.

<a id="declare-button-styles-and-resources"></a>

## Declare control styles and resources

Resources and named styles belong directly inside a component:

```text
component DangerActions {
    resources {
        DangerFill: theme(light: 0xB42318, dark: 0x8F1D16);
        OnDangerFill: 0xFFFFFF;
        DangerEdge: theme(light: 0x68110C, dark: 0xFFA198);
        DangerHover: theme(light: 0xD92D20, dark: 0xB42318);
        DisabledFill: theme(light: 0xD0D5DD, dark: 0x475467);
        DestructiveFill: resource(DangerFill);
    }

    style DangerButton for Button {
        background: resource(DangerFill);
        foreground: resource(OnDangerFill);
        cornerRadius: 0;
        borderBrush: resource(DangerEdge);
        borderThickness: (3, 0, 0, 0);
        when hovered { background: resource(DangerHover); }
        when disabled { background: resource(DisabledFill); }
    }

    view {
        VStack() {
            Button("Delete", style: DangerButton);
        }
    }
}
```

The sample `DeclarativeSample\Counter.xui` includes this Delete button beside the existing counter controls.
The button demonstrates appearance and does not delete data.

### Grammar

The following grammar describes the style structure.
The exported catalog restricts each target, part, property, state, and value combination.
`Identifier` uses the same identifier syntax as other XUI names.
Brackets mark optional syntax, and braces after `=` mark repetition.
Quoted braces are literal delimiters.

```text
Resources   = "resources" "{" { Identifier ":" Color ";" } "}"
Style       = "style" Identifier "for" Target [ "basedOn" Identifier ]
              "{" { Property | Rule | Part } "}"
Part        = "part" PartName "{" { Property | Rule } "}"
Rule        = "when" State "{" { Property } "}"
Property    = PropertyName ":" Value ";"
Color       = Rgb24
            | "theme" "(" "light" ":" Rgb24 "," "dark" ":" Rgb24 ")"
            | "resource" "(" Identifier ")"
Insets      = Dimension | "(" Dimension "," Dimension "," Dimension "," Dimension ")"
```

`Target`, `PartName`, `State`, and `PropertyName` must match the supported catalog names.
`Value` must match the property's type and the part's limits.
Targets use case-sensitive PascalCase names, such as `TextInput`, `ItemsView`, and `NavigationView`.
Part, property, and state names use lower camel case.
The target aliases are `Text` for `Label` and `VStack` or `HStack` for `Stack`.
The [style contract](control-styling.md) describes shared behavior and target-specific boundaries.
Root and part rules accept only states that the corresponding native model supplies.
Support for a property and a state does not imply support for that property inside the state rule.
For example, `ItemsView` accepts base `tile.width`, but rejects `tile.width` in every state rule.
Parts cannot contain other parts.
State blocks cannot contain parts.
All styles reject duplicate parts and duplicate state blocks within one part.
The root is implicit, so `part root` is invalid.
Base and derived styles must target the same control type.
Per-part local values use the C++, C ABI, C#, or Rust setter.
Style-value and part-rule edits update the method-body revision for hot reload.
They preserve the existing control tree.

The compiler accepts the Element-applicable targets in the [exported catalog](https://github.com/zadjii-msft/xui/blob/9e6673cffbb2f4fb320da652937729f1b7a03099/bindings/control_style_catalog.json).
Tooltip declarations reject because tooltips require the Window API.
`ContentDialog`, `CommandSurface`, `LocationPicker`, and `ViewPicker` are facades, not style targets.
Their root styles use `Popup`.
Retained children use their actual control targets.

### Property values

The catalog determines which properties each target and part accept.
This vocabulary does not imply that every property applies to every part.

| Properties | Value syntax |
| --- | --- |
| `background`, `foreground`, `borderBrush` | RGB24 integer, `resource(Name)`, or `theme(light: RGB24, dark: RGB24)` |
| `padding`, `borderThickness` | One dimension or four dimensions in left, top, right, bottom order |
| `fontFamily` | Nonempty C# string literal with valid Unicode and no NUL |
| `fontSize` | Positive numeric literal, limited by the part |
| `fontWeight` | Integer literal from 1 through 999 |
| `fontStyle` | Bare `normal`, `italic`, or `oblique`, limited by the part |
| `horizontalAlignment`, `verticalAlignment` | Bare `start`, `center`, `end`, or `stretch`, limited by the part |
| `wrapping` | `true` or `false` |
| `maximumLines` | Integer literal from 0 through 32768 |
| `cornerRadius`, `size`, `spacing`, `headerHeight`, `indentation`, `thickness`, `width`, `height`, `rowGap`, `columnGap` | Dimension |
| `rowHeight` | Positive dimension |

Font families have a maximum length of 1024 UTF-8 bytes and must also fit the part's UTF-16 limit.
Native text parts restrict font size to 512 DIPs and family length to 31 UTF-16 code units.
Those native parts accept normal or italic fonts, not oblique.
Paragraph parts reject vertical stretch.
Supported layout parts can accept stretch.
Enum values are unquoted names, not strings or C# enum expressions.

`Rgb24` is an integer literal from `0x000000` through `0xFFFFFF`.
Hexadecimal values use `0xRRGGBB`, not alpha or COLORREF byte order.
Decimal and other C# integer literal forms are also valid within that range.
`Dimension` is a finite numeric literal from 0 through 32768 DIPs.
Negative values, arithmetic expressions, state references, and method calls are not style values.
Insets use left, top, right, bottom order.
A single dimension applies to all four edges.
Parenthesized expressions, named tuple elements, and two-value inset shorthand are not supported.

The `theme(light: ..., dark: ...)` order is fixed.
This explicit pair keeps light and dark values together without separate theme blocks or ambiguous override order.
It also permits each resource alias to identify one complete color.
The generator preserves both colors in `ThemeColor`.
The native renderer selects the active theme at paint time.
The generator does not read the current theme or freeze the color during construction.

All `resources` blocks in one component form one color scope.
Resource names are case-sensitive and must be unique within that scope.
Aliases and style properties can refer to resources declared later in the component.
The compiler checks every resource, including unused resources.
Cross-component resources, mutable resource dictionaries, and other resource types are not supported.

### Sparse values, derivation, and local properties

A style sets only its declared properties.
An omitted property remains absent, not zero.
Explicit zero therefore differs from an omitted corner radius, inset, or black color.
State rules also contain sparse values.
Repeated properties within the same style body or rule are errors.
All declarations reject duplicate state blocks within one part.
Rules cannot contain other rules.

A derived style names its base after `for Button`:

```text
style CompactDanger for Button basedOn DangerButton {
    padding: (8, 2, 8, 2);
    when pressed { background: 0x68110C; }
}
```

Base styles can appear later in the component.
Style names must be unique and cannot conflict with generated members, state, parameters, references, or methods.
Resources and styles have separate name scopes.
The compiler rejects missing base styles and inheritance cycles.

Native nodes accept a declared style name in `style: Identifier`.
The [control catalog](../choose-a-control/controls/index.md#language-and-styling-boundaries) lists all 24 supported nodes.
The style target must match the node.
Other supported targets use `Content(existingElement, style: NamedStyle)`, without a new constructor syntax.
Native attachment checks the actual target of that existing element.
`Content` requires a named style before it accepts local style properties.
Button styles can also be applied to existing buttons through `Content`.

Style names are XUI references, not fields available inside `code csharp`.
A Button also accepts the six foundation properties directly as named arguments:

```text
Button("Delete", style: DangerButton, padding: (8, 2, 8, 2), cornerRadius: 0);
Button("Local only", background: resource(DangerFill), foreground: 0xFFFFFF);
```

Local properties use the same constant syntax as style properties.
Every style declaration produces a `ControlStyle`, and local properties produce sparse `PartStyleValues`.
Generated code uses `Element.SetControlStyle` and `Element.SetControlStyleValues`.
Local properties use the root part's supported property set.
The native engine resolves local overrides, state rules, base styles, and defaults.

The node argument `size: (width, height)` remains structural size, not the scalar style property `size`.
Button scalar `size` belongs only to its supported icon and arrow parts.
Stack node arguments `padding` and `spacing` remain structural float setters and override style values.
Omitted Stack arguments leave style values available.
Explicit zero overrides them.
Padding inside a style declaration still accepts four-edge insets.

```xui
style Heading for Label {
    foreground: theme(light: 0x202020, dark: 0xEEEEEE);
    fontFamily: "Segoe UI";
    fontSize: 20;
    fontWeight: 600;
    wrapping: true;
    maximumLines: 2;
}
style Panel for Stack { padding: 12; spacing: 8; }
```

`Text("Title", style: Heading)` and `VStack(style: Panel)` apply these declarations inside the component's view.
These declarations do not replace the controls or their input behavior.

The [style contract](control-styling.md) describes that precedence and the native rendering boundaries.
This stage does not change control ownership, events, keyboard behavior, accessibility, or the control tree.
It does not implement `ItemTemplate`, control templates, implicit styles, arbitrary selectors, or state expressions.

### Bounds and diagnostics

A component supports at most 256 color resources.
A style supports at most 256 rules.
Style inheritance supports at most 16 layers, including the applied style.
Resource aliases can traverse the bounded component scope but cannot form a cycle.
The compiler checks unused styles and resources as well as referenced declarations.

Invalid declarations produce `XUI001` at the `.xui` source location and a mapped C# error that blocks the build.
These errors include duplicate names, missing references, cycles, unsupported targets, properties, states, invalid literal types, and values outside the limits.
Invalid inset lengths, duplicate properties, and excess resources, rules, or inheritance layers also block the build.
General control expressions outside the style subset retain their existing C# diagnostics.

### Shared definitions and reload

The generated class shares immutable style definitions across its component instances.
The managed binding creates native handles for each owning window.
Components without named styles do not allocate a style cache.

Edits to existing colors, aliases, properties, state rules, base-style references, and applied style references can update existing controls.
The generated cache checks a revision from a method body during refresh.
A changed revision creates new shared definitions and applies them to the existing elements.
Unchanged definitions do not trigger another native style assignment.
Local value edits update the existing local override binding.
These refreshes preserve component state, input state, event subscriptions, and control ownership.

Resource and style declaration names and order belong to the structural signature.
Adding, deleting, renaming, or reordering those declarations requires replacement.
Adding or removing a style binding or local property also requires replacement.
This prevents a removed property from remaining on a retained element.
The general runtime restrictions in [reload behavior](#understand-reload-behavior) still apply.

## Reuse a component

```text
component BrowserPane {
    param global::Xui.Element Files;
    param string Title;

    view {
        Grid(Title, ref: Layout,
            rows: [new(global::Xui.TrackSizing.Star, 1)],
            columns: [new(global::Xui.TrackSizing.Fixed, 200), new(global::Xui.TrackSizing.Star, 1)]) {
            NavigationView("Locations", ref: Navigation, headerVisible: false);
            ScrollView("Files", column: 1) {
                Content(Files);
            }
        }
    }
}
```

`param Type Name;` declares an immutable constructor input and a public read-only property.
Parameters have no initializer.
The constructor accepts `Window window`, the parameters in declaration order, and `bool attach = true`.
The parameter names `window` and `attach` are reserved.
Every component exposes its typed native root as `Root`.

```csharp
var pane = new BrowserPane(window, files, "Browser", attach: false);
var root = window.Stack().Add(pane.Root, flex: 1);
window.SetContent(root);
```

With `attach: false`, the constructor creates the tree without calling `SetContent`.
With `attach: true`, the root must be `VStack` or `HStack`.
A different root causes an `ArgumentException` before the constructor creates controls.
Existing calls such as `new Counter(window)` still attach their Stack root.

`Content(expression);` uses the supplied `Element` without creating another native element.
The expression runs once during construction and cannot depend on state.
The native bindings reject content from another window or content that already has a parent.
The caller must keep constructor-supplied element identities fixed for the component lifetime.

`Grid` accepts `global::Xui.GridTrack[]` expressions in `rows` and `columns`.
Each omitted argument defaults to one star track.
The compiler installs tracks before it adds children.
Track expressions can depend on state.
The positional Grid name is a constructor input and cannot depend on state.
Unlike controls, the managed Grid has no name setter.

A direct Grid child supports integer `row`, `column`, `rowSpan`, and `columnSpan` arguments.
Rows and columns start at zero.
Spans default to one and must be positive.
The native Grid rejects cells outside its tracks.
A direct Stack child supports `flex: float`.
Placement and flex cannot depend on state because the bindings expose no placement update method.
`Content` also accepts these parent-placement arguments.

`Grid`, `VStack`, and `HStack` use braces for their children.
`ScrollView` and `Popup` require exactly one child inside braces.
`SplitView` and `AdaptiveLayout` require exactly two children.
The compiler creates children before it calls factories that require those children.

## Bind state

The compiler generates a property for each `state` declaration.
A state change updates properties that directly depend on that state.
It does not reevaluate the entire view.
Initializers do not run again during an in-place reload.
Equal assignments do not update the controls.
Mutations inside a reference-type state value do not trigger updates.
Assigning a replacement state value can trigger an update.

Direct state references make dependencies explicit.
An arbitrary method can hide a state dependency from the compiler.
The first version rejects unsupported view expressions instead of adding runtime dependency discovery.
External helpers must be pure and receive their state dependencies as explicit arguments.
Pure methods on a state value, such as `Game.CellText(0)`, also expose that state dependency.
The compiler does not prove the purity of arbitrary external C# code.
Member names on external types do not identify component methods.
For example, `ButtonIcon.Search` remains valid when the component also declares a `Search` handler.
Direct calls to component methods, including `this.Search()`, remain invalid in view expressions.

## Configure a project

The `Xui` NuGet package includes the compiler and runtime.
The [`dotnet new xui` template](packages.md#create-a-project-with-dotnet-new) creates a package-based project with a counter and Debug hot reload.
The [package guide](packages.md#net-applications) describes package-based integration.
For source development, use the projects in this repository:

1. Create a .NET 10 executable project.
2. Import `bindings\dotnet\Xui.Declarative.targets` after the project's property definitions.
3. Add the `.xui` files inside the project directory.
4. Create the component before `Window.Run`.

The following project uses a placeholder path to the repository:

```xml
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <RuntimeIdentifier>win-arm64</RuntimeIdentifier>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <Import Project="D:\src\xui\bindings\dotnet\Xui.Declarative.targets" />
</Project>
```

The targets include the compiler and managed binding references.
Debug builds also include the development host.
Release builds exclude that host.
The targets supply the native-control application manifest unless the project specifies another manifest.

The entry point can select the development host at compile time:

```csharp
using Xui;

internal static class Program
{
    [STAThread]
    private static void Main()
    {
#if XUI_HOT_RELOAD
        Xui.Development.ReloadHost.Run(
            () => new Window("Counter", 480, 360),
            window => _ = new Demo.Counter(window));
#else
        using var window = new Window("Counter", 480, 360);
        _ = new Demo.Counter(window);
        window.Run();
#endif
    }
}
```

By default, the component constructor creates its controls and installs the Stack root content.
All control access uses the creating UI thread.
The development host does not change that rule.

## Run the sample

Use the [C# build and watch commands](../contribute-and-explore-designs/contributing.md#c-and-declarative-samples).
Edit `bindings\dotnet\DeclarativeSample\Counter.xui` while the watcher runs.
The native library does not rebuild for each markup change.

## Understand reload behavior

Authored text and supported property expressions can update existing controls.
Stack spacing and padding can also update in place.
Existing `size` and `help` bindings can update in place.
Other supported property bindings, including tracks and columns, can also update in place.
Supported C# handler-body edits affect later events.
The development host applies refreshes on the UI thread.

In-place refresh preserves component state.
It does not attach each event handler again.
Unchanged authored input values do not overwrite user edits.
Unchanged authored arrays do not reset tracks or user-adjusted column widths.
The compiler compares array contents, not array identities.
Omitted control properties do not generate refresh setters.

A structural edit changes the control types or their parent-child relationships.
A source edit to the state schema, an initializer, or an explicit automation-ID expression also requires replacement.
Parameter declarations, reference names, placement, flex, Grid and AdaptiveLayout names, and Content expressions belong to the structural signature.
An edit to any of them requires replacement.
Adding or deleting an event subscription requires replacement.
Adding or removing an optional binding also requires replacement.
Changing the target method of an existing event subscription can update in place.
The development host reports window replacement and resets component state.
It closes the old window, waits for `Run` to return, and disposes the old owner.
Then it constructs a new window.

The .NET runtime can reject other code changes as unsupported live edits.
With `--non-interactive`, the watcher restarts the process for those edits.
Process restart also resets transient state.

Controls without explicit IDs use positional identity.
Reordering same-kind controls without IDs can retain native input state at the old positions.
Stable literal IDs distinguish stateful controls during source edits.

Recoverable property errors produce diagnostics without a partial update.
The old window remains usable for those errors.
An error that prevents generation of a component's declarations can cause the SDK to request a process restart.
A later valid edit recovers without deletion of generated files, but a restarted process loses transient state.

## Publish a native executable

Use the [NativeAOT instructions](../contribute-and-explore-designs/contributing.md#nativeaot-and-deployment).
The published executable excludes the development reload host.
The executable and `xui.dll` must use the same architecture.

## Play Minesweeper

The [Minesweeper sample](../samples/minesweeper.md) uses `.xui` for a complete game interface.
It includes first-click safety, flood reveal, flags, win/loss states, and restart.
Its immutable C# model supplies values for a fixed native board.

After the native build, run:

```powershell
dotnet watch --project bindings\dotnet\Minesweeper\Minesweeper.csproj --non-interactive
```

## Install VS Code syntax support

The extension is in `integrations\vscode-xui`.
Its [README](https://github.com/zadjii-msft/xui/blob/9e6673cffbb2f4fb320da652937729f1b7a03099/integrations/vscode-xui/README.md) contains the package and installation commands.

The extension supplies `.xui` highlighting, embedded C# highlighting, brackets, comments, and snippets.
It is a syntax package.
It does not provide a language server, semantic completion, or a visual designer.

## Microsoft Edit syntax support

The [XUI LSH grammar](https://github.com/zadjii-msft/xui/blob/9e6673cffbb2f4fb320da652937729f1b7a03099/integrations/edit-lsh/xui.lsh) supplies `.xui` highlighting for [Microsoft Edit](https://github.com/microsoft/edit).
It recognizes declarations, control names, named arguments, styles, resources, and embedded C# tokens.
It preserves multiline comments, verbatim strings, raw strings, and nested C# blocks.
Ordinary and verbatim interpolated strings use C# highlighting inside interpolation expressions.
Their interpolation braces use the normal code color, while escaped braces remain part of the string.
Named argument labels have a separate token category from identifier values.
Hexadecimal and binary literals accept either letter case, digit separators, and integer suffixes.
Raw interpolated strings use one string color.
Their interpolation expressions are not parsed.
A delimiter-length quote run inside a raw interpolation can end highlighting early.

The grammar is a standalone file with no dependency on other LSH definitions.
It uses existing Edit highlight kinds and registers the `XUI` display name for `*.xui` files.
Highlighting is lexical, not semantic validation.
It does not check control arguments, style catalog entries, or C# types.
Incomplete multiline strings, comments, and blocks retain their context until a closing delimiter.

Edit compiles LSH definitions into its executable.
This repository does not install the grammar into an existing Edit binary.
The [integration procedure](../contribute-and-explore-designs/contributing.md#microsoft-edit-lsh-grammar) describes compilation and the regression suite.

## Run the integration checks

Use the [compiler and integration commands](../contribute-and-explore-designs/contributing.md#tests).
The [fixture reference](https://github.com/zadjii-msft/xui/blob/9e6673cffbb2f4fb320da652937729f1b7a03099/docs/llm/testing.md#declarative-integration-fixtures) describes the native probes and isolated edit loop.

## Performance boundary

The baseline is equivalent handwritten C# that uses the same managed bindings.
The bindings still allocate and marshal data for native calls.
The language does not remove those existing costs.

The ordinary state-update path uses generated, targeted property calls.
Development refresh tracking does not belong in the release application.
The release application does not load the compiler or a UI interpreter.

The managed Debug build supplies the development loop.
NativeAOT publishing is a separate release operation.
An incremental generator does not guarantee a fixed save-to-visible-change duration for every application.
