Label
Names a form control.
Installation
npx shadcn@latest add https://qure-ui.qure.ai/r/label.jsonUsage
import { Label } from '@/components/ui/label'Either associate it explicitly, or wrap the control:
<Label htmlFor="accession">Accession number</Label>
<Input id="accession" />
<Label><Checkbox /> Include prior studies</Label>Both make the text a click target for the control, which matters more than it sounds — a 14px checkbox is a small thing to hit, and the label is usually ten times the area.
A Label is for a form control and nothing else. Text that names a region, a card or a table
column is a heading or a th; giving it a label element points the accessibility tree at a
control that does not exist.
Beside an input
The default shape: label above, control below, an 8px gap. Use htmlFor with the control's id
whenever the two are siblings rather than nested.
Wrapping a control
For a checkbox or a switch, wrapping is usually better than htmlFor — there is no id to keep
in step, and the whole row becomes the hit target. Label is already
inline-flex items-center gap-2, so the control and its text align without extra classes.
Both forms work with Base UI's Checkbox and Switch: each renders a real hidden input beside
the visible span, and their id prop lands on that input rather than on the span — so
htmlFor associates correctly. Set nativeButton and the id moves to the span, at which point
only wrapping works.
Required and optional
Mark whichever is rarer, and mark it once. The asterisk is aria-hidden because the control's
own required attribute is what a screen reader announces — a read-out "star" adds noise. Where
most fields are required, label the exceptions "Optional" instead and drop the asterisks.
A placeholder is not a label. It disappears exactly when someone needs it, it is announced
inconsistently, and it fails contrast far more often than body text. Every input wants a real
label, even when the design puts it visually elsewhere. If the design has no room, keep the
label and hide it with sr-only.
API Reference
No primitive and no added props — everything a native
<label> accepts, including
htmlFor. Inside a Base UI Field the association
is supplied for you and htmlFor becomes unnecessary.
The stylesheet greys the label when the control it names is disabled, via
:has(+ :disabled) and :has(:disabled) — so the sibling and wrapping forms both dim without a
prop.