Label
Accessible, configurable labels for form controls and supporting field context.
Label renders an accessible HTML <label> with a consistent Mosmox UI treatment. It associates text with a form control through htmlFor and can also display required/optional markers, supporting text, validation errors, icons, semantic tones, and responsive text handling.
Basic usage
import { Input, Label } from '@mosmox/ui';
<Label htmlFor="workspace-name">Workspace name</Label>
<Input id="workspace-name" />When the label wraps a control, htmlFor is optional. For separate controls, use the same htmlFor value as the input's id.
Required and optional fields
Use required to render the required indicator. The component does not automatically add the native required attribute to the associated input; set that on the input itself. Use optional for non-required fields and customize its text with optionalLabel.
<Label htmlFor="email" required>Email address</Label>
<Input id="email" required />
<Label htmlFor="nickname" optional optionalLabel="Optional">Nickname</Label>
<Input id="nickname" />Required and optional markers are not exposed as a duplicate accessible name. The input's own required attribute remains the source of form semantics.
Description and validation
description renders supporting text below the label. error replaces the description and uses the danger tone. The label itself does not add aria-describedby to the input because the input may be controlled independently; connect the same text IDs to the input when your field composition requires explicit announcement.
<Label htmlFor="project" description="Use a short name your team can recognize.">Project name</Label>
<Input id="project" />
<Label htmlFor="slug" required error="This project name is already in use.">Project name</Label>
<Input id="slug" aria-invalid="true" />Sizes, tones, and weight
Available sizes are xs, sm, default, and lg. tone supports default, muted, danger, success, and warning. weight supports normal, medium, and semibold.
<Label size="xs" weight="normal">Extra small</Label>
<Label size="sm" tone="muted">Small helper label</Label>
<Label size="default" weight="medium">Default</Label>
<Label size="lg" weight="semibold">Large heading label</Label>
<Label tone="success">Saved field</Label>
<Label tone="warning">Review field</Label>
<Label tone="danger">Invalid field</Label>Icons and long labels
leadingIcon accepts any React node and is decorative. truncate keeps the text on one line and adds an ellipsis when the available width is limited.
import { Sparkle } from '@mosmox-ui/icons';
<Label leadingIcon={<Sparkle size={16} />} optional>AI summary</Label>
<Label truncate description="The supporting text remains visible below.">
A very long configuration label that may not fit in the available space
</Label>Disabled and visually hidden labels
disabled applies the disabled visual treatment and communicates that the associated control is unavailable. It does not set the input's disabled attribute; set that on the input as well.
visuallyHidden means “visually hidden”, not “removed”. The label remains in the DOM, keeps its native relationship with the control, and can still be read by screen readers. CSS clips it to a 1px region and removes it from normal layout, so it does not create a visible gap or push the next row down.
Use it when the purpose of a control is clear from an icon or compact layout but an accessible name is still required. It is especially useful for search fields with only a search icon, icon-only buttons, compact toolbar controls, and responsive layouts where a visible label is intentionally omitted.
Do not use it to hide important instructions from sighted users, and do not use it as a replacement for visible validation or help text. Give it meaningful text and connect it to the control with matching htmlFor and id values. The Label component itself does not make the associated input required or disabled.
<Label htmlFor="locked" disabled>Locked value</Label>
<Input id="locked" disabled />
<Label htmlFor="search" visuallyHidden>Search</Label>
<Input id="search" placeholder="Search" />In the example above, a sighted user sees only the input. A screen-reader user receives the accessible name “Search”. If the label appears to leave a gap, the cause is outside the visuallyHidden style—normally a parent layout or spacing rule. The component’s hidden style uses clipping, absolute positioning, height: 1px, width: 1px, and negative margin specifically to avoid occupying layout space.
API Reference
| Property | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Visible label content. |
htmlFor | string | — | ID of the associated form control. |
description | ReactNode | — | Supporting content below the label. |
error | ReactNode | — | Error content; replaces description and uses danger styling. |
required | boolean | false | Show the required indicator. Does not set input validation. |
requiredIndicator | ReactNode | '*' | Custom required marker. |
optional | boolean | false | Show the optional marker. Ignored visually when required is true. |
optionalLabel | ReactNode | '(optional)' | Custom optional marker. |
leadingIcon | ReactNode | — | Decorative content before the label. |
size | 'xs' | 'sm' | 'default' | 'lg' | 'default' | Typography and line-height preset. |
tone | 'default' | 'muted' | 'danger' | 'success' | 'warning' | 'default' | Semantic text color. |
weight | 'normal' | 'medium' | 'semibold' | 'medium' | Label font weight. |
truncate | boolean | false | Truncate long label text with an ellipsis. |
disabled | boolean | false | Apply disabled styling and cursor. |
visuallyHidden | boolean | false | Visually hide the label while keeping it available to assistive technology. |
className | string | — | Additional class on the label element. |
The component also accepts native LabelHTMLAttributes<HTMLLabelElement> props, including id, onClick, onMouseEnter, style, title, aria-*, and data attributes.
Accessibility and theme tokens
The component uses a native <label> element. htmlFor creates the relationship with the associated control, while visuallyHidden preserves that relationship when the visible label is unnecessary. Icons and required markers are decorative. Use the input's required, disabled, aria-invalid, and aria-describedby props to communicate control state to assistive technology.
Shared theme values can be overridden through ConfigProvider. Component-only layout and visually-hidden rules live in Label.css.
| Token | Purpose |
|---|---|
--mm-color-text | Default label text. |
--mm-color-muted-text | Muted tone and supporting text. |
--mm-color-danger | Required marker. |
--mm-color-danger-text | Error and danger tone. |
--mm-color-success | Success tone. |
--mm-color-warning-text | Warning tone. |
--mm-color-placeholder | Disabled label text. |
--mm-color-control-icon | Leading icon. |
--mm-font-family-sans | Label typography. |
--mm-font-weight-normal | Normal text weight. |
--mm-font-weight-medium | Default and required marker weight. |
--mm-space-control-gap | Spacing between icon, text, and marker. |
For a live implementation of every Label mode, see the Label component showcase.