New

Label

A composable, size-aware label with a semantic `<label>` element and an optional compound block for title, description, icon, required/optional markers, badge, info tooltip, and counter.

Component label-demo not found in registry.

Installation

pnpm dlx createui@latest add label

Usage

Label is the semantic <label> element — use it directly for simple one-line labels.

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

It also accepts inline slots in the title row (icon, required/optional marker, badge, info tooltip):

<Label htmlFor="email">
  <LabelIcon>
    <MailIcon />
  </LabelIcon>
  Email
  <LabelRequired />
</Label>

For richer layouts that need a description and/or a right-aligned counter, wrap everything in LabelBlock:

import {
  Label,
  LabelBadgeSlot,
  LabelBlock,
  LabelCount,
  LabelDescription,
  LabelIcon,
  LabelInfoSlot,
  LabelMain,
  LabelRequired,
} from "@/components/ui/label"
 
;<LabelBlock size="xs">
  <LabelMain>
    <Label htmlFor="email">
      <LabelIcon>
        <MailIcon />
      </LabelIcon>
      Email
      <LabelRequired />
      <LabelBadgeSlot>
        <Badge size="xs">NEW</Badge>
      </LabelBadgeSlot>
      <LabelInfoSlot>
        <InfoTooltip variant="inverse" size="sm">
          We never share your email.
        </InfoTooltip>
      </LabelInfoSlot>
    </Label>
    <LabelDescription>
      Description or any kind of additional text.
    </LabelDescription>
  </LabelMain>
  <LabelCount>0/300</LabelCount>
</LabelBlock>

Sizes

LabelBlock exposes a size variant (xs | sm | md | lg) that cascades to every sub-component via data-size and the group/label selector. Pass size on a sub-component to override for that child. Gaps (root gap-3, column gap-1, title row gap-1) stay constant; only typography and icon sizes scale.

sizetitle textdescription texticonbadge sizeinfo tooltip size
xstext-ui-smtext-ui-smsize-4smsm
smtext-ui-mdtext-ui-mdsize-5mdmd
mdtext-ui-lgtext-ui-lgsize-6mdmd
lgtext-ui-xltext-ui-lgsize-6lglg

Label in Field

Inside forms, use the Field component — it provides size context, invalid/disabled propagation, and a FieldLabel that renders a semantic <label> wired to the control.

<Field>
  <FieldLabel htmlFor="email">Email</FieldLabel>
  <Input id="email" />
  <FieldDescription>We&apos;ll never share your email.</FieldDescription>
</Field>

Accessibility

  • Label renders a semantic <label> only when htmlFor is set; without it, it falls back to a <span> with no label semantics. Always pass htmlFor (or use the Field component) when pairing a label with a form control.
  • LabelIcon is marked aria-hidden="true"; the meaning must be carried by the title text.
  • LabelRequired is decorative (aria-hidden="true"). Mirror the requirement on the input itself with required and/or aria-required="true".
  • LabelDescription renders a plain <p> and is not auto-wired. Outside Field, give it an id and reference it from the input's aria-describedby:
<LabelBlock>
  <LabelMain>
    <Label htmlFor="email">Email</Label>
    <LabelDescription id="email-desc">
      We&apos;ll never share your email.
    </LabelDescription>
  </LabelMain>
</LabelBlock>
<input id="email" aria-describedby="email-desc" />

Inside Field, prefer FieldDescription / FieldError which handle this for you.

API Reference

Label

The semantic <label> element (Radix Label.Root) when htmlFor is set, otherwise a <span>. Hosts icon, text, required, optional, badge slot, and info tooltip slot inline.

PropTypeDefault
size"xs" | "sm" | "md" | "lg"context size
htmlForstring
classNamestring

LabelBlock

Compound root <div> laid out as a row (flex items-end). Provides size to children via data-size and the group/label selector. Use when the label needs a description and/or a right-aligned LabelCount.

PropTypeDefault
size"xs" | "sm" | "md" | "lg""sm"
asChildbooleanfalse
classNamestring

LabelMain

Left column (flex-1 flex-col) that holds Label and LabelDescription. Required when using LabelCount.

LabelIcon

Icon slot (<span>) for leading glyphs. Scales to match size.

LabelRequired

Renders the required marker (default *) in text-primary-base.

LabelOptional

Renders the optional hint (default (Optional)) in text-placeholder.

LabelDescription

Helper <p> below the title in text-placeholder.

LabelBadgeSlot

Inline grouping slot (inline-flex gap-1) for one or more Badge components inside the title row. To right-align, pass className="ml-auto".

LabelInfoSlot

Inline slot for an InfoTooltip trigger, sitting after LabelBadgeSlot in the title row.

LabelCount

Right-side counter (e.g. 0/300) rendered next to LabelMain in text-placeholder. Pass any text as children.