Components
Field
Combine labels, controls, and help text to compose accessible form fields and grouped inputs. Supports vertical, horizontal, and responsive orientations.
Preview
Installation
npx blackboard-ui@latest add fieldUsage
import {
Field,
FieldContent,
FieldDescription,
FieldError,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSeparator,
FieldSet,
FieldTitle,
} from "@/components/ui/field";
import { Input } from "@/components/ui/input";
export default function Example() {
return (
<Field>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" type="email" placeholder="you@example.com" />
<FieldDescription>We'll never share your email.</FieldDescription>
</Field>
);
}Anatomy
The Field family is designed for composing accessible forms. A typical field is structured as follows:
<Field>
<FieldLabel htmlFor="input-id">Label</FieldLabel>
{/* Input, Select, Switch, etc. */}
<FieldDescription>Optional helper text.</FieldDescription>
<FieldError>Validation message.</FieldError>
</Field>Fieldis the core wrapper for a single field.FieldContentis a flex column that groups label and description — useful in horizontal layouts.- Wrap related fields with
FieldGroup, and useFieldSetwithFieldLegendfor semantic grouping.
Examples
Input
We'll never share your email with anyone.
<Field>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" type="email" placeholder="Enter your email" />
<FieldDescription>We'll never share your email.</FieldDescription>
</Field>Disabled
Add data-disabled to the Field to cascade the disabled state visually.
This field is currently disabled.
<Field data-disabled>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" placeholder="Enter your email" disabled />
<FieldDescription>This field is currently disabled.</FieldDescription>
</Field>Invalid
Add data-invalid to the Field and aria-invalid on the input. Labels, descriptions, and errors switch to destructive styling automatically.
Please enter a valid email address.
<Field data-invalid>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" type="email" aria-invalid="true" defaultValue="not-an-email" />
<FieldError>Please enter a valid email address.</FieldError>
</Field>Field Group
Stack fields with FieldGroup. Add FieldSeparator to visually divide sections.
Optional — for business accounts.
<FieldGroup>
<Field>
<FieldLabel htmlFor="first">First name</FieldLabel>
<Input id="first" placeholder="Jane" />
</Field>
<Field>
<FieldLabel htmlFor="last">Last name</FieldLabel>
<Input id="last" placeholder="Doe" />
</Field>
<FieldSeparator>Or continue with</FieldSeparator>
<Field>
<FieldLabel htmlFor="company">Company</FieldLabel>
<Input id="company" placeholder="Acme Inc." />
<FieldDescription>Optional — for business accounts.</FieldDescription>
</Field>
</FieldGroup>Fieldset
Use FieldSet with FieldLegend for semantic, accessible grouping.
<FieldSet>
<FieldLegend>Shipping Address</FieldLegend>
<FieldDescription>Enter delivery address.</FieldDescription>
<FieldGroup>
<Field>
<FieldLabel htmlFor="street">Street address</FieldLabel>
<Input id="street" placeholder="123 Main St" />
</Field>
{/* ... more fields */}
</FieldGroup>
</FieldSet>Horizontal
Set orientation="horizontal" to align label and control side by side. Pair with FieldContent to keep descriptions aligned.
Your work email.
<Field orientation="horizontal">
<FieldContent className="shrink-0 min-w-28">
<FieldLabel htmlFor="email">Email</FieldLabel>
<FieldDescription>Your work email.</FieldDescription>
</FieldContent>
<Input id="email" type="email" placeholder="you@company.com" />
</Field>Responsive
Set orientation="responsive" for automatic column layout driven by @container queries on FieldGroup. Vertical on narrow, horizontal on wide — no JS needed.
As shown on your ID.
Your primary contact.
<FieldGroup>
<Field orientation="responsive">
<FieldContent className="shrink-0 @md/field-group:min-w-32">
<FieldLabel htmlFor="name">Full name</FieldLabel>
<FieldDescription>As shown on your ID.</FieldDescription>
</FieldContent>
<Input id="name" placeholder="Jane Doe" />
</Field>
</FieldGroup>API Reference
Field
| Prop | Type | Default |
|---|---|---|
| orientation | "vertical" | "horizontal" | "responsive" | "vertical" |
| data-invalid | boolean | — |
| data-disabled | boolean | — |
FieldLabel
| Prop | Type | Default |
|---|---|---|
| asChild | boolean | false |
| className | string | — |
FieldLegend
| Prop | Type | Default |
|---|---|---|
| variant | "legend" | "label" | "legend" |
| className | string | — |
FieldError
| Prop | Type | Default |
|---|---|---|
| errors | Array<{ message?: string }> | — |
| className | string | — |
All subcomponents also accept standard HTML attributes for their respective element types (className, children, etc.). FieldSet, FieldGroup, FieldContent, FieldTitle, FieldDescription, and FieldSeparator accept className as their only custom prop.