Field

Combine labels, controls, and help text to compose accessible form fields and grouped inputs.

let months: array<BaseUi.Select.Item.t<string>> = [
  {label: "MM", value: ""},
  {label: "01", value: "01"},

Installation

npx shadcn@latest add @rescript-shadcn/Field

Usage

<Field.Set>
  <Field.Legend> {"Profile"->React.string} </Field.Legend>
  <Field.Description> {"This appears on invoices and emails."->React.string} </Field.Description>
  <Field.Group>
    <Field>
      <Field.Label htmlFor="name"> {"Full name"->React.string} </Field.Label>
      <Input id="name" placeholder="Evil Rabbit" />
    </Field>
    <Field orientation=Horizontal>
      <Switch id="newsletter" />
      <Field.Label htmlFor="newsletter"> {"Subscribe to the newsletter"->React.string} </Field.Label>
    </Field>
  </Field.Group>
</Field.Set>

Anatomy

The Field family is designed for composing accessible forms. A typical field is structured as follows:

<Field>
  <Field.Label htmlFor="input-id">Label</Field.Label>
  {/* Input, Select, Switch, etc. */}
  <Field.Description>Optional helper text.</Field.Description>
  <Field.Error>Validation message.</Field.Error>
</Field>
  • Field is the core wrapper for a single field.
  • Field.Content is a flex column that groups label and description. Not required if you have no description.
  • Wrap related fields with Field.Group, and use Field.Set with Field.Legend for semantic grouping.

Form

See the Form documentation for building forms with the Field component and React Hook Form or Tanstack Form.

Examples

Input

@react.component
let make = () =>
  <Field.Set className="w-full max-w-xs">

Textarea

@react.component
let make = () =>
  <Field.Set className="w-full max-w-xs">

Select

let items: array<BaseUi.Select.Item.t<string>> = [
  {label: "Engineering", value: "engineering"},
  {label: "Design", value: "design"},

Slider

@@directive("'use client'")

@react.component

Field.Set

@react.component
let make = () =>
  <Field.Set className="w-full max-w-sm">

Checkbox

@react.component
let make = () =>
  <Field.Group className="w-full max-w-xs">

Radio

@react.component
let make = () =>
  <Field.Set className="w-full max-w-xs">

Switch

@react.component
let make = () =>
  <Field orientation=BaseUi.Types.Orientation.Horizontal className="w-fit">

Choice Card

Wrap Field components inside Field.Label to create selectable field groups. This works with RadioItem, Checkbox and Switch components.

@react.component
let make = () =>
  <Field.Group className="w-full max-w-xs">

Field Group

Stack Field components with Field.Group. Add Field.Separator to divide them.

@react.component
let make = () =>
  <Field.Group className="w-full max-w-xs">

Responsive Layout

  • Vertical fields: Default orientation stacks label, control, and helper text—ideal for mobile-first layouts.
  • Horizontal fields: Set orientation="horizontal" on Field to align the label and control side-by-side. Pair with Field.Content to keep descriptions aligned.
  • Responsive fields: Set orientation="responsive" for automatic column layouts inside container-aware parents. Apply @container/field-group classes on Field.Group to switch orientations at specific breakpoints.
@react.component
let make = () =>
  <div className="w-full max-w-lg">

Validation and Errors

  • Add dataInvalid to Field to switch the entire block into an error state.
  • Add ariaInvalid on the input itself for assistive technologies.
  • Render Field.Error immediately after the control or inside Field.Content to keep error messages aligned with the field.
<Field dataInvalid=true>
  <Field.Label htmlFor="email"> {"Email"->React.string} </Field.Label>
  <Input id="email" type="email" ariaInvalid=true />
  <Field.Error> {"Enter a valid email address."->React.string} </Field.Error>
</Field>

Accessibility

  • Field.Set and Field.Legend keep related controls grouped for keyboard and assistive tech users.
  • Field outputs role="group" so nested controls inherit labeling from Field.Label and Field.Legend when combined.
  • Apply Field.Separator sparingly to ensure screen readers encounter clear section boundaries.

API Reference

Field.Set

Container that renders a semantic fieldset with spacing presets.

PropTypeDefault
classNamestring
<Field.Set>
  <Field.Legend> {"Delivery"->React.string} </Field.Legend>
  <Field.Group>{/* Fields */}</Field.Group>
</Field.Set>

Field.Legend

Legend element for a Field.Set. Switch to the label variant to align with label sizing.

PropTypeDefault
variantLegend | LabelLegend
classNamestring
<Field.Legend variant=Label> {"Notification Preferences"->React.string} </Field.Legend>

The Field.Legend has two variants: Legend and Label. The Label variant applies label sizing and alignment. Handy if you have nested Field.Set.

Field.Group

Layout wrapper that stacks Field components and enables container queries for responsive orientations.

PropTypeDefault
classNamestring
<Field.Group className="@container/field-group flex flex-col gap-6">
  <Field>{/* ... */}</Field>
  <Field>{/* ... */}</Field>
</Field.Group>

Field

The core wrapper for a single field. Provides orientation control, invalid state styling, and spacing.

PropTypeDefault
orientationVertical | Horizontal | ResponsiveVertical
classNamestring
dataInvalidbool
<Field orientation=Horizontal>
  <Field.Label htmlFor="remember"> {"Remember me"->React.string} </Field.Label>
  <Switch id="remember" />
</Field>

Field.Content

Flex column that groups control and descriptions when the label sits beside the control. Not required if you have no description.

PropTypeDefault
classNamestring
<Field>
  <Checkbox id="notifications" />
  <Field.Content>
    <Field.Label htmlFor="notifications"> {"Notifications"->React.string} </Field.Label>
    <Field.Description> {"Email, SMS, and push options."->React.string} </Field.Description>
  </Field.Content>
</Field>

Field.Label

Label styled for both direct inputs and nested Field children.

PropTypeDefault
classNamestring
<Field.Label htmlFor="email"> {"Email"->React.string} </Field.Label>

Field.Title

Renders a title with label styling inside Field.Content.

PropTypeDefault
classNamestring
<Field.Content>
  <Field.Title> {"Enable Touch ID"->React.string} </Field.Title>
  <Field.Description> {"Unlock your device faster."->React.string} </Field.Description>
</Field.Content>

Field.Description

Helper text slot that automatically balances long lines in horizontal layouts.

PropTypeDefault
classNamestring
<Field.Description>We never share your email with anyone.</Field.Description>

Field.Separator

Visual divider to separate sections inside a Field.Group. Accepts optional inline content.

PropTypeDefault
classNamestring
<Field.Separator>Or continue with</Field.Separator>

Field.Error

Accessible error container that accepts children or an errors array (e.g., from react-hook-form).

PropTypeDefault
errorsArray<Error.t>
classNamestring
<Field.Error errors={errors.username} />

When the errors array contains multiple messages, the component renders a list automatically.

Field.Error also accepts issues produced by any validator that implements Standard Schema, including Sury, Zod, Valibot, and ArkType. Pass the issues array from the schema result directly to render a unified error list across libraries.