Field Grid
A responsive one-to-three column grid of Fields by container width, and FieldChoices — radios or checkboxes in a wrapping row.
- Status
- Since
0.23.57- Accessibility pattern
- layout only; Field, FieldSet and RadioGroup keep semantics
Last updated
A textarea takes the whole row.
Install
Add Field Grid from the VegaStack registry. The CLI verifies the item's integrity hash before writing it.
pnpm dlx shadcn@latest add @vegastack/field-gridUsage
import {
FieldChoices,
FieldGrid,
FieldGridItem,
} from "@/components/ui/field-grid";
<FieldGrid>
{specs.map((spec) => (
<Field key={spec.id}>
<FieldLabel htmlFor={spec.id}>{spec.name}</FieldLabel>
<Input id={spec.id} />
</Field>
))}
</FieldGrid>;
<FieldSet>
<FieldLegend variant="label">Type</FieldLegend>
<FieldChoices orientation="horizontal">
<RadioGroup value={type} onValueChange={setType}>
…
</RadioGroup>
</FieldChoices>
</FieldSet>;Anatomy
Examples
Three columns
The default grid: one column below 28rem of its container's width, two from 28rem and three
from 48rem. It follows the container, not the viewport, so the same form stays one column in a
side panel. A field holding a Textarea takes the whole row by itself.
A textarea takes the whole row.
Two columns
columns={2} stops at two. FieldGridItem span="full" gives any other content the whole row.
Choices in a row
FieldChoices orientation="horizontal" sets a short set of radios (a RadioGroup placed
directly inside it) or checkbox fields side by side, wrapping onto the next line when the row is
full. Use it for two to five short options.
Choices in a column
The default vertical stack, for longer labels or more options.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
columns | 2 | 3 | 3 | The most columns the grid grows to. 3 is one column below 28rem of container width,
two from 28rem and three from 48rem; 2 stops at two. |
Data attributes and CSS variables on FieldGrid
| Attribute | Values |
|---|---|
data-columns | mirrors a prop or state value |
data-slot | "field-grid" | "field-grid-body" |
FieldGridItem
| Prop | Type | Default | Description |
|---|---|---|---|
span | "auto" | "full" | 'auto' | full takes the whole row at every width; auto takes one cell. |
Data attributes and CSS variables on FieldGridItem
| Attribute | Values |
|---|---|
data-slot | "field-grid-item" |
data-span | mirrors a prop or state value |
FieldChoices
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | 'vertical' | horizontal sets the choices side by side in a row that wraps; vertical stacks them. |
Data attributes and CSS variables on FieldChoices
| Attribute | Values |
|---|---|
data-orientation | mirrors a prop or state value |
data-slot | "field-choices" |
Accessibility
- Layout only: the grid adds no roles. Each
Fieldkeeps its label, and a set of choices keeps itsFieldSetandFieldLegend, which name the group for assistive tech. - Reading and tab order follow the source order in every column count.
- Radio targets keep their 24px hit areas side by side: the row gap is wide enough that the invisible hit areas of neighbouring choices touch without overlapping.
| Contract | States tested |
|---|---|
| Behaviour | default, full-span |
| Accessibility | semantic-html |
| Visual | default, horizontal, vertical |
Do / Don't
Field
The form-field scaffold — label, description, error, legend, separator and choice-card layouts in vertical, horizontal or responsive orientation.
Editable Cell
Inline-editable value whose edit mode looks like view — optimistic saves, a delayed spinner, rollback with a Retry toast, and table-cell and heading variants.