Fieldset
Something has to hold all these form controls together.
import { Description, Field, FieldGroup, Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> {/* ... */} </form> ) } import { Description, Field, FieldGroup, Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> {/* ... */} </form> ) } Component API
| Prop | Default | Description |
|---|---|---|
Fieldset extends the JSX <div> element | ||
disabled | false | Whether or not to disable the entire fieldset. |
Legend extends the JSX <div> element | ||
| This component does not expose any component-specific props. | ||
FieldGroup extends the JSX <div> element | ||
| This component does not expose any component-specific props. | ||
Examples
Basic example
Use the Fieldset, Legend, Text, and FieldGroup components to group a subset of form controls together:
import { Description, Field, FieldGroup, Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> {/* ... */} </form> ) } import { Description, Field, FieldGroup, Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> {/* ... */} </form> ) } Without legend
Use a Fieldset with aria-label to group a set of form controls together without a Legend:
import { Description, Field, FieldGroup, Fieldset, Label } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> <Fieldset aria-label="Shipping details"> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> </form> ) } import { Description, Field, FieldGroup, Fieldset, Label } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> <Fieldset aria-label="Shipping details"> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> </form> ) } Without role
Use the FieldGroup component on its own to use it solely for layout, without adding role="group" and announcing it to assistive technology like a traditional fieldset:
We currently only ship to North America.
If you have a tiger, we'd like to know about it.
import { Description, Field, FieldGroup, Label } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </form> ) } import { Description, Field, FieldGroup, Label } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </form> ) } With grid layout
For more complex layouts like grids, use wrapper elements to create nested form control groups and style them yourself with utility classes:
import { Description, Field, FieldGroup, Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <FieldGroup> <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 sm:gap-4"> <Field> <Label>First name</Label> <Input name="first_name" /> </Field> <Field> <Label>Last name</Label> <Input name="last_name" /> </Field> </div> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <div className="grid grid-cols-1 gap-8 sm:grid-cols-3 sm:gap-4"> <Field className="sm:col-span-2"> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> </Field> <Field> <Label>Postal code</Label> <Input name="postal_code" /> </Field> </div> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> {/* ... */} </form> ) } import { Description, Field, FieldGroup, Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <FieldGroup> <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 sm:gap-4"> <Field> <Label>First name</Label> <Input name="first_name" /> </Field> <Field> <Label>Last name</Label> <Input name="last_name" /> </Field> </div> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <div className="grid grid-cols-1 gap-8 sm:grid-cols-3 sm:gap-4"> <Field className="sm:col-span-2"> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> </Field> <Field> <Label>Postal code</Label> <Input name="postal_code" /> </Field> </div> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> {/* ... */} </form> ) } With custom layout
Use a plain <div> instead of a FieldGroup along with the unstyled Field component from @headlessui/react to implement a fully custom layout:
import { Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' import * as Headless from '@headlessui/react' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <div data-slot="control" className="grid grid-cols-1 items-center gap-x-4 gap-y-6 sm:grid-cols-3"> <Headless.Field className="grid grid-cols-subgrid sm:col-span-3"> <Label>Full name</Label> <Input className="mt-3 sm:col-span-2 sm:mt-0" name="full_name" /> </Headless.Field> <Headless.Field className="grid grid-cols-subgrid sm:col-span-3"> <Label>Street address</Label> <Input className="mt-3 sm:col-span-2 sm:mt-0" name="street_address" /> </Headless.Field> <Headless.Field className="grid grid-cols-subgrid sm:col-span-3"> <Label>Country</Label> <Select className="mt-3 sm:col-span-2 sm:mt-0" name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> </Headless.Field> <Headless.Field className="grid grid-cols-subgrid sm:col-span-3"> <Label>Delivery notes</Label> <Textarea className="mt-3 sm:col-span-2 sm:mt-0" name="notes" /> </Headless.Field> </div> </Fieldset> {/* ... */} </form> ) } import { Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' import * as Headless from '@headlessui/react' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <div data-slot="control" className="grid grid-cols-1 items-center gap-x-4 gap-y-6 sm:grid-cols-3"> <Headless.Field className="grid grid-cols-subgrid sm:col-span-3"> <Label>Full name</Label> <Input className="mt-3 sm:col-span-2 sm:mt-0" name="full_name" /> </Headless.Field> <Headless.Field className="grid grid-cols-subgrid sm:col-span-3"> <Label>Street address</Label> <Input className="mt-3 sm:col-span-2 sm:mt-0" name="street_address" /> </Headless.Field> <Headless.Field className="grid grid-cols-subgrid sm:col-span-3"> <Label>Country</Label> <Select className="mt-3 sm:col-span-2 sm:mt-0" name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> </Headless.Field> <Headless.Field className="grid grid-cols-subgrid sm:col-span-3"> <Label>Delivery notes</Label> <Textarea className="mt-3 sm:col-span-2 sm:mt-0" name="notes" /> </Headless.Field> </div> </Fieldset> {/* ... */} </form> ) } Add data-slot="control" to a child of your Fieldset if you want it to receive the same layout styles as a FieldGroup.
Disabled state
Add the disabled prop to a Fieldset component to disable the entire fieldset:
import { Description, Field, FieldGroup, Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset disabled> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> {/* ... */} </form> ) } import { Description, Field, FieldGroup, Fieldset, Label, Legend } from '@/components/fieldset' import { Input } from '@/components/input' import { Select } from '@/components/select' import { Text } from '@/components/text' import { Textarea } from '@/components/textarea' function Example() { return ( <form action="/orders" method="POST"> {/* ... */} <Fieldset disabled> <Legend>Shipping details</Legend> <Text>Without this your odds of getting your order are low.</Text> <FieldGroup> <Field> <Label>Street address</Label> <Input name="street_address" /> </Field> <Field> <Label>Country</Label> <Select name="country"> <option>Canada</option> <option>Mexico</option> <option>United States</option> </Select> <Description>We currently only ship to North America.</Description> </Field> <Field> <Label>Delivery notes</Label> <Textarea name="notes" /> <Description>If you have a tiger, we'd like to know about it.</Description> </Field> </FieldGroup> </Fieldset> {/* ... */} </form> ) }