# Label

**Maturity:** experimental

Pair a leading icon with a title so the two read as one unit — the "gear + Settings" row in a sidebar, the "trash + Delete" row in a context menu, the "star + Favorites" tab.

## Import

```tsx
import { Label } from "@liquidify/react/label"
```

## Props

- `as`: `TextElement | undefined`; default ``"span"``. The HTML element the title's {@link Text} renders as, so the type carries the right semantics (SwiftUI has no analogue — a web affordance). Only applies when the title is wrapped (a `string | number`).
- `className`: `string | undefined`. Optional additional CSS class merged into the glass surface class. The supported per-instance customisation seam: override any `--lq-*` custom property from this class's CSS — the token cascade the engine reads (ADR-0004). No raw inline style is involved, so this stays ADR-0003 clean.
- `icon`: `ReactNode`. The leading icon (SwiftUI `systemImage:` / `icon:`). Decorative (`aria-hidden`) — the title carries the accessible name. Omit for a title-only label; ignored when {@link LabelProps.variant} is `"titleOnly"`.
- `labelProps`: `SharedLabelProps | undefined`; default ``undefined``. Per-instance typography override for the title `Text` (ADR-0028, charter §2 — the catalog-wide typography seam name), spread last so an explicit consumer value wins over the component default.
- `ref`: `Ref<HTMLSpanElement> | undefined`. Forwarded ref to the rendered element — the component's native root (or the merged child element on a component that opts into {@link SlottableProps}). Generic over `E` (charter `docs/api-conventions.md` §4 rule 1, default `HTMLElement`) so a component with a polymorphic root (Link's navigation / action mode union, Text's `as`) can instantiate the concrete element per variant instead of leaving every consumer with a widened `Ref<HTMLElement>`. A component that does not narrow simply inherits the `HTMLElement` default — source-compatible with every pre-existing non-generic `extends ControlProps`.
- `title`: `ReactNode` (required). The title (SwiftUI `_:` / `title:`) — the accessible name, always present. A `string | number` renders through the `TextLabel` guard into an internal `Text`; any other `ReactNode` passes through unwrapped so the caller keeps ownership of its typography.
- `variant`: `LabelVariant | undefined`; default ``"titleAndIcon"``. Which of the pairing to render (SwiftUI `.labelStyle(_:)`). `"iconOnly"` keeps the title in the DOM (visually hidden) so the accessible name survives.

## SwiftUI mapping

- ``init(_ titleKey:, systemImage name:)` / `init<S>(_ title:, systemImage name:)`` → ``<Label title="Settings" icon={<Icon name="gear" />} />`` (renamed): The two SF-Symbol convenience inits collapse to one `title` + one `icon` prop; `icon` accepts any `ReactNode` (not a name string) so the caller supplies a rendered `Icon`/custom glyph rather than a symbol-name lookup.
- ``init(_ titleKey:, image name:)` / `init<S>(_ title:, image name:)`` → `same `<Label title icon />` shape` (direct): Asset-catalog-image and SF-Symbol convenience inits are not distinguished in React — both are "pass a rendered icon node," so they map onto the same `icon` prop rather than two.
- ``init(@ViewBuilder title:, @ViewBuilder icon:)`` → ``title`/`icon` accept arbitrary `ReactNode`` (direct): The fully-custom ViewBuilder init is not a separate React overload — `title: ReactNode` and `icon?: ReactNode` already accept any element, covering this case without a second prop shape.
- ``init(_ configuration: LabelStyleConfiguration)`` → `— (Out of scope)` (direct): Style-plumbing internal, not app-facing; no React equivalent is exposed.
- ``.labelStyle(_:)` + `.automatic`/`.titleAndIcon`/`.iconOnly`/`.titleOnly`` → ``variant?: "titleAndIcon" | "iconOnly" | "titleOnly"`` (renamed): A style *modifier* becomes one `variant` prop, never a fan of booleans (`showIcon`/`showTitle`). `.automatic` collapses into `"titleAndIcon"` (the default) since every reference use of `.automatic` resolves to showing both.
- `*(no title-only single-argument `Label(_:)` exists in SwiftUI)*` → ``variant="titleOnly"` (title always required as a separate prop)` (direct): SwiftUI has no bare-title initialiser (`tmp/refs/label.md` §Initialisers note); this component preserves that shape — `title` is a required prop regardless of `variant`, and `"titleOnly"` is a *presentation* choice, not a different constructor.
- `*(no analogue — web-only)*` → ``as?: TextElement`, default `"span"`` (web-only): The HTML element the title's `Text` renders as (`span`/`div`/`p`/`b`/`strong`/`i`/`em`/`pre`/`code`/`sup`/`sub`) — a semantic-HTML affordance SwiftUI has no need for (it has no DOM). Applies only when the title is a `string`/`number` wrapped by `TextLabel`.
- `*(no analogue — web-only, ADR-0028/charter §2)*` → ``labelProps?: LabelProps["labelProps"]` (`Pick<TextProps, "variant" | "weight" | "color" | "tint" | "tracking" | "transform" | "italic" | "lineHeight" | "wrap">` — the shared `shared/text-label` Text seam)` (web-only): Per-instance typography override for the title, spread last so an explicit value wins over the component default (`variant="body"`, `color="primary"`). Named `labelProps` (not `titleProps`) to match the catalog-wide seam name (charter §2); no public `LabelTextProps` alias — the shape is reachable via `LabelProps["labelProps"]`.
