# Field

The composition that ties a label, a control, its description and its errors into one announced unit.

```slint
import { Field } from "@glint/components/field.slint";
import { Input } from "@glint/components/input.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 320px;
    background: Tokens.color-background;

    in-out property <string> email-val: "";

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            VerticalLayout {
                width: 320px;

                email-field := Field {
                    label: "Email Address";
                    required: true;
                    description: "We'll never share your email with third parties.";
                    label-clicked => { email-input.focus(); }

                    email-input := Input {
                        text <=> root.email-val;
                        placeholder: "user@example.com";
                        invalid: email-field.invalid;
                    }
                }
            }
        }
    }
}
```

## Usage

```slint
import { Field } from "@glint/components/field.slint";
import { Input } from "@glint/components/input.slint";

export component AppWindow inherits Window {
    in-out property <string> username: "";

    VerticalLayout {
        alignment: center;

        username-field := Field {
            label: "Username";
            required: true;
            description: "Your unique public handle.";
            errors: root.username == "" ? ["Username is required."] : [];
            label-clicked => { username-input.focus(); }

            username-input := Input {
                text <=> root.username;
                invalid: username-field.invalid;
            }
        }
    }
}
```

`Field` acts as the single source of truth for form field composition. It pairs a label, helper description, and validation errors with an arbitrary slotted control. Bind your control’s `invalid` property to the surrounding `Field.invalid` output so that visual error borders and message text remain synchronized.

## Examples

### Orientations

The `orientation` property controls label placement relative to the control. `FieldOrientation.vertical` stacks the label above the control (standard for form columns). `FieldOrientation.horizontal` places the label beside the control (ideal for settings rows and switches). `FieldOrientation.responsive` places the label beside the control when container width exceeds `responsive-breakpoint` (default `448px`), falling back to stacked on narrower widths.

```slint
import { Field, FieldOrientation } from "@glint/components/field.slint";
import { Input } from "@glint/components/input.slint";
import { Switch } from "@glint/components/switch.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 380px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        spacing: 20px;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            VerticalLayout {
                width: 360px;
                spacing: 16px;

                Field {
                    label: "Profile Name";
                    orientation: FieldOrientation.vertical;
                    description: "Displayed on your public profile.";

                    Input {
                        placeholder: "Jane Doe";
                    }
                }

                Field {
                    label: "Auto-sync Data";
                    orientation: FieldOrientation.horizontal;
                    description: "Sync changes across all registered devices.";

                    Switch {
                        checked: true;
                    }
                }

                Field {
                    label: "Responsive Field";
                    orientation: FieldOrientation.responsive;
                    description: "Adapts layout depending on available width.";

                    Input {
                        placeholder: "Adaptive layout";
                    }
                }
            }
        }
    }
}
```

### Validation errors and live region

Pass an array of error messages to `errors`. When non-empty, `Field.invalid` becomes `true` and each message is rendered in destructive red text below the control. Each error is declared as an assertive live region so assistive technology immediately announces the failure upon validation.

```slint
import { Field } from "@glint/components/field.slint";
import { Input } from "@glint/components/input.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 320px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            VerticalLayout {
                width: 320px;

                field := Field {
                    label: "Account Password";
                    required: true;
                    errors: [
                        "Password must be at least 8 characters long.",
                        "Must contain at least one uppercase letter."
                    ];

                    Input {
                        text: "pass";
                        invalid: field.invalid;
                    }
                }
            }
        }
    }
}
```

### Disabled field

Setting `disabled: true` on `Field` cascades disabled styling (dimmed opacity and silenced click interactions) to the label.

```slint
import { Field } from "@glint/components/field.slint";
import { Input } from "@glint/components/input.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 300px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            VerticalLayout {
                width: 320px;

                Field {
                    label: "License Key";
                    description: "Managed by your enterprise organization.";
                    disabled: true;

                    Input {
                        text: "GLINT-ENTERPRISE-9842";
                        enabled: false;
                    }
                }
            }
        }
    }
}
```

## API Reference

### Properties

| Property                | Type                  | Default                     | Description                                                                                                                                                                                                                                           |
| ----------------------- | --------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label`                 | `in string`           | no default                  | Label shown beside or above the control; empty hides the label row.                                                                                                                                                                                   |
| `required`              | `in bool`             | `false`                     | Appends the destructive asterisk to the label.                                                                                                                                                                                                        |
| `description`           | `in string`           | no default                  | Helper text under the label; empty hides it.                                                                                                                                                                                                          |
| `errors`                | `in [string]`         | no default                  | Validation messages under the control, one text node each; an empty list means "valid". A control failing two rules reports two messages rather than one string the consumer had to join.                                                             |
| `orientation`           | `in FieldOrientation` | `FieldOrientation.vertical` | Where the label sits — see `FieldOrientation`.                                                                                                                                                                                                        |
| `responsive-breakpoint` | `in length`           | `448px`                     | The width a `responsive` field needs before it lays out as a row. shadcn's is the `@md` container query; a narrower form column can say so here.                                                                                                      |
| `disabled`              | `in bool`             | `false`                     | Carries the row's disabled state to the label this Field owns, so a disabled form row is said once here rather than on the label and the control both. The control in the slot still takes its own `disabled` — it is the thing that stops answering. |
| `invalid`               | `out bool`            | no default                  | True while `errors` carries a message — bind the control's `invalid` to it.                                                                                                                                                                           |

### Callbacks

| Callback          | Description                                                     |
| ----------------- | --------------------------------------------------------------- |
| `label-clicked()` | Fired when the label is clicked; forward focus to your control. |

### Enums

| Enum               | Values                                 |
| ------------------ | -------------------------------------- |
| `FieldOrientation` | `vertical`, `horizontal`, `responsive` |

## Accessibility

- **Groupbox role.** `Field` publishes an accessible `groupbox` node carrying `accessible-label: root.label`.
- **Descriptive context.** The accessible description joins `description` and the first validation error message (ADR-0013).
- **Live region error announcements.** Every error in `errors` is announced via `accessible-live-region: AccessibleLiveness.assertive`.
- **Label forwarding.** Activating the label runs `label-clicked()`, allowing the parent container to forward keyboard focus to the slotted control.
