For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. An agent skill is available at /.well-known/agent-skills/site-skill.md.
Home

Label

An accessible form label that associates with its input and responds to disabled state.

import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";

export const LabelDemo = () => (
    <div className="flex flex-col gap-6">
      {/* Basic label + input */}
      <div className="flex flex-col gap-1.5">
        <Label htmlFor="email">Email address</Label>
        <Input id="email" type="email" placeholder="you@example.com" />
      </div>
      {/* Required */}
      <div className="flex flex-col gap-1.5">
        <Label htmlFor="username">
          Username
          <span className="text-destructive">*</span>
        </Label>
        <Input id="username" placeholder="johndoe" />
      </div>
      {/* Disabled — peer-disabled styling */}
      <div className="flex flex-col gap-1.5">
        <Label htmlFor="disabled-input">Disabled field</Label>
        <Input id="disabled-input" disabled placeholder="Not available" />
      </div>
      {/* With icon */}
      <div className="flex flex-col gap-1.5">
        <Label htmlFor="avatar" className="cursor-pointer">
          <span className="flex size-5 items-center justify-center rounded-full bg-muted text-[10px] font-semibold">NS</span>
          Display name
        </Label>
        <Input id="avatar" placeholder="Nuno Santos" />
      </div>
    </div>
  );

With input

Associate a label to a field with a matching htmlFor / id pair. Clicking the label focuses the input.

<div className="flex flex-col gap-1.5">
  <Label htmlFor="email">Email address</Label>
  <Input id="email" type="email" placeholder="you@example.com" />
</div>

Required indicator

Append a <span className="text-destructive">*</span> as a child to mark a required field. Label is flex so it aligns children naturally.

<Label htmlFor="username">
  Username
  <span className="text-destructive">*</span>
</Label>

Disabled

When the associated input is disabled, Label uses the peer-disabled: selectors to reduce opacity and show cursor-not-allowed. Place the input before the label in the DOM, or use the Field component which handles this automatically.

<div className="flex flex-col gap-1.5">
  <Label htmlFor="api-key">API key</Label>
  <Input id="api-key" disabled />
</div>

With Field

Field auto-generates the id, wires htmlFor, and propagates error / required state — no manual htmlFor / id needed.

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field";
 
<Field required error="Email is required.">
  <FieldLabel>Email</FieldLabel>
  <Input type="email" placeholder="you@example.com" />
  <FieldError />
</Field>

With icon

Label is a flex row — prefix it with any inline element.

<Label htmlFor="name" className="cursor-pointer">
  <UserIcon className="size-4" />
  Full name
</Label>
<Input id="name" placeholder="Nuno Santos" />

Props

Extends all props from LabelPrimitive.Root (Radix UI Label).
PropTypeDefaultDescription
htmlForstring—ID of the associated form control
classNamestring—Merged after base classes

Usage

import { Label } from "@/components/ui/label";
 
<Label htmlFor="email">Email address</Label>

Specs

# Mint — Label Specs
 
## Component
- name: label
- file: registry/mint/label.tsx
- installs to: components/ui/label.tsx
- dependencies: radix-ui
- registryDependencies: none
 
## What is it
A styled wrapper around Radix UI Label.Root that renders a native `<label>`
element. Its primary use case is associating a visible text label with a form
control via `htmlFor` / `id`. Prefer the `Field` compound component when the
field also needs a description or error message — `Field` handles ID generation
and aria wiring automatically.
 
## Visual identity
Plain text treatment in Mint: 14px medium-weight type, tight leading, and
`select-none` to prevent accidental text selection. Rendered as a flex row so
icons or required-field markers align without extra layout work.
 
## Design tokens
No explicit colour tokens — inherits `--foreground` from the page. Disabled
states rely on opacity reduction rather than a dedicated token.
 
## States
- peer-disabled:cursor-not-allowed: shows `not-allowed` cursor when the
  preceding sibling input is disabled; input must appear before label in DOM
- peer-disabled:opacity-70: reduces label opacity when the peer input is
  disabled
- group-data-[disabled=true]:pointer-events-none: disables pointer events when
  a parent group (e.g. Field / fieldset) carries `data-disabled=true`
- group-data-[disabled=true]:opacity-50: reduces opacity when the parent group
  is disabled
 
## Conventions
- Always pair with a form control via `htmlFor` + matching `id`; Radix
  Label.Root clicks forward to the associated control automatically
- Required-field indicator: add `<span className="text-destructive">*</span>`
  as a child — the flex layout aligns it inline
- Icon prefix: prepend any `size-4` inline element as a child; gap-2 handles
  spacing automatically
- For full form fields (description, error), use the `Field` compound
  component instead of wiring `htmlFor` / `id` manually
- Sub-components expose `data-slot="label"` for CSS targeting

Installation

GIN Design Plugin
$ npx shadcn add https://gin-design.vercel.app/label