Label

Names one form control. Put it above an input or select, wrap a checkbox, switch, or radio with it, or place it beside a long confirmation.

Above a control

htmlFor names an input, select, or textarea. A click on the label moves focus to the control.

Large input · onboarding

This URL is taken. Try another.

Default input · dialogs

Compact filters

The same label over 28px select triggers in a files toolbar.

Wrapping a checkbox

Put the checkbox first, then its text. The whole row toggles it, and the text dims when the checkbox is disabled.

States
Workflow access for Maya Chen

2 of 3 permissions granted

Wrapping a switch

Both switch sizes keep the 8px gap and the 14px label text.

size="default"18px track · settings rows
size="sm"14px track · dense lists

Wrapping a radio

Each option is a label around its radio. Arrow keys move between options.

Checkbox before a label

For long confirmations, place the checkbox beside the label and point htmlFor at its id.

Visually hidden text

In a grid of checkboxes, the label can hold only the checkbox and hidden text that names the row.

PersonUseManage
Maya Chen
Jordan Okafor
Priya Raman-Lindqvist

Wrapping a text control

A label around a textarea stacks the text above it, so no id is needed.

Naming a custom control

When the control is not a form element, give the label an id and point aria-labelledby at it.

New sign-up from Form · Email

The value must be text, from 1 to 4,000 characters.

Inside a locked field

A field wrapper with data-slot="field" and data-disabled dims its labels and stops label clicks while a save runs.

Usage

Label usageTSX
import { Label } from "@tulipfarm/sprout/label";

<div className="grid gap-1.5">
  <Label htmlFor="workspace-name">Workspace name</Label>
  <Input id="workspace-name" />
</div>

<Label>
  <Checkbox checked={business} onCheckedChange={setBusiness} />
  Shared business account
</Label>

<div className="flex items-start gap-3">
  <Checkbox id="retained-data" checked={acknowledged} onCheckedChange={setAcknowledged} />
  <Label htmlFor="retained-data">
    I understand that workspace data is retained, not erased.
  </Label>
</div>

Label renders a label element and takes everylabel prop. Text is 14px, medium weight. Children sit in a row 8px apart, so a control and its text line up without extra classes. There is one size. It pairs with large and default inputs, 32px and 28px selects, and both switch sizes.

Long text wraps, and long names or addresses break anywhere instead of overflowing. When a checkbox, switch, or radio is inside the label or just before it, the line height grows to 20px and the pointer becomes a hand, since a click on the text toggles the control.

Wrapping a text control

Label around a textareaTSX
<Label>
  {advanced ? "Response JSON" : "Decision or comment"}
  <Textarea value={text} disabled={closed} onChange={…} />
</Label>

When the label wraps a textarea, select, input, or select trigger, the text stacks above the control with a 6px gap and the control fills the width. The control needs no id.

Disabled

Label has no disabled prop. It follows its control.

A label that wraps a disabled control turns muted and shows a not-allowed cursor. The control keeps its own disabled look, so nothing is dimmed twice.

A label just before or after a disabled control, such as a confirmation beside its checkbox or a stacked label over a disabled input, fades to 50%.

Inside a wrapper with data-slot="field" and data-disabled, or inside a disabled fieldset, the label fades to 50% and ignores clicks.

Accessibility

Every label must name a control. Use htmlFor with the control'sid, or wrap the control. Base UI checkboxes, switches, and radios take the id on their hidden input, so both forms work, and Space toggles the control once it has focus.

For a control that is not a form element, such as a rich text editor, give the label an id and set aria-labelledby on the control. A label with no control and no id names nothing.

When a grid of checkboxes has its names in row and column headers, wrap each checkbox and add visually hidden text, such as “Use Maya Chen”.

Label text cannot be selected, so a double click on it does not highlight words. Color and opacity changes take 120ms and stop when reduced motion is requested.

Theme tokens

Text uses --sprout-text, and --sprout-mutedwhen it wraps a disabled control. Size and family follow --sprout-text-sm and --sprout-font.