Noctis

Toggle

A two-state button that is either off or pressed. Every variant is quiet when off and fills only when pressed — ghost neutral, accent the indigo accent, primary the bold primary. Its variants and xslg sizes mirror Button, so the two action controls feel identical under the finger.

Basic

A standalone toggle flips between off and pressed on click or with the keyboard, announcing its state through aria-pressed. Drive it with pressed + onPressedChange, or let it own its state with defaultPressed.

Variants

Four looks, named to match Button — each quiet when off, each lighting a different fill when pressed. ghost (the default, for dense toolbars) fills neutral; accent fills the indigo accent for a prominent, signalling on/off; primary fills the bold primary; outline carries a resting border so a single toggle reads as a control on bare ground, then fills primary when pressed.

Sizes

Four heights — xs, sm, md, and lg — sharing the control type and spacing rhythm with Button. Reach for xs in a dense toolbar; keep sm as the floor for touch targets.

Single-select group

Without attached, ToggleGroup is a separated row sharing its variant and size. By default it is single-select — pressing one releases the others. Each toggle takes a value; the group's value is the array of pressed values.

Multiple-select group

Set multiple to let several toggles be pressed at once — the pattern for independent formatting controls like bold, italic, and underline.

Select-all (mixed)

A composite "select all" toggle that drives several children reads as mixed when only some are pressed — a half-state fill between rest and pressed. Set aria-pressed="mixed" on that toggle yourself; it is a documented pattern, not a prop. Never swap the toggle's label between states.

Icon-only toggles

Square a toggle with iconOnly for a single glyph, and always give it an aria-label — there is no visible text to name it. For sighted discoverability, pair it with a Tooltip so its purpose is revealed on hover and focus. Don't mix icon-only and text toggles within one group, and don't change a toggle's icon between pressed states (that's an action button, not a toggle).

Keyboard

A standalone toggle is a button; a group adds roving arrow-key navigation between its toggles.

KeyAction
Space / EnterToggle the focused button's pressed state.
Arrow Right / Arrow LeftMove focus to the next / previous toggle in a horizontal group. In RTL the directions mirror.
Arrow Down / Arrow UpMove focus to the next / previous toggle in a vertical group.
Home / EndMove focus to the first / last toggle in a group.
TabMove focus into and out of the group (the group is a single tab stop).

Accessibility

  • Pressed state — each toggle is a native <button> carrying aria-pressed; Base UI keeps it in sync. Space and Enter activate it.
  • Group role — a ToggleGroup becomes a role="toolbar" once it holds three or more toggles, per the APG, and stays role="group" below that. A toolbar requires an aria-label (or aria-labelledby) — an unlabeled one is an axe finding. You can override the computed role by passing your own.
  • Orientation — set orientation="vertical" and the arrow keys and aria-orientation follow; in RTL the horizontal arrow directions mirror automatically.
  • Group disableddisabled on the group cascades to every toggle inside.
  • Icon-only — supply an aria-label; pair with a Tooltip for sighted discoverability. Never change the label or icon on toggle.
  • Mixed — reserve aria-pressed="mixed" for a composite "select all" toggle whose children don't all share a value.

Anatomy

Compose a single toggle directly, or wrap several in a group.

  • Toggle — one two-state button. Pass pressed / defaultPressed standalone, or a value inside a group. Takes a variant (ghost / accent / primary / outline), size (xslg), optional startIcon / endIcon glyphs, and iconOnly to square it for a single glyph. variant, size, and iconOnly are inherited from an enclosing group when unset.
  • ToggleGroup — the container. Owns the pressed set (controlled via value / onValueChange, or uncontrolled via defaultValue), shares its variant / size / iconOnly with the toggles, and switches between single- and multiple-select with multiple.

Each part carries a data-slot (toggle, toggle-group) for host-side styling — pair it with the data attributes (data-pressed, data-disabled, data-orientation, data-multiple). The group is fully keyboard-operable and RTL-aware.

On surfaces

The same control re-tuned across the elevation scopes — the root canvas, an elevated panel, a menu, and a sunken well. It stays legible on every layer.

root
elevated
menu
sunken

Design tokens

Generated from the component's declaration — the same graph that mints the CSS, so a variable name or its resolution default can't drift. The minted tokens are the public override seam: set one on any ancestor and every toggle in that region retunes — e.g. .toolbar { --noctis-toggle-border-radius: var(--noctis-radius-sm); } softens the corners. See Customization for the full override ladder and Tokens for the whole graph.

Token

API reference

Generated from the component's types — every prop, type, default, and description comes straight from the source.

Prop

AttributeDescription
data-slotThe rendered toggle (or group) element.
data-variantThe visual emphasis — `ghost` (transparent) | `primary` (primary-filled pressed) | `outline` (bordered).
data-sizeThe size scale — `xs` | `sm` | `md` | `lg`; the generated layer keys the per-size internals off it.
data-pressedPresent on a pressed (on) toggle.
data-disabledPresent on a disabled toggle or group.
data-attachedPresent on a group drawing the recessed segmented/connected track.
data-multiplePresent on a group that allows several toggles pressed at once.
data-orientation`horizontal` | `vertical` — the group's orientation.
Prop