Form Group
A label / description / error scaffold that wraps any slotted control and wires the accessibility plumbing.
Live demo
FormGroup is the presentational scaffolding around a form control you bring yourself: a Select, Textarea, Checkbox, Radio, or a bare native input. It renders the label, an optional description, and an error region, and wires the accessibility plumbing: it associates the label with the slotted control, builds aria-describedby from whichever of the description and error are showing, and reflects invalid / required onto the control as aria-invalid / aria-required.
Unlike Field, it owns no input of its own; it is the reusable wrapper that gives every other control the same labelled, described, error-aware shell. Two variants (default, invalid) and the shared three-step size scale keep it in lockstep with the rest of the form family.
When to use
How this component composes with the rest of the set.
Props
7 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
aria-labelledby. | ||||
aria-describedby. | ||||
invalid; linked into the control's aria-describedby. | ||||
aria-invalid on the control. | ||||
aria-required on the control. | ||||
Appearance
Variants
default
The resting scaffold: label, optional description, control, no error.
invalid
The error message is shown, the label takes the danger ink, and the control is marked aria-invalid.
Sizes
sm
Compact stack and smaller helper text.
md
Default.
lg
Roomier stack and larger helper text.
States
invalid
Error region revealed, label tinted danger, control flagged aria-invalid.
required
Required indicator appended to the label, control flagged aria-required.
Anatomy
The named parts that make up the component. A ::part() handle is reachable from your own stylesheet; the class beside it is the component's internal selector, which a shadow boundary keeps to itself.
group
The vertical stack wrapping the label, description, control, and error.
label
The control's label, associated with the slotted control via for / aria-labelledby.
required-indicator
The asterisk appended to the label when the group is required.
description
Optional helper text below the label, referenced by the control's aria-describedby.
control
The slot region that holds whatever control the author drops in.
error
The validation message shown when invalid, also referenced by aria-describedby.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xtyle-default register
(derive(xtyleDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--danger--danger-text--fg-1--fg-2--font-sans--leading-normal--space-0--space-1--space-2--text-body--text-sm--text-xs--weight-medium--weight-semiboldSlots
The form control to scaffold: a Select, Textarea, Checkbox, Radio, or native input.
Accessibility
Code
Scaffolding controls
FormGroup wraps a Select, a textarea, and a native input, labelling, describing, and error-wiring each.
<xtyle-form-group label="Theme" description="Applies across the whole workspace." for="theme">
<xtyle-select id="theme" name="theme">
<option value="auto">Match system</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</xtyle-select>
</xtyle-form-group>
<xtyle-form-group label="Bio" description="A short line shown on your profile.">
<textarea rows="3"></textarea>
</xtyle-form-group>
<xtyle-form-group label="Email" required invalid error="That address is already in use." for="email">
<input type="email" id="email" name="email" />
</xtyle-form-group><script lang="ts">
import { FormGroup, Select } from "@xtyle/svelte";
let theme = $state("auto");
</script>
<FormGroup label="Theme" description="Applies across the whole workspace." for="theme">
<Select id="theme" name="theme" bind:value={theme}>
<option value="auto">Match system</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</Select>
</FormGroup>
<FormGroup label="Email" required invalid error="That address is already in use." for="email">
<input type="email" id="email" name="email" />
</FormGroup>---
import { FormGroup, Select } from "@xtyle/astro";
---
<FormGroup label="Theme" description="Applies across the whole workspace." for="theme">
<Select id="theme" name="theme">
<option value="auto">Match system</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</Select>
</FormGroup>
<FormGroup label="Email" required invalid error="That address is already in use." for="email">
<input type="email" id="email" name="email" />
</FormGroup>