Components

Field

Combine labels, controls, and help text to compose accessible form fields and grouped inputs. Supports vertical, horizontal, and responsive orientations.

Preview

Payment Method

All transactions are secure and encrypted

Enter your 16-digit card number

Billing Address

The billing address associated with your payment method

Installation

npx blackboard-ui@latest add field

Usage

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>
  • Field is the core wrapper for a single field.
  • FieldContent is a flex column that groups label and description — useful in horizontal layouts.
  • Wrap related fields with FieldGroup, and use FieldSet with FieldLegend for 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.

<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.

Or continue with

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.

Shipping Address

Enter the address where you want your order delivered.

<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

PropTypeDefault
orientation"vertical" | "horizontal" | "responsive""vertical"
data-invalidboolean
data-disabledboolean

FieldLabel

PropTypeDefault
asChildbooleanfalse
classNamestring

FieldLegend

PropTypeDefault
variant"legend" | "label""legend"
classNamestring

FieldError

PropTypeDefault
errorsArray<{ message?: string }>
classNamestring

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.