Label
A styled native label for form controls — htmlFor association, disabled-dimming via peer/group, and a data-required styling hook.
- Status
- Since
0.1.0- Accessibility pattern
- native label
Last updated
Install
Add Label from the VegaStack registry. The CLI verifies the item's integrity hash before writing it.
pnpm dlx shadcn@latest add @vegastack/labelUsage
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" />;Label is a thin wrapper over the native <label>, so every standard attribute
(htmlFor, id, onClick, …) works as expected, and its ref forwards to the
underlying element. Associate it with a control by matching htmlFor to the
control's id, or by wrapping the control as a child.
Examples
Required
Pass required to set a data-required="" hook on the <label>. This renders
no visual asterisk — it is a styling/automation hook only, so the rendered
label below looks identical to a normal one (inspect it to see the attribute).
Enforce requiredness on the control itself (required / aria-required) and
surface it with an inline FieldError on submit, not with a decorative mark.
Layout
Label is inline-flex by default, so it composes into running text and sits beside a control
without breaking the line around itself. Pass layout="block" for the stacked form row, where the
label should own its own full-width line above the input.
// Inline, in a sentence
<p>
Type the word <Label>delete</Label> to confirm.
</p>
// Stacked above a control
<Label layout="block" htmlFor="name">Full name</Label>
<Input id="name" />States
The label dims to 50% opacity (the --opacity-dim token) when the control it
labels is disabled. Place the label after a peer control
(peer-disabled:opacity-(--opacity-dim)) or inside a disabled group
(group-data-[disabled=true]:opacity-(--opacity-dim)) and it reacts
automatically — no extra prop needed. Both dimming paths are shown below.
Playground
Every Label prop, auto-generated from its TypeScript types.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
layout | "block" | "inline" | 'inline' | Box layout. inline composes into running text and beside a control; block takes its own
full-width line above one. |
required | boolean | false | Marks the labelled control as required by setting data-required on the
<label> (a styling/automation hook — no visual asterisk). Enforce
requiredness on the control itself (required) and surface it with an
inline FieldError on submit, not with a decorative mark. |
Data attributes and CSS variables on Label
| Attribute | Values |
|---|---|
data-layout | mirrors a prop or state value |
data-required | "" |
data-slot | "label" |
Accessibility
-
Form labels render at 12px (
text-label-sm): a label is dense metadata ABOUT the control beneath it, not a peer of the 14px value typed into it.text-label(14px) stays for UI labels and navigation. -
Renders a native
<label>— associate it with exactly one control viahtmlFor/idor by wrapping the control, so clicking the label focuses (or toggles) the control and screen readers announce the accessible name. -
select-nonekeeps double-clicking the label from selecting its text instead of activating the control. -
requiredsets a non-visualdata-requiredstyling hook only — it renders no asterisk or other glyph. Mark the controlrequired(oraria-required) so the requirement is conveyed to assistive technology, and surface it on submit with an inlineFieldError. -
Disabled dimming is token-driven (
peer-disabled/group-data-[disabled]) and never relies on color alone to signal state.
| Key | Action |
|---|---|
Click | Focuses (or toggles) the associated control via the label-control association. |
| Contract | States tested |
|---|---|
| Behaviour | default, disabled |
| Accessibility | disabled, labeled, semantic-html |
| Visual | default, disabled |