form
Wraps one form control with a label, help text and an error message, and wires up the accessibility attributes.
npx blankui add fieldWe never share it.
Field renders the label, help text and error for one control, and passes id, aria-describedby, aria-invalid and required to the control inside it. Input, Textarea, Select and Checkbox all read this automatically.
import { Field } from "@/components/ui/field"
<form onSubmit={handleSubmit}>
<Stack gap={4}>
<Field label="Email" description="We never share your email." error={errors.email} required>
<Input type="email" name="email" />
</Field>
<Field label="Plan">
<Select name="plan" defaultValue="pro">
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="free">Free</SelectItem>
<SelectItem value="pro">Pro</SelectItem>
</SelectContent>
</Select>
</Field>
<Field label="I agree to the terms" orientation="horizontal">
<Checkbox name="terms" />
</Field>
<Button type="submit">Create account</Button>
</Stack>
</form>
const { register, formState: { errors } } = useForm<FormValues>()
<Field label="Name" error={errors.name?.message} required>
<Input {...register("name", { required: "Name is required" })} />
</Field>
label (required): visible label text.description: help text under the label.error: error message. Marks the control invalid.required: marks the control required and shows *.orientation: vertical (default) or horizontal. Use horizontal for Checkbox.id: control id. Generated when not set.Call useFieldControl(props) in your control and spread the result onto the element. It adds the Field wiring and keeps any props you set directly.
| Avoid | Instead |
|---|---|
| <label htmlFor="email">Email</label><Input id="email" /> | <Field label="Email"><Input /></Field> |
| {error && <p className="text-red-500">{error}</p>} under an input | <Field label="Email" error={error}> |
| Setting aria-invalid or aria-describedby by hand | Field sets them from the error and description props |
| Placeholder text instead of a label | A label prop, plus a placeholder only for an example value |
Install with the shadcn CLI: npx shadcn add https://blank.vageshwar.dev/r/field.json