Components
Field
View in FigmaThe label + control + help/error wrapper that every form row is built from. It generates an id, associates the <label>, wires aria-describedby to the description/error, and flips the control into its invalid state when error is set — so any control that accepts id/aria-* (Input, Textarea, Select) gets accessible labelling for free. label/description/error are data props; the control is a composition slot.
Install
npx shadcn@latest add @alix/fieldPreview
Internal code-name.
Usage
<Field label="Engagement name" description="Internal code-name." required>
<Input placeholder="e.g. Project Atlas" />
</Field>
<Field label="Owner" error="Select an owner.">
<Select items={owners} placeholder="Unassigned" />
</Field>Examples
Select with helper text
Field wires the label and description to Select just as it does for a text input.
Shown in the engagement dashboard.
<Field label="Owner" description="Shown in the engagement dashboard.">
<Select
placeholder="Unassigned"
items={[
{ value: "jp", label: "J. Patel" },
{ value: "rs", label: "R. Silva" },
{ value: "mk", label: "M. Khan" },
]}
/>
</Field>Error replaces help
When error is present, the helper copy is hidden and the child control receives aria-invalid.
Client code is required.
<Field
label="Client code"
description="Use the finance system identifier."
error="Client code is required."
required
>
<Input placeholder="e.g. ALX-1042" />
</Field>Form section
A form section composes Field with Input, Select, Textarea, and Button without Field mirroring any control API.
<div className="flex flex-col gap-4">
<div className="grid gap-4 md:grid-cols-2">
<Field label="Engagement name" required>
<Input defaultValue="Project Atlas" />
</Field>
<Field label="Priority">
<Select
defaultValue="urgent"
items={[
{ value: "urgent", label: "Urgent" },
{ value: "standard", label: "Standard" },
]}
/>
</Field>
</div>
<Field label="Decision needed">
<Textarea rows={4} placeholder="Summarise the client decision." />
</Field>
<div>
<Button>Save request</Button>
</div>
</div>When to use it
Use it for
- Every labelled form row that needs accessible label, description, required, or error wiring.
- Input, Textarea, Select, or another single control that accepts id and aria attributes.
- Validation states where the control and error message must stay associated.
Reach for something else
- Plain layout groups with no form control — use Stack or Grid instead.
- Standalone check rows with visible label text beside the box — use Checkbox with a label instead.
- Inline add-ons around a control — use InputGroup inside an already-labelled context instead.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | ReactNode | — | Rendered as a <label> wired to the control via htmlFor. |
| description | ReactNode | — | Helper text under the control. Hidden while an error is showing. |
| error | ReactNode | — | Error message — turns the control's invalid treatment on and replaces the description. |
| required | boolean | false | Adds an asterisk and forwards required to the control. |
| children | React.ReactElement | — | The single form control — a composition slot, not a config. Field clones it to inject id, aria-describedby, aria-invalid, and required. |