Noctis

Toolbar

Group a set of related controls into one framed row. The toolbar is a single tab stop; arrow keys rove between its items, so a dense bar of actions never floods the page's tab order.

Basic

A row of buttons, a toggle, and a link, divided into clusters by a hairline separator. The first item is the only tab stop — once focus is inside, the arrow keys move between items. A Toolbar.Toggle is just another flat item that shows an on state (the pressed fill is the neutral selected fill — accent stays reserved for the focus ring, never selection).

Docs

Groups

Weld a set of items into one segmented cluster with Toolbar.Group — the buttons abut and only the cluster's outer corners round, so it reads as a single control. Separators rule between clusters. Icon-only buttons take an aria-label to name them.

Sizes

size sets the density. md (the default) is the comfortable bar; sm drops to control-xs heights and tighter padding for a dense editor header. The hosted toggles map their own size from the toolbar, so a whole bar resizes in one prop. (Icon-only items stay touch-safe on coarse pointers.)

Variants

variant chooses the frame. framed (default) is a bordered surface row; plain drops the border and background for a toolbar that already sits inside a Surface or Card; floating lifts a bubble / selection bar off the page with an elevated shadow. All stay sharp.

Input & spacer

Toolbar.Input is a roving field item — a zoom %, a font size, an inline search — styled with the field roles and kept level with the buttons beside it. Toolbar.Spacer is a logical flex slot that pushes the items after it to the inline-end, so a left-tools / right-actions split leans correct in RTL with no hand-rolled flex-1 div. An overflow "More" menu composes through Toolbar.Button's render (render={<Menu.Trigger />}).

Vertical

Set orientation="vertical" on Toolbar.Root to stack the items into a column — for a side rail of tools. The arrow keys follow the orientation (up/down), and the separator turns to a horizontal rule.

Keyboard

The toolbar is one tab stop; focus roves within it with the arrow keys. Directional keys mirror under RTL — ArrowRight walks toward the visual end in LTR and toward the start in RTL.

KeyAction
TabMove focus into the toolbar (landing on the last-focused item) or out of it — the whole row is a single tab stop.
ArrowRight / ArrowDownMove focus to the next item. In a horizontal toolbar ArrowRight follows the writing direction (toward the start under RTL); a vertical toolbar uses ArrowDown.
ArrowLeft / ArrowUpMove focus to the previous item, mirrored under RTL.
HomeMove focus to the first item.
EndMove focus to the last item.
Enter / SpaceActivate the focused button, follow the focused link, or toggle the focused toggle.

Focus loops at the ends by default; pass loopFocus={false} to Toolbar.Root to stop at the first and last item. A hosted menu or select item owns its own arrow keys, so the toolbar's roving doesn't fight it.

Accessibility

  • Name the toolbar. Always pass aria-label (or aria-labelledby) to Toolbar.Root — the APG toolbar pattern requires the row be named, and the toolbar should never be the only way to reach an action.
  • Tooltips on icon-only items fire on focus and hover. A keyboard-roving user lands on an unlabeled glyph, so the name must reach them too: give every icon-only item an aria-label (the visible tooltip supplements, never replaces it).
  • Don't nest a bare arrow-key widget. A radio group inside a horizontal toolbar fights the toolbar's own arrow navigation; host such controls behind a menu button instead (compose Menu through Toolbar.Button's render).

Anatomy

Compose a toolbar from its parts. Toolbar.Root owns the orientation, density (size), frame (variant), and the roving-tabindex focus model.

  • Toolbar.Root — the row container. Props: size (sm | md, default md), variant (framed | plain | floating, default framed), orientation (default horizontal), loopFocus (default true), disabled, plus the Base UI Toolbar.Root props. Give it an aria-label.
  • Toolbar.Button — one button item. Optional leading icon; can be disabled (it stays in the roving order so it can still be reached and announced).
  • Toolbar.Link — a roving item rendered as an anchor, sharing the button look. Pass href.
  • Toolbar.Toggle — a pressable on/off item (a flat ghost toggle with a neutral pressed fill and aria-pressed); use it standalone for an independent toggle. Optional startIcon / endIcon; aria-label when icon-only.
  • Toolbar.ToggleGroup — coordinates a set of toggles with a shared value model — single-select (a view switcher / alignment) or multiple (Bold/Italic/Underline). It renders as a plain, gap-separated row of toggles (no segmented track), spaced like the buttons. Its size maps from the toolbar density.
  • Toolbar.Input — a roving field item (zoom %, font size), field-styled; mark it aria-invalid for the error border.
  • Toolbar.Group — welds several items into one segmented cluster; only the cluster's outer corners round.
  • Toolbar.Spacer — a logical flex slot pushing the following items to the inline-end (a left / right split); presentational, not a roving stop.
  • Toolbar.Separator — a hairline divider between item clusters; it turns horizontal in a vertical toolbar.

The toolbar hosts the shipped controls rather than forking its own: Toolbar.Button renders a Button (ghost), Toolbar.Link is a real anchor styled with the same Button recipe, and the toggles render Toggle/ToggleGroup — so every item shares one visual language and the link never drifts in size from the buttons. The toolbar-owned slots are toolbar, toolbar-separator, toolbar-group, toolbar-input, and toolbar-spacer; the items carry the Button/Toggle slots and markers. Pair a slot with the state attributes (data-size, data-variant, data-orientation) for host-side styling. The row is fully keyboard-operable and RTL-aware.

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 toolbar in that region retunes — e.g. .tight { --noctis-toolbar-item-radius: 0; } squares the hosted controls. The items' own sizing/padding comes from the Button/Toggle tokens. Knobs that aren't minted are reached through the part's data-slot. 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. Each part gets its own table; parts that only forward to Base UI list just the props they pass through. Expand a row for the full type and description.

Toolbar.Root

Prop

Toolbar.Button

Prop

Toolbar.Link

Prop

Toolbar.ToggleGroup

Prop

Toolbar.Toggle

Prop

Toolbar.Input

Prop

Toolbar.Group

Prop

Toolbar.Spacer

Prop

Toolbar.Separator

Prop

AttributeDescription
data-slotThe element's slot — the styling and testing hook.
data-size`sm` | `md` — the toolbar density, stamped on the root; re-points the button/input metrics.
data-variant`framed` | `plain` | `floating` — the toolbar frame, stamped on the root.
data-orientation`horizontal` | `vertical` — the row's orientation, stamped on every part.
data-disabledPresent on a disabled toolbar button or group.
data-pressedPresent on a hosted toolbar toggle while it is pressed (on).
data-highlightedPresent on the item the keyboard's roving focus currently rests on.