

<Preview name="LabelHeroExample" />

## Overview [#overview]

The **Label** component provides accessible, semantic labeling for form controls, automatically associating with form elements through the `htmlFor` prop to improve usability and screen reader support. Built on Radix UI, it features customizable sizes, orientation options, and flexible styling powered by class-variance-authority.

## Usage [#usage]

```tsx
import { Label } from "@tilt-legal/cubitt-components/primitives";
```

```tsx
<Label htmlFor="email">Your email address</Label>
```

## Examples [#examples]

### With input [#with-input]

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="LabelWithInputExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Label, LabelDescription, Input } from "@tilt-legal/cubitt-components/primitives";

    <Label htmlFor="email" orientation="vertical" className="w-full max-w-sm">
      <span>Email</span>
      <LabelDescription>We’ll never share your email.</LabelDescription>
      <Input type="email" id="email" placeholder="Enter your email" />
    </Label>;
    ```
  </Tab>
</Tabs>

### With switch [#with-switch]

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="LabelWithSwitchExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Label, Switch } from "@tilt-legal/cubitt-components/primitives";

    <div className="flex items-center gap-2">
      <Switch id="notifications" />
      <Label htmlFor="notifications">Enable notifications</Label>
    </div>;
    ```
  </Tab>
</Tabs>

### Sizes [#sizes]

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="LabelSizesExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Label, Checkbox } from "@tilt-legal/cubitt-components/primitives";

    <div className="flex flex-col items-center justify-center gap-4">
      <Label orientation="horizontal" size="sm">
        <Checkbox defaultChecked size="sm" />
        Accept terms and conditions
      </Label>
      <Label orientation="horizontal">
        <Checkbox defaultChecked />
        Accept terms and conditions
      </Label>
      <Label orientation="horizontal" size="lg">
        <Checkbox defaultChecked size="lg" />
        Accept terms and conditions
      </Label>
    </div>;
    ```
  </Tab>
</Tabs>

### Orientations [#orientations]

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="LabelOrientationsExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Label, Input, Checkbox } from "@tilt-legal/cubitt-components/primitives";

    // Vertical orientation (default)
     <Label orientation="vertical">
      <span>Vertical orientation</span>
      <LabelDescription>Optional helper text</LabelDescription>
    </Label>

    // Horizontal orientation
    <Label orientation="horizontal">
      <Checkbox />
      Horizontal orientation
    </Label>
    ```
  </Tab>
</Tabs>

### With Select [#with-select]

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="LabelWithSelectExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      Label,
      Select,
      SelectContent,
      SelectItem,
      SelectTrigger,
      SelectValue,
    } from "@tilt-legal/cubitt-components/primitives";

    const countryItems = [
      { label: "United States", value: "us" },
      { label: "Canada", value: "ca" },
      { label: "United Kingdom", value: "uk" },
    ];

    <Label htmlFor="country" className="w-full max-w-xs">
      Country
      <Select items={countryItems}>
        <SelectTrigger id="country">
          <SelectValue placeholder="Select a country" />
        </SelectTrigger>
        <SelectContent>
          {countryItems.map((item) => (
            <SelectItem key={item.value} value={item.value}>
              {item.label}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
    </Label>;
    ```
  </Tab>
</Tabs>

### With Textarea [#with-textarea]

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="LabelWithTextareaExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Label, Textarea } from "@tilt-legal/cubitt-components/primitives";

    <Label htmlFor="message" className="w-full max-w-xs">
      Message
      <Textarea id="message" placeholder="Type your message here..." />
    </Label>;
    ```
  </Tab>
</Tabs>

## Props [#props]

### Label [#label]

| Prop          | Type                                           | Description                                              |
| ------------- | ---------------------------------------------- | -------------------------------------------------------- |
| `htmlFor`     | `string`                                       | The id of the form control this label is associated with |
| `size`        | `"xs" \| "sm" \| "default" \| "lg"`            | The size of the label text and spacing                   |
| `orientation` | `"vertical" \| "horizontal"`                   | Layout direction for label content                       |
| `className`   | `string`                                       | Additional CSS classes to apply to the label             |
| `children`    | `React.ReactNode`                              | The content of the label                                 |
| `...props`    | `React.ComponentProps<typeof RadixLabel.Root>` | All other Radix label props                              |

### LabelDescription [#labeldescription]

Size-aware helper text rendered under the main label.

| Prop        | Type                                | Description                           |
| ----------- | ----------------------------------- | ------------------------------------- |
| `size`      | `"xs" \| "sm" \| "default" \| "lg"` | Matches the parent label/control size |
| `className` | `string`                            | Additional CSS classes                |
| `children`  | `React.ReactNode`                   | Description content                   |

## Design Guidelines [#design-guidelines]

### Accessibility and association [#accessibility-and-association]

* **Always associate labels with form controls** using the `htmlFor` prop that matches the control's `id`
* **Use descriptive text** that clearly explains what the associated control is for
* **Avoid placeholder-only forms** - labels should always be visible, not just placeholder text
* **Use sentence case** rather than title case for better readability

### Layout and positioning [#layout-and-positioning]

* **Use vertical orientation** for traditional form fields (inputs, selects, textareas) to improve scanability
* **Use horizontal orientation** for checkboxes, radio buttons, and switches to maintain natural reading flow
* **Use consistent spacing** between labels and their associated controls - the component handles appropriate gap sizes automatically
* **Align labels left** for better readability in forms

### Sizing [#sizing]

* **Use consistent sizes** throughout your form for visual hierarchy
* **Match label size** with the associated form control size when possible
* **Use smaller sizes (xs, sm)** for compact forms or secondary information
* **Use larger sizes (lg)** for prominent form fields or headings

### Best practices [#best-practices]

* **Prefer `htmlFor` association** over wrapping form controls when possible for cleaner markup
* **Use wrapping pattern** with orientation prop when you need the label to contain multiple elements
* **Maintain semantic meaning** - labels should always describe the purpose of their associated control
