Components
- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input OTP
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
- New Component
Elements
Charts
Icons
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 fromLabelPrimitive.Root (Radix UI Label).
| Prop | Type | Default | Description |
|---|---|---|---|
htmlFor | string | — | ID of the associated form control |
className | string | — | 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 targetingInstallation
$ npx shadcn add \https://gin-design.vercel.app/label