Skip to content
Monogem

Component · Core

Label

Overview

The visible text that identifies a form control's purpose — "Email," "Full name," "Message." Label is both a standalone native primitive — confirmed in use by Checkbox, Radio Group, and Switch, alongside Input and Textarea — and a required part of the shared form-field model documented on Input's page. It is not a general-purpose typography style — don't reach for Label in place of a heading, a caption, or arbitrary metadata text; those are plain text, not a control's name.

Anatomy

Label text → optional (optional) suffix.

  • Label text — the visible name of the control it labels.
  • (optional) suffix — appended to the label text on optional fields.

Live Example

Code Example

label-showcase.tsx
import { Label } from "@/components/ui/label";

/**
* Live Label example — a Label bound to its control with `htmlFor` / `id` (the
* mandatory association), and the `(optional)` suffix for a non-required field.
* The bare <input> is a native element standing in for a form control: the
* Monogem Input component is documented separately and out of scope here.
*/
const fieldClass =
"h-10 rounded-md border-[length:var(--scale-px)] border-solid border-input bg-background px-3 text-sm leading-snug text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background";

export function LabelShowcase() {
return (
<div className="flex max-w-sm flex-col gap-6">
<div className="flex flex-col gap-2">
<Label htmlFor="label-example-name">Full name</Label>
<input
id="label-example-name"
type="text"
className={fieldClass}
placeholder="Ada Lovelace"
/>
</div>

<div className="flex flex-col gap-2">
<Label htmlFor="label-example-nickname" optional>
Nickname
</Label>
<input
id="label-example-nickname"
type="text"
className={fieldClass}
placeholder="Ada"
/>
</div>
</div>
);
}

Usage Guidance

Default usage

A native <label> bound to its control via htmlFor/id. Always visible — no floating-label pattern, and never replaced by a placeholder (see Input's shared form-field model).

Label has no disabled styling of its own — when its control is disabled, the label dims as part of the same field unit; see Input's disabled treatment.

Required and optional indicators

Fields are required by default. Optional fields append (optional) after the label text, in --muted-foreground — never a red asterisk on required fields. Full reasoning lives on Input's shared form-field model: a red asterisk would contradict Color's "red means danger, only" principle. The native required attribute (not the label) carries the actual required-field semantics.

Content guidance

  • Short noun phrase — "Email," not "Please enter your email address."
  • Sentence case.
  • No trailing colon ("Email", not "Email:").

Tokens

Label uses existing Monogem semantic tokens to stay consistent with the design system; it introduces no component-specific styling values.

TokenWhere used
--foregroundLabel text
--muted-foreground"(optional)" suffix

Text uses the "Label / button" recipe (text-sm font-medium leading-snug) — the same recipe Button uses for its own label, reused as-is.

Do / Don’t

Do

  • Bind every Label to its control with htmlFor/id.
  • Keep label text short and scannable.
  • Mark optional fields, not required ones.

Don’t

  • Use Label for headings, captions, or metadata unconnected to a form control.
  • Rely on placeholder text or aria-label in place of a visible Label when one can be shown.
  • Add a red asterisk for required fields.

Accessibility

  • htmlFor/id pairing is mandatory — it's what lets a screen reader announce the label when the control receives focus, and what lets clicking the label focus/activate the control.
  • Only fall back to aria-label (no visible text) when a visible Label truly can't be shown — a visible Label is always preferred.

Related Components / Patterns

  • Input — the control a Label most often names.
  • Checkbox — carries its own inline label.
  • Radio Group — labels the group with a legend.