---
url: "https://vueda.dev/v3/reference/theming/keys/family/controls.md"
title: "controls keys"
---

# controls keys

Source file: `client/lib/theme/vueda-tailwind/controls/index.js`

## Button family meta keys

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [_ButtonBase](/v3/reference/theming/keys/_ButtonBase.md) | primitive | 1 | The shared button shell: inline-flex layout, 2px control radius, sm font-medium type, default 16px icon sizing, focus-visible ring, and the system-wide disabled treatment. Height and horizontal padding are omitted; the leaf picks a tier from `base.css § Control sizing`. |
| [_ButtonDefault](/v3/reference/theming/keys/_ButtonDefault.md) | primitive | 1 | The `--primary` fill keeps the canonical brand blue in both modes with dark `--primary-foreground` labels. Hover and active use opaque white mixes through `--primary-hover` and `--primary-active`. Pair sparingly with neutral pressed-state recipes like [Toggle.root](/v3/reference/theming/keys/Toggle.md#theme-key-Toggle-root) so a CTA and an active toggle do not compete. |
| [_ButtonDestructive](/v3/reference/theming/keys/_ButtonDestructive.md) | primitive | 1 | The `--destructive` fill: solid destructive background in light mode, 60%-mix in dark so the chip stays legible against `--background` at rest, destructive-foreground text, and a destructive-tinted focus outline. Hover and active swap to the `--destructive-hover` / `--destructive-active` lightness steps (darker in light mode, lighter in dark). Reserve for actions that delete user data or are otherwise irreversible; menu / list destructive items use a colour-only recipe. |
| [_ButtonOutline](/v3/reference/theming/keys/_ButtonOutline.md) | primitive | 1 | The neutral-chip recipe: DPR-aware hairline at `--border-strong` that darkens to `--foreground` on hover (a chip that still reads as a control without outweighing the one filled action beside it), `--background` fill, and an `--accent` hover swap with an `--accent-active` pressed step. The hairline paints as an inset shadow rather than a layout border, so outlined buttons match fill-button intrinsic width while using the same chromatic-fringing mitigation as inputs. Hover / active use the mode-aware `--accent` tokens in both light and dark, so the lightness step is identical in either mode; only the *rest* fill differs (dark mode keeps the input-tint convention, `bg-input/30`, so an outlined chip reads input-like at rest while keeping its stronger edge). The earlier dark-mode `bg-input/50` hover topped out near the rest lightness because `--input` is itself dark, leaving the smaller sizes with no perceptible state change. Reused by chip-shaped leaves that want the button shape without a fill, including [FileUpload.trigger](/v3/reference/theming/keys/FileUpload.md#theme-key-FileUpload-trigger) and the calendar prev / next buttons, so the hover and pressed steps reach those surfaces too. |
| [_ButtonSecondary](/v3/reference/theming/keys/_ButtonSecondary.md) | primitive | 1 | The `--secondary` surface fill: solid secondary background, secondary-foreground text. Hover and active swap to the `--secondary-hover` / `--secondary-active` lightness steps (darker in light mode, lighter in dark); the previous `/80` alpha hover was near-invisible because secondary sits almost on the page surface. Use for actions that sit beside a CTA without stealing it; a row of secondary buttons reads as a control cluster rather than a set of competing CTAs. |
| [_ButtonGhost](/v3/reference/theming/keys/_ButtonGhost.md) | primitive | 1 | The transparent-at-rest recipe: no fill or edge until hover, when `--accent` paints the background, with an `--accent-active` pressed step (dark mode: half-strength `accent/50` hover, full `accent` active). Shared by [CalendarCellTrigger.root](/v3/reference/theming/keys/CalendarCellTrigger.md#theme-key-CalendarCellTrigger-root) and [RangeCalendarCellTrigger.root](/v3/reference/theming/keys/RangeCalendarCellTrigger.md#theme-key-RangeCalendarCellTrigger-root) so day buttons in a calendar grid keep one consistent hover and press affordance; dark-mode hover is half-strength accent so the day button does not over-saturate the popover surface. |
| [_ButtonLink](/v3/reference/theming/keys/_ButtonLink.md) | primitive | 1 | The inline-text recipe uses `--primary-text`, a contrast-adjusted blue separate from the primary fill. Hover adds an underline with a 4px offset; active uses `--primary-text-active`. The `link` emphasis of [Button](/v3/reference/theming/keys/Button.md) drops the control height and horizontal padding so the affordance does not break surrounding line metrics. |
| [_ButtonPrimaryOutline](/v3/reference/theming/keys/_ButtonPrimaryOutline.md) | primitive | 1 | The primary outline recipe pairs a DPR-aware `--primary` hairline with readable `--primary-text` over `--background` (dark mode keeps `bg-input/30`). Hover and active add a primary tint (`/10` then `/15`) while the label retains its contrast-adjusted blue. The inset hairline matches filled-button dimensions. |
| [_ButtonDestructiveOutline](/v3/reference/theming/keys/_ButtonDestructiveOutline.md) | primitive | 1 | The destructive neutral-chip recipe: a DPR-aware `--destructive` hairline and `--destructive` text over the `--background` fill (dark mode keeps the outline-family `bg-input/30` rest tint). The inset hairline avoids layout-width drift against fill buttons and uses the same saturated-edge fringing mitigation as inputs. Hover and active wash a low-alpha `--destructive` tint behind the label (`/10` then `/15`) so the chip warms toward danger on interaction without becoming a filled destructive CTA, and focus swaps to the destructive outline. Use for a reversible-but-cautionary action that should not carry the weight of a filled [\_ButtonDestructive](/v3/reference/theming/keys/_ButtonDestructive.md) (a low-emphasis delete in a toolbar or row). |
| [_ButtonPrimaryGhost](/v3/reference/theming/keys/_ButtonPrimaryGhost.md) | primitive | 1 | The transparent-at-rest primary recipe uses `--primary-text` with no fill or edge until hover, when a primary tint paints the background (`/10` hover, `/15` active). The lowest-weight accented affordance, for an emphasized action inside a dense cluster where an outline or fill would be too heavy. |
| [_ButtonDestructiveGhost](/v3/reference/theming/keys/_ButtonDestructiveGhost.md) | primitive | 1 | The transparent-at-rest destructive recipe: `--destructive` text with no fill or edge until hover, when a low-alpha `--destructive` tint paints the background (`/10` hover, `/15` active) and focus swaps to the destructive outline. The lowest-weight destructive affordance, for a cautionary action inside a dense cluster (a row's delete glyph, a menu-adjacent strip) where even an outlined chip would be too heavy. |
| [_ButtonNeutralLink](/v3/reference/theming/keys/_ButtonNeutralLink.md) | primitive | 1 | The neutral inline-text recipe: `--foreground` text with a 4px underline offset that appears on hover only; active eases the label to 70% opacity. Unlike [\_ButtonLink](/v3/reference/theming/keys/_ButtonLink.md), it does not tint the text with `--primary`, so a row of quiet text actions does not spread the earned accent across every secondary affordance. The `link` emphasis of [Button](/v3/reference/theming/keys/Button.md) also drops the control height and horizontal padding. |
| [_ButtonDestructiveLink](/v3/reference/theming/keys/_ButtonDestructiveLink.md) | primitive | 1 | The destructive inline-text recipe: `--destructive` text with a 4px underline offset that appears on hover only; active deepens the label to `--destructive-active`. The text-weight counterpart to [\_ButtonDestructive](/v3/reference/theming/keys/_ButtonDestructive.md), for a cautionary action that must read inline with prose rather than as a control. |

## Button

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [Button](/v3/reference/theming/keys/Button.md) | key | 1 | The pressable root. Composes [\_ButtonBase.root](/v3/reference/theming/keys/_ButtonBase.md#theme-key-_ButtonBase-root) plus the `_Button*` primitive for the resolved (tone, emphasis) cell (see `controls/button/buttonVariant.js`), then layers the per-size height / padding pair from `base.css § Control sizing` (or `size-vueda-control*` for icon-only sizes). The `link` emphasis skips the control-height block and goes inline. The `data-state=cooldown` state (set by the component while a one-shot action is recovering) mutes the label to `--muted-foreground` and suppresses hover so a recently-clicked button reads as "wait" without changing layout. |

## Button group

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [ButtonGroup](/v3/reference/theming/keys/ButtonGroup.md) | key | 1 | The segmented-cluster shell. Strips inner radii between adjacent children so a row (or column when `orientation` is `vertical`) of buttons, inputs, and Select triggers reads as one slab. Outline buttons use DPR-aware inset hairlines rather than layout borders, so adjacent outline buttons overlap by exactly `--vueda-hairline-width` to share one visible seam. Focus z-index promotion keeps the focus ring from being clipped by neighbours. Nested [ButtonGroup](/v3/reference/theming/keys/ButtonGroup.md) children retain an 8px gap. The icon-only-stays-seamless / text-or-mixed-keeps-seams rule is applied by the component, not this slot. |
| [ButtonGroupSeparator](/v3/reference/theming/keys/ButtonGroupSeparator.md) | key | 1 | The explicit divider used inside a [ButtonGroup](/v3/reference/theming/keys/ButtonGroup.md) when the segmented cluster needs a visible split between text segments. Uses the `--input` token so the divider matches the surrounding hairline color in both modes, and stretches to the group's cross-axis. |
| [ButtonGroupText](/v3/reference/theming/keys/ButtonGroupText.md) | key | 1 | The static-label chip used to join readable copy ("of", "to", a unit suffix) into a [ButtonGroup](/v3/reference/theming/keys/ButtonGroup.md). Wears the button shape (2px control radius, hairline edge) but sits on `--muted` so it does not read as pressable; padding picks 16px to match the default button's `px-vueda-control-px` baseline. |

## Toggle

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [Toggle](/v3/reference/theming/keys/Toggle.md) | key | 1 | The on/off button shell. Reads as a Button shape (control radius, `text-sm font-medium`, 16px icon) but the pressed state (`data-state=on`) paints `--accent` instead of `--primary` so a pressed toggle does not compete with a CTA on the same surface. Two variants (default, `outline`) and three size tiers ride the shared `h-vueda-control*` scale; the `outline` variant wears the same `hairline-border-strong` edge, darkening to `hairline-foreground` on hover, as [\_ButtonOutline.root](/v3/reference/theming/keys/_ButtonOutline.md#theme-key-_ButtonOutline-root) (an inset box-shadow, not a layout border, so it DPR-tracks and matches intrinsic width), and `min-w-vueda-control*` keeps a single-icon toggle square. Disabled items use `--disabled-foreground` ink and a `--border` outline; pressed items keep a `--disabled` fill while unpressed items stay transparent. |
| [ToggleGroup](/v3/reference/theming/keys/ToggleGroup.md) | key | 1 | The row layout for a set of [ToggleGroupItem.root](/v3/reference/theming/keys/ToggleGroupItem.md#theme-key-ToggleGroupItem-root) children. The `--gap` custom property is driven by the consumer's `spacing` prop, which lets the same group render as a gapped row or (at `spacing=0`) as a segmented control where child items drop their outer radii and shared borders. The `group/toggle-group` Tailwind group label lets items react to group-level state. |
| [ToggleGroupItem](/v3/reference/theming/keys/ToggleGroupItem.md) | key | 1 | The individual item inside a [ToggleGroup](/v3/reference/theming/keys/ToggleGroup.md). Mirrors the [Toggle.root](/v3/reference/theming/keys/Toggle.md#theme-key-Toggle-root) recipe (same variants, sizes, and accent-pressed treatment) and adds segmented behaviour: when the host group sets `data-spacing=0`, items drop their per-item radius and shadow and re-add them on the first and last child so the cluster reads as one slab. `min-w-0 shrink-0 px-3` overrides the Toggle minimum width so a label-bearing item grows to its content rather than staying square. Disabled items use `--disabled-foreground` ink and a `--border` outline; pressed items keep a `--disabled` fill while unpressed items stay transparent. |

## File upload

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [FileUpload](/v3/reference/theming/keys/FileUpload.md) | key | 3 | The outer container. In inline-trigger mode this is a tight flex column wrapping the picker button plus optional helper text; in `dropzone` mode it grows into a dashed-border target (2px input-coloured dashes, 6 spacing pad, large radius) that highlights with a primary-tinted fill when `dragging`. The `disabled` state dims the whole region and switches the cursor; the inner trigger still picks up its own disabled treatment from [\_ButtonBase.root](/v3/reference/theming/keys/_ButtonBase.md#theme-key-_ButtonBase-root). |

## Text input

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [Input](/v3/reference/theming/keys/Input.md) | key | 1 | The single-line input shell and the reference recipe for the input-shaped family. Carbon-style field edge: a `bg-field` fill on a bottom-only `field-line` at rest, a `hover:bg-field-hover` step, the same bottom-only line recoloured to `--ring` on focus, `--warning` under `data-warning`, and `--destructive` on invalid while the separate focus ring carries the full perimeter, control-height tier from `base.css § Control sizing`, and the cross-cutting `aria-invalid` swap that paints `--destructive` on the border and ring. Read-only drops the fill and softens the line to `--border`, so a read-only field reads as display rather than editable; the file-picker variant (`<input type=file>`) inherits `file:` classes so a bare file input reads as the same chip family as a button. |
| [Textarea](/v3/reference/theming/keys/Textarea.md) | key | 1 | The multi-line counterpart to [Input.root](/v3/reference/theming/keys/Input.md#theme-key-Input-root). Same field fill, bottom `field-line`, recoloured focus and `aria-invalid` line, and read-only recipe; grows vertically via `field-sizing: content` so the field expands with the typed text rather than holding a fixed `min-height`. Horizontal padding moves to `px-3 py-2` (both axes) because a textarea's content box is two-dimensional. |

## Input group

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [InputGroup](/v3/reference/theming/keys/InputGroup.md) | key | 1 | The shell that joins an input (or textarea) with one or more addons (icon, button, kbd, helper line) into a single bordered chip. The group, not its children, owns the hairline and focus ring: child controls strip their own chrome (see [InputGroupInput](/v3/reference/theming/keys/InputGroupInput.md) / [InputGroupTextarea](/v3/reference/theming/keys/InputGroupTextarea.md)) and the group reacts to `focus-visible` on any `[data-slot=input-group-control]` and to `aria-invalid` on any tagged child via `:has(...)` selectors. Inline addons (`align=inline-start` / `inline-end`) stay on a single row at `h-vueda-control`; block addons (`align=block-start` / `block-end`) stack and flip the row to `flex-col` with auto height, so the same shell supports left/right glyphs and top/bottom helper rows. |
| [InputGroupAddon](/v3/reference/theming/keys/InputGroupAddon.md) | key | 1 | The addon slot inside an [InputGroup.root](/v3/reference/theming/keys/InputGroup.md#theme-key-InputGroup-root). `align` picks one of four placements: `inline-start` / `inline-end` for icon, kbd, or button content flush against the input edge, and `block-start` / `block-end` for helper-text rows stacked above or below the input. Negative-margin hooks (`has-[>button]:ml-[-0.45rem]`, `has-[>kbd]:ml-[-0.35rem]`) tighten interior padding when the addon hosts a button or kbd so the addon does not visually balloon. Inherits `--muted-foreground` text so the addon reads as chrome, not as content; dimmed in lockstep with the group when the host carries `data-disabled=true`. |
| [InputGroupInput](/v3/reference/theming/keys/InputGroupInput.md) | key | 1 | The text-input child inside an [InputGroup.root](/v3/reference/theming/keys/InputGroup.md#theme-key-InputGroup-root). Strips its own border, shadow, and focus ring so the surrounding group owns the chrome; flexes to fill the remaining row, and overrides the standalone [Input](/v3/reference/theming/keys/Input.md) dark-mode tint with `dark:bg-transparent` so the group's tint is the only one painted. The important shadow reset suppresses the standalone bottom line and its focus and invalid variants, keeping the group as the only edge in every state. |
| [InputGroupTextarea](/v3/reference/theming/keys/InputGroupTextarea.md) | key | 1 | The textarea child inside an [InputGroup.root](/v3/reference/theming/keys/InputGroup.md#theme-key-InputGroup-root). Same chrome-strip recipe as [InputGroupInput.root](/v3/reference/theming/keys/InputGroupInput.md#theme-key-InputGroupInput-root) plus `resize-none` so the textarea grows with content rather than offering a corner drag handle that would fight the group's shared shell. |
| [InputGroupText](/v3/reference/theming/keys/InputGroupText.md) | key | 1 | The inline-text addon inside an [InputGroup.root](/v3/reference/theming/keys/InputGroup.md#theme-key-InputGroup-root): helper labels, prefix / suffix copy, unit markers. Renders at sm size on `--muted-foreground` with 16px icons so the addon reads as chrome rather than as input content. |
| [InputGroupButton](/v3/reference/theming/keys/InputGroupButton.md) | key | 1 | Pressable addon inside an [InputGroup.root](/v3/reference/theming/keys/InputGroup.md#theme-key-InputGroup-root). Sized smaller than a standalone [Button.root](/v3/reference/theming/keys/Button.md#theme-key-Button-root) (`xs`, `sm`, plus `icon-xs` / `icon-sm`) so the button fits inside the input shell without breaking the row's `h-vueda-control` baseline. Shadow is suppressed because the group already carries `shadow-vueda-control`; an inset button drawing its own shadow would double-paint at the addon edge. The `xs` and `icon-xs` tiers use a tighter `rounded-[calc(var(--radius)-5px)]` so a 24px button reads as a chip inside a 32px shell rather than a miniature slab. |

## Input OTP

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [InputOTP](/v3/reference/theming/keys/InputOTP.md) | key | 1 | The container for character groups and separators. The `group/input-otp` marker lets visible slots read invalid and disabled state from the native input. Each active slot owns its focus ring. Disabled inputs use disabled text colors without fading the container or separator. |
| [InputOTPGroup](/v3/reference/theming/keys/InputOTPGroup.md) | key | 1 | A contiguous run of [InputOTPSlot.root](/v3/reference/theming/keys/InputOTPSlot.md#theme-key-InputOTPSlot-root) cells (e.g. the three digits before and after a `-` in a 3-3 split code). Pure flex row; the visual joining comes from the slots themselves overlapping their hairlines, so a group is just a layout marker that separates one run from the next when a code is split. |
| [InputOTPSlot](/v3/reference/theming/keys/InputOTPSlot.md) | key | 1 | A single character cell. Borders use `--input` at the `border-hairline` width, and every non-first slot pulls left by exactly `--vueda-hairline-width` so adjacent slots overlap one device pixel and read as one painted line rather than doubling at the seam. The active slot promotes `z-10` and swaps to `border-ring` so the run's active position outlines cleanly above its neighbours; `aria-invalid="true"` on the containing native input swaps every slot border and the active focus ring to `--destructive`. The active slot owns the focus ring, including across separated groups. Direct slot-level `aria-invalid` remains supported. First / last children round only their outer corners so the run reads as one chip. When the containing OTP input is disabled, slots use `--disabled` fill, `--disabled-foreground` ink, and `--border` edges with no shadow, including active or invalid slots. |

## Native select

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [NativeSelect](/v3/reference/theming/keys/NativeSelect.md) | key | 1 | The native `<select>` styled to match the VUEDA control shell. Used where a JS-driven [SelectTrigger](/v3/reference/theming/keys/SelectTrigger.md) or [ComboboxTrigger](/v3/reference/theming/keys/ComboboxTrigger.md) would be overkill: short fixed enums on touch devices, environments where native menu UX is preferred. Same control-height, `bg-field` fill, bottom `field-line`, recoloured focus line, and `aria-invalid` shell as [Input.root](/v3/reference/theming/keys/Input.md#theme-key-Input-root), with the shared `hover:bg-field-hover` step. `appearance-none` strips the native chevron and `pr-9` reserves space for the icon the consumer paints. The option surface inside the dropdown is owned by the OS; deep styling lives in the JS-driven pickers. |
| [NativeSelectOptGroup](/v3/reference/theming/keys/NativeSelectOptGroup.md) | key | 1 | The native `<optgroup>` tinted to inherit the popover surface so the system's native dropdown reads as the same surface family as VUEDA's JS-driven pickers. The OS owns layout and the divider between groups; this slot only paints the background. |
| [NativeSelectOption](/v3/reference/theming/keys/NativeSelectOption.md) | key | 1 | The native `<option>` tinted to inherit the popover surface. Per-row layout, highlight, and check indicator are all owned by the OS; for richer option chrome (icons, sub-labels, highlighted-vs-checked distinction) use [SelectItem](/v3/reference/theming/keys/SelectItem.md) or [ComboboxItem](/v3/reference/theming/keys/ComboboxItem.md). |

## Number field

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [NumberField](/v3/reference/theming/keys/NumberField.md) | key | 1 | The outer grid wrapper for a numeric input with optional increment / decrement steppers. Pure layout (`grid gap-1.5`) so a label, the input, and any messaging stack at the standard form rhythm. The visible input chrome lives on [NumberFieldInput.root](/v3/reference/theming/keys/NumberFieldInput.md#theme-key-NumberFieldInput-root); the absolute-positioned steppers are anchored by [NumberFieldContent.root](/v3/reference/theming/keys/NumberFieldContent.md#theme-key-NumberFieldContent-root). |
| [NumberFieldContent](/v3/reference/theming/keys/NumberFieldContent.md) | key | 1 | The inner wrapper that hosts [NumberFieldInput.root](/v3/reference/theming/keys/NumberFieldInput.md#theme-key-NumberFieldInput-root) plus the optional stepper buttons. Reserves horizontal pad on the input (`pl-5` / `pr-5`) only when [NumberFieldDecrement](/v3/reference/theming/keys/NumberFieldDecrement.md) / [NumberFieldIncrement](/v3/reference/theming/keys/NumberFieldIncrement.md) are actually rendered, so a stepperless number field keeps the standard control padding and a stepper-bearing one never crashes a digit string into the glyphs. `relative` is the anchor for the absolute-positioned steppers. |
| [NumberFieldInput](/v3/reference/theming/keys/NumberFieldInput.md) | key | 1 | The numeric `<input>` itself. Same hairline + focus shell as [Input.root](/v3/reference/theming/keys/Input.md#theme-key-Input-root), but renders in mono + tabular numerals and centres the value so digit widths stay stable while a stepper cycles through different-length numbers. Mono is the segment-as-token treatment shared with the date / time fields. |
| [NumberFieldDecrement](/v3/reference/theming/keys/NumberFieldDecrement.md) | key | 1 | The decrement stepper anchored to the left edge of [NumberFieldInput.root](/v3/reference/theming/keys/NumberFieldInput.md#theme-key-NumberFieldInput-root). Absolutely positioned so the stepper overlays the input rather than competing for row width; `disabled:opacity-20` reads as "at the lower bound" — a stronger fade than the standard 50% control-disabled treatment so a temporarily unusable stepper does not look like a fully disabled field. |
| [NumberFieldIncrement](/v3/reference/theming/keys/NumberFieldIncrement.md) | key | 1 | The increment stepper anchored to the right edge of [NumberFieldInput.root](/v3/reference/theming/keys/NumberFieldInput.md#theme-key-NumberFieldInput-root). Mirror of [NumberFieldDecrement.root](/v3/reference/theming/keys/NumberFieldDecrement.md#theme-key-NumberFieldDecrement-root); same overlay positioning and same upper-bound fade. |

## Date / time fields

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [DateField](/v3/reference/theming/keys/DateField.md) | key | 1 | The input-shaped shell hosting the editable date segments. Same hairline + focus + `aria-invalid` recipe as [Input.root](/v3/reference/theming/keys/Input.md#theme-key-Input-root), with the row of [DateFieldInput.root](/v3/reference/theming/keys/DateFieldInput.md#theme-key-DateFieldInput-root) segments laid out as flex items inside; sizes pick the standard `h-vueda-control*` tier from `base.css § Control sizing`. The read-only treatment swaps to `bg-muted/50` so a frozen date field reads as the same surface family as a read-only text input. |
| [DateFieldInput](/v3/reference/theming/keys/DateFieldInput.md) | key | 1 | A single editable date segment (year / month / day). Renders in `--vueda-font-mono` at `font-medium` with `font-feature-settings: 'tnum','zero'` so digit widths stay stable as values change and `0` remains visually distinct from `O`. The focused segment paints `--accent` / `--accent-foreground` (same recipe as a menu-item-highlighted row, since a focused segment is a selection); `caret-transparent` hides the text caret because segments edit via arrow keys rather than free-form typing, and `data-[placeholder]` mutes the segment to `--muted-foreground` while empty. |
| [DateRangeField](/v3/reference/theming/keys/DateRangeField.md) | key | 1 | The input-shell variant that joins a start / end [DateRangeFieldInput.root](/v3/reference/theming/keys/DateRangeFieldInput.md#theme-key-DateRangeFieldInput-root) pair into one chip. See also: [DateField.root](/v3/reference/theming/keys/DateField.md#theme-key-DateField-root) for the shared shell recipe; delta is that the row hosts two segment runs separated by a literal separator glyph rendered by the component rather than a single run. |
| [DateRangeFieldInput](/v3/reference/theming/keys/DateRangeFieldInput.md) | key | 1 | An editable segment inside a [DateRangeField.root](/v3/reference/theming/keys/DateRangeField.md#theme-key-DateRangeField-root). See also: [DateFieldInput.root](/v3/reference/theming/keys/DateFieldInput.md#theme-key-DateFieldInput-root); same mono + tabular + slashed-zero, accent-on-focus, `caret-transparent` recipe applies. |
| [TimeField](/v3/reference/theming/keys/TimeField.md) | key | 1 | The input-shell variant for editable time segments (hour / minute, plus optional second / period). See also: [DateField.root](/v3/reference/theming/keys/DateField.md#theme-key-DateField-root); identical shell and size-tier recipe, only the segment set inside differs. |
| [TimeFieldInput](/v3/reference/theming/keys/TimeFieldInput.md) | key | 1 | An editable segment inside a [TimeField.root](/v3/reference/theming/keys/TimeField.md#theme-key-TimeField-root). See also: [DateFieldInput.root](/v3/reference/theming/keys/DateFieldInput.md#theme-key-DateFieldInput-root); identical recipe. |

## Calendar

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [Calendar](/v3/reference/theming/keys/Calendar.md) | key | 1 | The outer surface that hosts the month grid. Pure 12px padding (`p-3`) and no border or shadow of its own; chrome belongs to the host (a [PopoverContent.root](/v3/reference/theming/keys/PopoverContent.md#theme-key-PopoverContent-root) when used in a date-picker popover, or the surrounding view when embedded inline). No footer either: [CalendarFooter.root](/v3/reference/theming/keys/CalendarFooter.md#theme-key-CalendarFooter-root) is a separate chin attached below by composition, so a footer-free embed renders as a bare grid. |
| [CalendarHeader](/v3/reference/theming/keys/CalendarHeader.md) | key | 1 | The title row above the day grid. Flex-centred so the [CalendarHeading.root](/v3/reference/theming/keys/CalendarHeading.md#theme-key-CalendarHeading-root) sits in the middle of the row, with `px-8` reserving 32px of side padding for the prev / next [CalendarNavButton.root](/v3/reference/theming/keys/CalendarNavButton.md#theme-key-CalendarNavButton-root) pair that the component anchors to the row edges. |
| [CalendarHeading](/v3/reference/theming/keys/CalendarHeading.md) | key | 1 | The month-year title text inside a [CalendarHeader.root](/v3/reference/theming/keys/CalendarHeader.md#theme-key-CalendarHeader-root). Single-line `text-sm font-medium`; sits centred between the prev / next nav buttons. |
| [CalendarNavButton](/v3/reference/theming/keys/CalendarNavButton.md) | key | 1 | The prev / next month button anchored to a [CalendarHeader.root](/v3/reference/theming/keys/CalendarHeader.md#theme-key-CalendarHeader-root). Composes [\_ButtonBase.root](/v3/reference/theming/keys/_ButtonBase.md#theme-key-_ButtonBase-root) plus [\_ButtonOutline.root](/v3/reference/theming/keys/_ButtonOutline.md#theme-key-_ButtonOutline-root) for the neutral chip recipe, then overrides to a square 28×28 transparent chip with `opacity-50` at rest and full opacity on hover so the chrome stays out of the way until the user reaches for it. One theme key serves both directional SFCs (CalendarPrevButton, CalendarNextButton); the [RangeCalendarPrevButton.root](/v3/reference/theming/keys/RangeCalendarPrevButton.md#theme-key-RangeCalendarPrevButton-root) / [RangeCalendarNextButton.root](/v3/reference/theming/keys/RangeCalendarNextButton.md#theme-key-RangeCalendarNextButton-root) pair on the range side stays split. Whether the two sides should converge on one shape is unsettled. |
| [CalendarGrid](/v3/reference/theming/keys/CalendarGrid.md) | key | 1 | The 7-column day grid. `border-collapse` lets adjacent cell borders share one hairline rather than doubling at the seam; `w-full` lets the grid stretch to the [Calendar.root](/v3/reference/theming/keys/Calendar.md#theme-key-Calendar-root) content width so cell sizing falls out of `flex-1` on [CalendarCell.root](/v3/reference/theming/keys/CalendarCell.md#theme-key-CalendarCell-root). |
| [CalendarGridRow](/v3/reference/theming/keys/CalendarGridRow.md) | key | 1 | A single week row inside a [CalendarGrid.root](/v3/reference/theming/keys/CalendarGrid.md#theme-key-CalendarGrid-root). Flex row; cell width comes from `flex-1` on the children, not from a column template. |
| [CalendarHeadCell](/v3/reference/theming/keys/CalendarHeadCell.md) | key | 1 | A weekday-label cell (Mo / Tu / We ...) above the day grid. Width pins to `--vueda-cal-cell` (32px) so labels align under the day-button slots below; renders at 0.8rem on `--muted-foreground` so the header row reads as chrome rather than as a row of day buttons. |
| [CalendarCell](/v3/reference/theming/keys/CalendarCell.md) | key | 1 | A grid slot inside a [CalendarGridRow.root](/v3/reference/theming/keys/CalendarGridRow.md#theme-key-CalendarGridRow-root); the [CalendarCellTrigger.root](/v3/reference/theming/keys/CalendarCellTrigger.md#theme-key-CalendarCellTrigger-root) day button sits inside it. `p-0` so the button owns the inner spacing, `flex-1` distributes width evenly across the row, and `relative` plus `focus-within:z-20` lets a focused day button promote above its neighbours when the focus ring would otherwise be clipped by adjacent cells. |
| [CalendarCellTrigger](/v3/reference/theming/keys/CalendarCellTrigger.md) | key | 1 | The pressable day button inside a [CalendarCell.root](/v3/reference/theming/keys/CalendarCell.md#theme-key-CalendarCell-root). Composes [\_ButtonBase.root](/v3/reference/theming/keys/_ButtonBase.md#theme-key-_ButtonBase-root) plus [\_ButtonGhost.root](/v3/reference/theming/keys/_ButtonGhost.md#theme-key-_ButtonGhost-root) so day buttons share the popover-friendly hover recipe with the rest of the picker chrome. Size pins to `--vueda-cal-day` (30×30) so the button sits inside the 32px [CalendarCell.root](/v3/reference/theming/keys/CalendarCell.md#theme-key-CalendarCell-root) with a 1px breathing margin. Carries the picker's full state matrix: `data-selected` paints `--primary` / `--primary-foreground`, `data-today` (when not selected) paints `--accent`, `data-disabled` and `data-outside-view` mute to `--muted-foreground`, and `data-unavailable` paints `--destructive` plus `line-through`. |
| [CalendarFooter](/v3/reference/theming/keys/CalendarFooter.md) | key | 2 | The optional chin slot below a [Calendar.root](/v3/reference/theming/keys/Calendar.md#theme-key-Calendar-root) or [RangeCalendar.root](/v3/reference/theming/keys/RangeCalendar.md#theme-key-RangeCalendar-root). Flex row with a `border-t` separator and an 8px gap; used by date-picker popovers that need a date-summary line plus an action row (Apply / Clear). Calendar and RangeCalendar themselves stay footer-free so the bare grid can be embedded without chrome it cannot use. |

## Range calendar

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [RangeCalendar](/v3/reference/theming/keys/RangeCalendar.md) | key | 1 | See also: [Calendar.root](/v3/reference/theming/keys/Calendar.md#theme-key-Calendar-root); identical 12px-padded surface, only the grid inside differs (the [RangeCalendarCell.root](/v3/reference/theming/keys/RangeCalendarCell.md#theme-key-RangeCalendarCell-root) carries the range-fill state). |
| [RangeCalendarHeader](/v3/reference/theming/keys/RangeCalendarHeader.md) | key | 1 | The title row above a [RangeCalendar.root](/v3/reference/theming/keys/RangeCalendar.md#theme-key-RangeCalendar-root)'s day grid. See also: [CalendarHeader.root](/v3/reference/theming/keys/CalendarHeader.md#theme-key-CalendarHeader-root); delta is that the prev / next buttons inside ([RangeCalendarPrevButton.root](/v3/reference/theming/keys/RangeCalendarPrevButton.md#theme-key-RangeCalendarPrevButton-root) / [RangeCalendarNextButton.root](/v3/reference/theming/keys/RangeCalendarNextButton.md#theme-key-RangeCalendarNextButton-root)) anchor to the row edges via `position: absolute`, so this header does not reserve `px-8` the way the single-calendar header does. |
| [RangeCalendarHeading](/v3/reference/theming/keys/RangeCalendarHeading.md) | key | 1 | See also: [CalendarHeading.root](/v3/reference/theming/keys/CalendarHeading.md#theme-key-CalendarHeading-root); identical recipe. |
| [RangeCalendarPrevButton](/v3/reference/theming/keys/RangeCalendarPrevButton.md) | key | 1 | The previous-month button anchored to the left edge of a [RangeCalendarHeader.root](/v3/reference/theming/keys/RangeCalendarHeader.md#theme-key-RangeCalendarHeader-root). Composes [\_ButtonBase.root](/v3/reference/theming/keys/_ButtonBase.md#theme-key-_ButtonBase-root) plus [\_ButtonOutline.root](/v3/reference/theming/keys/_ButtonOutline.md#theme-key-_ButtonOutline-root), then absolute-positions itself at `left-1` so the button does not consume row flex while the heading floats centred between the two edges. Same square 28×28 transparent plus 50%-opacity-at-rest treatment as [CalendarNavButton.root](/v3/reference/theming/keys/CalendarNavButton.md#theme-key-CalendarNavButton-root). |
| [RangeCalendarNextButton](/v3/reference/theming/keys/RangeCalendarNextButton.md) | key | 1 | See also: [RangeCalendarPrevButton.root](/v3/reference/theming/keys/RangeCalendarPrevButton.md#theme-key-RangeCalendarPrevButton-root); mirror anchored to the right edge of the header at `right-1`. |
| [RangeCalendarGrid](/v3/reference/theming/keys/RangeCalendarGrid.md) | key | 1 | See also: [CalendarGrid.root](/v3/reference/theming/keys/CalendarGrid.md#theme-key-CalendarGrid-root); identical recipe. |
| [RangeCalendarGridRow](/v3/reference/theming/keys/RangeCalendarGridRow.md) | key | 1 | See also: [CalendarGridRow.root](/v3/reference/theming/keys/CalendarGridRow.md#theme-key-CalendarGridRow-root); identical recipe. |
| [RangeCalendarHeadCell](/v3/reference/theming/keys/RangeCalendarHeadCell.md) | key | 1 | See also: [CalendarHeadCell.root](/v3/reference/theming/keys/CalendarHeadCell.md#theme-key-CalendarHeadCell-root); identical recipe (the class-order difference vs the single-calendar slot is incidental, not a deliberate departure). |
| [RangeCalendarCell](/v3/reference/theming/keys/RangeCalendarCell.md) | key | 1 | A grid slot inside a [RangeCalendarGridRow.root](/v3/reference/theming/keys/RangeCalendarGridRow.md#theme-key-RangeCalendarGridRow-root). Same `p-0` plus `relative` plus `focus-within:z-20` layout shape as [CalendarCell.root](/v3/reference/theming/keys/CalendarCell.md#theme-key-CalendarCell-root), plus the range-fill recipe: `[&:has([data-selected])]:bg-accent` paints `--accent` on the cell (not on the day button) whenever the inner trigger is part of the selected range, so middle cells render as a continuous strip while the `data-selection-start` and `data-selection-end` cells round only their outer corners via the `[&:has([data-selected][data-selection-start])]` / `[&:has([data-selected][data-selection-end])]` variants. Range fill goes on the cell rather than the day button so the run can round cleanly at its endpoints. |
| [RangeCalendarCellTrigger](/v3/reference/theming/keys/RangeCalendarCellTrigger.md) | key | 1 | The pressable day button inside a [RangeCalendarCell.root](/v3/reference/theming/keys/RangeCalendarCell.md#theme-key-RangeCalendarCell-root). See also: [CalendarCellTrigger.root](/v3/reference/theming/keys/CalendarCellTrigger.md#theme-key-CalendarCellTrigger-root); delta is that the single `data-selected` state is replaced by paired `data-selection-start` / `data-selection-end` states that paint `--primary` only at the two endpoints, leaving the middle of the range to read through the `--accent` fill that [RangeCalendarCell.root](/v3/reference/theming/keys/RangeCalendarCell.md#theme-key-RangeCalendarCell-root) paints on its cell. |

## Combobox

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [ComboboxAnchor](/v3/reference/theming/keys/ComboboxAnchor.md) | key | 1 | The positioning anchor for the [ComboboxList.root](/v3/reference/theming/keys/ComboboxList.md#theme-key-ComboboxList-root) popover. Pins to a 200px width by default so a Combobox that anchors to whitespace (rather than the trigger element) still has a sensible reference rectangle; consumers that wrap the trigger in the anchor inherit the trigger's width instead and can ignore this default. Layout-only slot; no chrome of its own. |
| [ComboboxTrigger](/v3/reference/theming/keys/ComboboxTrigger.md) | key | 1 | The pressable surface that opens the [ComboboxList.root](/v3/reference/theming/keys/ComboboxList.md#theme-key-ComboboxList-root). Ships empty today: in-tree consumers (`WidgetCombobox`) supply their own input-shell chrome via `asChild`, so the bare primitive has no usable default. The Combobox-vs-Select differentiator (Combobox reads as a field because the user is about to type) is enforced by consumers, not by this slot. Giving the bare primitive an input-shell default is deferred until the same session settles the multi-select div-trigger pattern, since one API choice covers both. |
| [ComboboxList](/v3/reference/theming/keys/ComboboxList.md) | key | 1 | The floating popover surface that holds the [ComboboxItem.root](/v3/reference/theming/keys/ComboboxItem.md#theme-key-ComboboxItem-root) rows. Reads as a popover: 2px control radius, `--popover` fill, and a hairline edge with popover elevation (`overlay-hairline`), with the standard side-aware enter / exit transforms anchored on `--reka-combobox-content-transform-origin` so the surface scales out of the corner closest to the trigger. Fixed 200px width matches [ComboboxAnchor.root](/v3/reference/theming/keys/ComboboxAnchor.md#theme-key-ComboboxAnchor-root); the inner [ComboboxViewport.root](/v3/reference/theming/keys/ComboboxViewport.md#theme-key-ComboboxViewport-root) owns scrolling. |
| [ComboboxViewport](/v3/reference/theming/keys/ComboboxViewport.md) | key | 1 | The scrollable region inside [ComboboxList.root](/v3/reference/theming/keys/ComboboxList.md#theme-key-ComboboxList-root) that wraps the result groups. Caps at 300px tall before the viewport begins to scroll; `scroll-py-1` keeps a hairline of breathing room above the first and below the last visible row so a focused item never crashes into the viewport edge. |
| [ComboboxInput](/v3/reference/theming/keys/ComboboxInput.md) | key | 1 | The search field at the top of a [ComboboxList.root](/v3/reference/theming/keys/ComboboxList.md#theme-key-ComboboxList-root). Sized to the large control-height tier (`h-vueda-control-lg`) so the input reads as the primary surface inside the popover; renders chrome-free (`bg-transparent`, no border or focus ring) because the surrounding popover already owns the elevation and ring contracts. The Combobox trigger that opens the popover wears the input shell instead. |
| [ComboboxGroup](/v3/reference/theming/keys/ComboboxGroup.md) | key | 2 | A section of related [ComboboxItem.root](/v3/reference/theming/keys/ComboboxItem.md#theme-key-ComboboxItem-root) rows inside [ComboboxList.root](/v3/reference/theming/keys/ComboboxList.md#theme-key-ComboboxList-root). 4px padding (`p-1`) carries the breathing room around the section so consecutive groups read as separate runs even without a [ComboboxSeparator.root](/v3/reference/theming/keys/ComboboxSeparator.md#theme-key-ComboboxSeparator-root) between them; `overflow-hidden` clips a long inner row to the group's box rather than letting it bleed into a neighbour. |
| [ComboboxItem](/v3/reference/theming/keys/ComboboxItem.md) | key | 1 | A single result row inside a [ComboboxGroup.root](/v3/reference/theming/keys/ComboboxGroup.md#theme-key-ComboboxGroup-root). The `data-highlighted` state (set by the picker on keyboard or pointer focus) paints `--accent` / `--accent-foreground`, and the muted leading icon flips to inherit on the same rule so a highlighted row reads as one tinted strip. `data-disabled` halves opacity and drops pointer events; `rounded-sm` keeps the row a chit inside the group's slab. The committed-value `data-state=checked` tint that [SelectItem.root](/v3/reference/theming/keys/SelectItem.md#theme-key-SelectItem-root) carries is not applied here because Combobox commits by closing the popover; the trailing [ComboboxItemIndicator.root](/v3/reference/theming/keys/ComboboxItemIndicator.md#theme-key-ComboboxItemIndicator-root) marks the selection instead. |
| [ComboboxItemIndicator](/v3/reference/theming/keys/ComboboxItemIndicator.md) | key | 1 | The trailing selected-state glyph on a [ComboboxItem.root](/v3/reference/theming/keys/ComboboxItem.md#theme-key-ComboboxItem-root) (typically a check mark). `ml-auto` pushes the indicator to the row's trailing edge; size and colour are inherited from the surrounding row so the indicator picks up the highlight swap without painting its own state. |
| [ComboboxSeparator](/v3/reference/theming/keys/ComboboxSeparator.md) | key | 1 | A 1px horizontal divider between groups inside [ComboboxList.root](/v3/reference/theming/keys/ComboboxList.md#theme-key-ComboboxList-root). Renders as a flat `--border` hairline rather than the DPR-aware `hairline` utility because the separator sits inside a popover that already paints its own border at the same width, so the visual seam never reads as a doubled line. `-mx-1` extends the divider to the popover edge past the group's 4px inner padding. |
| [ComboboxEmpty](/v3/reference/theming/keys/ComboboxEmpty.md) | key | 1 | The zero-result placeholder shown inside [ComboboxList.root](/v3/reference/theming/keys/ComboboxList.md#theme-key-ComboboxList-root) when the search has no matches. Centred sm text inside 24px vertical padding so the empty state reads as a deliberate pause rather than a collapsed popover; consumers supply their own copy. |

## Command

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [Command](/v3/reference/theming/keys/Command.md) | key | 1 | The outer Command surface (a search + categorised result list). 4px card radius rather than the 2px control radius the rest of the picker family wears, because Command is a shell surface, not a slab control. The flex-column layout stacks [CommandInput.root](/v3/reference/theming/keys/CommandInput.md#theme-key-CommandInput-root), [CommandList.root](/v3/reference/theming/keys/CommandList.md#theme-key-CommandList-root), and optional [CommandFooter.root](/v3/reference/theming/keys/CommandFooter.md#theme-key-CommandFooter-root) into one chip, and `overflow-hidden` lets the inner list scroll without escaping the rounded corners. Used inline or hosted inside a [CommandDialog.content](/v3/reference/theming/keys/CommandDialog.md#theme-key-CommandDialog-content). |
| [CommandInput](/v3/reference/theming/keys/CommandInput.md) | key | 2 | The free-text search field at the top of a [Command.root](/v3/reference/theming/keys/Command.md#theme-key-Command-root). Renders chrome-free at `--vueda-cmd-input-height` so the surrounding [CommandInput.wrapper](/v3/reference/theming/keys/CommandInput.md#theme-key-CommandInput-wrapper) owns the row's geometry and the lower hairline; the input itself just contributes placeholder, focus-clear, and the disabled treatment. |
| [CommandList](/v3/reference/theming/keys/CommandList.md) | key | 1 | The scrollable region of [Command.root](/v3/reference/theming/keys/Command.md#theme-key-Command-root) that holds the result groups. See also: [ComboboxViewport.root](/v3/reference/theming/keys/ComboboxViewport.md#theme-key-ComboboxViewport-root); identical 300px cap and `scroll-py-1` recipe so both pickers feel the same when keyboard navigation crosses the viewport edge. |
| [CommandEmpty](/v3/reference/theming/keys/CommandEmpty.md) | key | 1 | The zero-result placeholder shown inside [CommandList.root](/v3/reference/theming/keys/CommandList.md#theme-key-CommandList-root) when the search has no matches. See also: [ComboboxEmpty.root](/v3/reference/theming/keys/ComboboxEmpty.md#theme-key-ComboboxEmpty-root); identical recipe. |
| [CommandGroup](/v3/reference/theming/keys/CommandGroup.md) | key | 2 | A section of related [CommandItem.root](/v3/reference/theming/keys/CommandItem.md#theme-key-CommandItem-root) rows inside [CommandList.root](/v3/reference/theming/keys/CommandList.md#theme-key-CommandList-root). See also: [ComboboxGroup.root](/v3/reference/theming/keys/ComboboxGroup.md#theme-key-ComboboxGroup-root); identical recipe. |
| [CommandItem](/v3/reference/theming/keys/CommandItem.md) | key | 1 | A single result row inside a [CommandGroup.root](/v3/reference/theming/keys/CommandGroup.md#theme-key-CommandGroup-root). See also: [ComboboxItem.root](/v3/reference/theming/keys/ComboboxItem.md#theme-key-ComboboxItem-root); identical highlight + disabled + icon-tint recipe so result rows feel the same across both pickers. Command differs only at the row's trailing edge, where [CommandShortcut.root](/v3/reference/theming/keys/CommandShortcut.md#theme-key-CommandShortcut-root) (rather than [ComboboxItemIndicator.root](/v3/reference/theming/keys/ComboboxItemIndicator.md#theme-key-ComboboxItemIndicator-root)) marks the kbd hint for invoking the action. |
| [CommandSeparator](/v3/reference/theming/keys/CommandSeparator.md) | key | 1 | A 1px horizontal divider between groups inside [CommandList.root](/v3/reference/theming/keys/CommandList.md#theme-key-CommandList-root). See also: [ComboboxSeparator.root](/v3/reference/theming/keys/ComboboxSeparator.md#theme-key-ComboboxSeparator-root); identical recipe. |
| [CommandShortcut](/v3/reference/theming/keys/CommandShortcut.md) | key | 3 | Alignment wrapper for the trailing keyboard hint on a [CommandItem.root](/v3/reference/theming/keys/CommandItem.md#theme-key-CommandItem-root). `ml-auto` pushes the hint flush right while the nested [KbdGroup.root](/v3/reference/theming/keys/KbdGroup.md#theme-key-KbdGroup-root) owns the chord. |
| [CommandFooter](/v3/reference/theming/keys/CommandFooter.md) | key | 3 | The optional chin below [CommandList.root](/v3/reference/theming/keys/CommandList.md#theme-key-CommandList-root). Sits at `--vueda-cmd-footer-height` (32px) on `--muted` with a top hairline, holding keyboard-navigation hints on the leading edge and custom action labels on the trailing edge; supporting-size copy on `--muted-foreground` reads as status rather than primary chrome. |
| [CommandDialog](/v3/reference/theming/keys/CommandDialog.md) | key | 2 | The [DialogContent.root](/v3/reference/theming/keys/DialogContent.md#theme-key-DialogContent-root) pane that hosts a [Command.root](/v3/reference/theming/keys/Command.md#theme-key-Command-root) at modal scale. Drops all padding so Command's own card radius, fill, and inner geometry own the dialog box, and `overflow-hidden` keeps the inner list's scroll edges clipped to the rounded corners. |

## Select

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [SelectTrigger](/v3/reference/theming/keys/SelectTrigger.md) | key | 1 | The pressable surface that opens a [SelectContent.root](/v3/reference/theming/keys/SelectContent.md#theme-key-SelectContent-root). Wears the editable field recipe: a `bg-field` fill on a bottom-only `field-line`, square `rounded-vueda-field` corners, and a `hover:bg-field-hover` step, so a picker that sets a value reads as a field rather than a button. Focus recolours the bottom line to `--ring` and adds the focus ring. Three size tiers ride `h-vueda-control*` plus matching `px-vueda-control-px*`, and `aria-invalid` swaps that line and the focus-ring shadow to destructive. Placeholder text mutes to `--muted-foreground` so an unselected trigger reads as empty rather than as a chosen value. |
| [SelectContent](/v3/reference/theming/keys/SelectContent.md) | key | 2 | The floating popover surface that holds the [SelectItem.root](/v3/reference/theming/keys/SelectItem.md#theme-key-SelectItem-root) options. Reads as a popover (2px radius, a hairline edge with popover elevation via `overlay-hairline`) capped at the viewport-available height that Reka exposes via `--reka-select-content-available-height`; the `popper`-position-only translate nudges (`translate-y-1`, etc.) sit the popover one 4px step off the trigger so the surface does not crash into the chip that opened it. The `item-aligned` legacy mode (the popover aligns itself to the selected item rather than anchoring to the trigger) skips those nudges and shares all other chrome. |
| [SelectItem](/v3/reference/theming/keys/SelectItem.md) | key | 1 | A single option inside a [SelectContent.viewport](/v3/reference/theming/keys/SelectContent.md#theme-key-SelectContent-viewport). Carries the two-track selection state that distinguishes Select from Combobox: the highlighted-but-not-committed option paints `--accent` / `--accent-foreground` on `:focus`, while the committed value (`data-state=checked`) tints with `bg-primary/10` so the chosen option reads as a soft primary band even when another row is highlighted; the indicator icon alone is not a strong enough signal at rest. `pr-8` reserves trailing space for the check indicator; `rounded-sm` keeps the option a chit inside the popover slab. |
| [SelectLabel](/v3/reference/theming/keys/SelectLabel.md) | key | 1 | The section heading inside a [SelectContent.root](/v3/reference/theming/keys/SelectContent.md#theme-key-SelectContent-root). See also: [ComboboxGroup.heading](/v3/reference/theming/keys/ComboboxGroup.md#theme-key-ComboboxGroup-heading); same caps-micro eyebrow on `--muted-foreground` (the rendered class list drops the leading `font-mono`, but Tailwind's default sans / mono cascade leaves the eyebrow visually identical at the micro size). |
| [SelectSeparator](/v3/reference/theming/keys/SelectSeparator.md) | key | 1 | A 1px horizontal divider between sections inside [SelectContent.viewport](/v3/reference/theming/keys/SelectContent.md#theme-key-SelectContent-viewport). See also: [ComboboxSeparator.root](/v3/reference/theming/keys/ComboboxSeparator.md#theme-key-ComboboxSeparator-root); delta is a vertical 4px margin (`my-1`) so the divider breathes against the surrounding 4px viewport padding, plus `pointer-events-none` so the hairline never intercepts a click meant for a neighbouring row. |
| [SelectScrollUpButton](/v3/reference/theming/keys/SelectScrollUpButton.md) | key | 1 | The scroll-up affordance that surfaces at the top of a long [SelectContent.viewport](/v3/reference/theming/keys/SelectContent.md#theme-key-SelectContent-viewport). 4px tall flex centre so the slot reads as a thin handle rather than a button; the consumer paints the chevron glyph inside. Reka shows / hides the slot automatically based on scroll position. |
| [SelectScrollDownButton](/v3/reference/theming/keys/SelectScrollDownButton.md) | key | 1 | See also: [SelectScrollUpButton.root](/v3/reference/theming/keys/SelectScrollUpButton.md#theme-key-SelectScrollUpButton-root); mirror at the bottom of the viewport. |

## Tags input

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [TagsInput](/v3/reference/theming/keys/TagsInput.md) | key | 1 | The outer shell of a multi-value input that captures discrete entries as pill chips. Reads as the input family: `hairline` border, control radius, dark-mode `bg-input/30` tint. Flex-wrap with an 8px gap so committed [TagsInputItem.root](/v3/reference/theming/keys/TagsInputItem.md#theme-key-TagsInputItem-root) chips and the trailing [TagsInputInput.root](/v3/reference/theming/keys/TagsInputInput.md#theme-key-TagsInputInput-root) flow onto new rows as the chip count grows. Focus and `aria-invalid` rings fire on the shell (not the inner input) via `:has(input:focus-visible)` and `:has([data-state=active])` selectors: typing in the field paints the standard focus ring on the shell; focusing a committed chip (`data-state=active`) suppresses the shell ring so the chip's own active outline is the only one visible at a time. |
| [TagsInputInput](/v3/reference/theming/keys/TagsInputInput.md) | key | 1 | The free-text entry field inside a [TagsInput.root](/v3/reference/theming/keys/TagsInput.md#theme-key-TagsInput-root). Sized to `--vueda-chip-height` so pending text shares a baseline with the committed chips beside it; renders chrome-free (transparent fill, no border, no focus ring) because the surrounding shell owns the chip-row contract and fires the focus ring on its own when the input is focused. `flex-1` lets the field absorb the remaining row width inside the wrap so the typing affordance always reaches the trailing edge. |
| [TagsInputItem](/v3/reference/theming/keys/TagsInputItem.md) | key | 1 | An individual committed chip inside a [TagsInput.root](/v3/reference/theming/keys/TagsInput.md#theme-key-TagsInput-root). Pill radius (not the control / card radius the rest of the form family wears) marks the chip as a user-manipulated tag object rather than a slab-radius system badge or a chrome chit. Sized to `--vueda-chip-height` so multiple chips on a row share one baseline. `data-state=active` (set when the chip receives keyboard focus to edit or delete it) paints the standard focus ring on the chip, and the surrounding [TagsInput.root](/v3/reference/theming/keys/TagsInput.md#theme-key-TagsInput-root) suppresses its own ring on the same condition so only one ring paints at a time. |
| [TagsInputItemText](/v3/reference/theming/keys/TagsInputItemText.md) | key | 1 | The text label inside a [TagsInputItem.root](/v3/reference/theming/keys/TagsInputItem.md#theme-key-TagsInputItem-root). 4px / 8px padding on a transparent fill so the label reads as content sitting inside the secondary-tinted chip rather than carrying its own surface; sm size matches the surrounding [TagsInputInput.root](/v3/reference/theming/keys/TagsInputInput.md#theme-key-TagsInputInput-root) so committed and pending text share a tier. |
| [TagsInputItemDelete](/v3/reference/theming/keys/TagsInputItemDelete.md) | key | 1 | The remove (x) button at the trailing edge of a [TagsInputItem.root](/v3/reference/theming/keys/TagsInputItem.md#theme-key-TagsInputItem-root). Transparent fill so the button rides on the chip's secondary surface rather than punching its own swatch; the trailing 4px margin separates the glyph from the chip's pill end so the hit target does not run into the rounded edge. |

## Checkbox

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [Checkbox](/v3/reference/theming/keys/Checkbox.md) | key | 2 | The boolean-chit shell. 24px square at a 4px corner (one step softer than the 2px control radius) so it reads as a chit rather than a miniature slab control. Default state paints a `hairline` edge on the input-tinted surface and carries the standard focus + `aria-invalid` ring contract. In dark mode the rest edge swaps to `--border-strong` (`dark:hairline-border-strong`) so an unchecked box stays visible on hovered list rows, where the opaque `--input` edge would sink into the `bg-accent/50` hover band. Checked and indeterminate states fill with `--primary` and drop the hairline (the `--vueda-hairline-color:transparent` override on the same selectors) so the surface reads as a single solid swatch; `aria-invalid` swaps both the fill and the painted edge to `--destructive`. The `inline-flex` centring and `align-middle` hold the box to a fixed `size-6` square with a stable baseline whether or not it is checked; keep them when overriding this slot, or toggling a checkbox can reflow baseline-aligned parents (for example the card-layout [ObjectsGrid](/v3/reference/theming/keys/ObjectsGrid.md) grid). Disabled controls use `--disabled` fill, `--border` edge, and `--disabled-foreground` indicators at full opacity, including when invalid. |

## Radio group

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [RadioGroup](/v3/reference/theming/keys/RadioGroup.md) | key | 1 | Layout shell for a vertical run of [RadioGroupItem.root](/v3/reference/theming/keys/RadioGroupItem.md#theme-key-RadioGroupItem-root). 12px gap (`gap-3`) so the items breathe at the form-level density; the items, not the group, carry the focus and `aria-invalid` rings, so the group itself is a transparent layout container. Override to `flex` or `grid-flow-col` for a horizontal stack without touching the per-item contract. |
| [RadioGroupItem](/v3/reference/theming/keys/RadioGroupItem.md) | key | 3 | The individual radio chit inside a [RadioGroup.root](/v3/reference/theming/keys/RadioGroup.md#theme-key-RadioGroup-root). 24px circle, paired with the 24px [Checkbox.root](/v3/reference/theming/keys/Checkbox.md#theme-key-Checkbox-root) square so the two single-select families share a row height. `hairline` edge on an input-tinted surface (`dark:bg-input/30`) with the standard focus + `aria-invalid` ring contract; the dark rest edge uses `--border-strong` (parity with [Checkbox.root](/v3/reference/theming/keys/Checkbox.md#theme-key-Checkbox-root)) so the ring stays visible on hovered list rows. Selected state is carried by the inner [RadioGroupItem.dot](/v3/reference/theming/keys/RadioGroupItem.md#theme-key-RadioGroupItem-dot) via `text-primary` on the root (the dot inherits the colour through `bg-current`); `aria-invalid` recolours the dot to `--destructive` the same way. Disabled controls use `--disabled` fill, `--border` edge, and `--disabled-foreground` indicators at full opacity, including when invalid. |

## Switch

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [Switch](/v3/reference/theming/keys/Switch.md) | key | 2 | The track of the sliding boolean control. Tighter than the iOS-canonical size: 18.4px tall (`h-[1.15rem]`), 32px wide (`w-8`), so the switch sits at the form density tier rather than ballooning above the 32px control row. Pill radius; checked fills `--primary`, unchecked fills `--input` (with a darker `--input/80` tint in dark mode for visibility against the deeper canvas). Focus paints `--ring` directly on the otherwise-transparent 1px border and adds a 2px outline at 2px offset, rather than the canon `focus-ring` utility, because the track + thumb composition needs the ring to wrap the entire pill without the inset shadow variant interfering with the thumb's transform. Disabled tracks use `--disabled` at full opacity and drop the shadow. |

## Slider

| Component | Kind | Slots | Description |
| --- | --- | --- | --- |
| [Slider](/v3/reference/theming/keys/Slider.md) | key | 4 | The continuous-value control surface. Flex row by default; `data-[orientation=vertical]` flips to flex column and applies a 176px (`min-h-44`) minimum height so a vertical slider has enough travel to be precise. `touch-none` and `select-none` so dragging the [Slider.thumb](/v3/reference/theming/keys/Slider.md#theme-key-Slider-thumb) does not scroll the page or initiate a text selection. Disabled colors live on the track, range, and thumbs at full opacity; Reka blocks value changes and removes disabled thumbs from keyboard navigation. |
