1
ComponentsForm Controls

Label

Label gives one form control a visible, clickable name through htmlFor or wrapper semantics.

Purpose

Label gives one form control a visible, clickable name through htmlFor or wrapper semantics.

Control labels

import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";

export function Example() {
  return <Label><Checkbox />Receive updates</Label>;
}

Installation

With the Siteplane registry alias configured, add the component and import the installed source from your app.

CLI

pnpm dlx shadcn@4.16.1 add @siteplane/label

Import

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

Need the machine-readable source metadata? View registry JSON.

Usage

Use Label for standalone labeled controls. Inside Field, prefer FieldLabel so errors and descriptions wire automatically.

import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";

export function Example() {
  return <Label><Checkbox />Receive updates</Label>;
}

Examples

Pairing, states, the render prop and practical label patterns are compositions of the same primitive.

With control

const id = useId();

<div className="grid gap-1.5">
  <Label htmlFor={id}>Project name</Label>
  <Input id={id} placeholder="Plane workspace" />
</div>

Nested control

Wrapping the control skips htmlFor and keeps the whole area clickable.

<Label className="cursor-pointer flex-col items-start gap-1.5">
  <span>Email address</span>
  <Input
    aria-label="Email address"
    placeholder="team@ui.siteplane.io"
    type="email"
  />
</Label>

Required

<Label htmlFor={id}>
  <span>
    Email address
    <span aria-hidden="true" className="ml-0.5 text-destructive-foreground">
      *
    </span>
  </span>
</Label>
<Input id={id} required type="email" />

Disabled

A disabled control inside the label dims the text and blocks the pointer.

<Label>
  <Checkbox disabled />
  Receive partner offers
</Label>

<Label>
  <Switch disabled />
  Enable beta features
</Label>

Custom element

The render prop swaps the underlying element while keeping label styling.

Rendered as span
<Label>Rendered as label</Label>
<Label render={<span />}>Rendered as span</Label>

Inline help

Only you can see this name in the token list.
<div className="grid gap-1.5">
  <Label htmlFor={id}>API token name</Label>
  <Input aria-describedby={helpId} id={id} placeholder="ci-deploy" />
  <span className="text-muted-foreground text-xs leading-5" id={helpId}>
    Only you can see this name in the token list.
  </span>
</div>

Setting row

<div className="grid grid-cols-[1fr_auto] items-center gap-4 rounded-lg border p-3">
  <Label className="cursor-pointer" htmlFor={id}>
    Two-factor authentication
  </Label>
  <Switch defaultChecked id={id} />
</div>

API Reference

The reference lists the source-owned exports and props that are easy to miss in visual examples. Inherited Base UI props remain available unless the wrapper narrows them.

  • Connect htmlFor to the control id, or wrap the control when the primitive supports that pattern.
  • render may change the underlying element while retaining Label behavior.
  • Use FieldLabel inside Field so disabled and validation context stays synchronized.

Motion

Component motion uses the shared Siteplane motion contract. See the global motion guide for provider setup, tokens and reduced-motion behavior.

  • Label has no animation.
  • Clickable labels use a pointer cursor and activate their connected control.
  • Disabled styling changes color without changing layout.

Accessibility

  • Every visible Label must name exactly one connected control.
  • Controls without visible labels require an explicit accessible name.
  • Mark decorative required asterisks aria-hidden; expose required state on the control itself.
  • Connect invalid state to the control and render a visible FieldError.

Implementation Guidance

  • Do not render visible controls without a connected label or accessible name.
  • Use FieldLabel inside Field and Label for direct control pairings.
  • Preserve pointer, disabled, render, and native label behavior.

On This Page