Components

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.

Updated Jul 24, 2026 by Leonardo Posada

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.

  1. 1
    Label 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.

  2. 2
    htmlFor wiring

    The Radix Label.Root behaves like a native <label htmlFor>. Set htmlFor to the control's id and Radix handles focus + accessibility automatically.

  3. 3
    peer-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.

Basic label + input

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>
Required field

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>
Label + input + hint

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>
Label for Switch / Checkbox

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.

A single named export. Pair with any form control by matching htmlFor to the control id.
import { Label } from "@/components/ui/label";

Props

Everything else from the underlying HTML or Radix primitive is forwarded via ...props.

PropTypeDefaultDescription
htmlForstringThe 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.
classNamestringExtra 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.
...propsReact.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.