ProductBrand
Join us
Foundations
  • Introduction
  • Colors
  • Typography
  • Icons
  • Illustrations
  • Logos
  • Shadows
Components
  • Accordion
  • Alert Dialog
  • Avatar
  • Badge
  • Button
  • Calendar
  • Card
  • Chart
  • Checkbox
  • Collapsible
  • Combobox
  • Context Menu
  • Date Picker
  • Dialog
  • Drawer
  • Dropdown Menu
  • Fluid Avatar
  • Hover Scroll Text
  • Input
  • Kbd
  • Popover
  • Progress Bar
  • Radio Group
  • Scroll Area
  • Select
  • Selectors
  • Separator
  • Separator Dot
  • Shimmer Text
  • Skeleton
  • Slider
  • Switch
  • Tabs
  • Textarea
  • Toast
  • Tooltip
Compositions
  • Empty State
  • File Attachment
  • Floating Bar
  • Input Banner
  • Markdown Editor
  • Media Controls
  • Product Feature Banner
  • Panels
  • Sidebar
  • Reasoning Trace
  • Pagination
  • Data Table
  • Breadcrumb
  • Thread Outline
Inline
  • Overview
  • Stat Tile
  • Metric Row
  • Comparison Table
  • Chart Card
  • Trend Tile
  • Cite
  • Custom
  • Agent skill

Label

Labels name a form control and move focus to it when clicked. Reach for Label only when the control is not inside a Form field, since FormLabel wraps this same component and wires htmlFor and the error state for you.

Import

tsx
import { Label } from "@rogo-technologies/ui/label";

Examples

With an input

Beside a control

Wrapping the control

Disabled control

The disabled styling is driven by the sibling control, not by a prop: the label dims when it follows an element marked peer that is :disabled. Order matters: Tailwind's peer-* only looks at preceding siblings, so put the control first in the DOM if you want that pairing.

Props

Label takes every prop a <label> takes; there are no variants.

PropTypeNotes
htmlForstringThe id of the control being named. Effectively required.
classNamestringMerged with cn().
refRef<HTMLLabelElement>Forwarded.
…restComponentPropsWithoutRef<label>Passed straight through, including your own onMouseDown.

Notes

This is a plain <label> rather than a Base UI wrapper on purpose: Base UI's label only works inside a Field.Root, and the Form layer here deliberately doesn't use Field, since FormField owns the id and error wiring instead.

It adds exactly one behavior over a bare <label>: double-clicking calls preventDefault() so the browser selects nothing instead of highlighting the surrounding text, which is what you want when a user double-clicks a label to get at the field. Your own onMouseDown runs first and can opt out by calling preventDefault() itself.

That guard steps aside when the double-click started inside a nested button, input, select, or textarea, so a label that wraps its control still lets the user select a word in it.

Guidelines

  • Inside a form field, use FormLabel. It renders this component with htmlFor already pointed at the control and turns destructive when the field has an error.
  • Give every control a real label, not placeholder text, since placeholders vanish on input and are skipped by some screen readers.
  • htmlFor needs the id to reach a real element. Base UI's Checkbox and Switch put it on their hidden <input>, so labelling those works. A composite whose root renders no DOM (Select, DropdownMenu) swallows the id instead, and so does any custom component that doesn't forward id to its own DOM node. There htmlFor silently points at nothing: name the control with aria-label, or give the label an id and point the control at it with aria-labelledby.

Design at Rogo

We’re redesigning an entire industry. Come design it with us.

See open roles

Design at Rogo

  • How we workThe mission of design at Rogo, and the open roles
  • About RogoThe company and the product