Label
The text label paired with a form control (Input, Switch, Checkbox, RadioGroup, Textarea). Radix Label.Root wired via htmlFor so clicking the label focuses the input, and screen readers announce the pair together. Default styling is text-sm font-medium leading-none — override to font-normal for Switch / Checkbox rows where the label reads as body text.
Anatomy
A tiny wrapper on Radix Label.Root — one text node. The important part is the htmlFor prop matching the form control's id. When it does, click-to-focus works and screen readers announce label + control as one unit. The primitive also carries peer-disabled:cursor-not-allowed peer-disabled:opacity-70 so a disabled peer input dims its label automatically.
- 1Label text
The visible label. Default text-sm font-medium leading-none — tuned for a tight caption over an input. Override to font-normal for Switch/Checkbox rows or when the label wraps.
- 2htmlFor wiring
The Radix Label.Root behaves like a native <label htmlFor>. Set htmlFor to the control's id and Radix handles focus + accessibility automatically.
- 3peer-disabled behavior
The primitive already listens to peer state via CSS: when the paired control has peer + disabled, the label dims to opacity-70 and cursor-not-allowed. No extra wiring needed if the input uses the peer class.
Recipes
Ready-to-copy compositions covering the most common Yuno usages of this atom.
The canonical form-field shape: Label above an Input, gap-2 between them, htmlFor matching the input id. Every form field in the Dashboard follows this shape.
<div className="flex flex-col gap-2">
<Label htmlFor="email">Email address</Label>
<Input id="email" type="email" placeholder="you@company.com" />
</div>A red asterisk next to the label with aria-hidden + a visually hidden '(required)' span for screen readers. Yuno reserves red text-destructive for required indicators and error states — never for decoration.
<div className="flex flex-col gap-2">
<Label htmlFor="workspace">
Workspace name
<span aria-hidden="true" className="ml-0.5 text-destructive">*</span>
<span className="sr-only">(required)</span>
</Label>
<Input id="workspace" required />
</div>A helper line under the input in text-xs text-muted-foreground. Use when the field needs an example, a format hint, or a link to where to find the value. The hint replaces the tooltip pattern — a persistent hint scales better than an icon the user has to discover.
Starts with sk_live_ or sk_sandbox_. Find it in Developers → API keys.
<div className="flex flex-col gap-2">
<Label htmlFor="api-key">API key</Label>
<Input id="api-key" placeholder="sk_live_…" />
<p className="text-xs text-muted-foreground">
Starts with sk_live_ or sk_sandbox_. Find it in Developers → API keys.
</p>
</div>For a Switch row, the label sits on the left with justify-between so the control right-aligns. For a Checkbox, the label sits to the right with items-start so multi-line labels align with the top of the box. Both drop font-medium → font-normal because the label reads as sentence-case body text.
<div className="flex items-center justify-between">
<Label htmlFor="3ds" className="font-normal">
Force 3DS challenge
</Label>
<Switch id="3ds" />
</div>
<div className="flex items-start gap-2">
<Checkbox id="terms" />
<Label htmlFor="terms" className="font-normal leading-normal">
I agree to the Terms of Service
</Label>
</div>Import
Copy this import line at the top of the file where you compose this atom.
import { Label } from "@/components/ui/label";Props
Everything else from the underlying HTML or Radix primitive is forwarded via ...props.
| Prop | Type | Default | Description |
|---|---|---|---|
| htmlFor | string | — | The id of the form control the label is describing. Radix uses it to wire the label to the control (click-to-focus, screen-reader association). Always set this on a form-field Label. |
| className | string | — | Extra classes on the underlying <label>. Common override: font-normal for a Switch/Checkbox row where the label reads as body text; leading-normal when the label wraps to multiple lines and font-medium leading-none feels too tight. |
| ...props | React.LabelHTMLAttributes<HTMLLabelElement> | — | Everything else forwards to the underlying Radix Label.Root (which renders a <label>). Standard attributes like children, onClick, id, etc. all pass through. |
Related
Cross-links to atoms and patterns you may reach for next.
- InputThe most common companion — every Input in a form has a Label above it.
- SwitchLabel-left justify-between recipe. Label is font-normal (reads as sentence-case body text).
- CheckboxLabel-right items-start recipe for consent, filters, multi-select.
- Radio groupEach radio option is a Label + Radio pair.
- TextareaSame Label-above-Input shape, just with a Textarea below.