Toolbar
Overview
A compact container that groups related actions, links, and toggle controls into a single roving-focus toolbar. SToolbar combines the Aria toolbar primitives (ToolbarRoot/ToolbarButton/ToolbarLink/ToolbarSeparator/ToolbarToggleGroup/ToolbarToggleItem) with the toolbarVariants style recipe (7 slots, 6 sizes × 2 orientations).
Use a toolbar for a dense, keyboard-navigable row of actions. For a single action button use button; for grouped buttons use toggle-group.
Usage
Features
- 🧩 Aria/styled split —
ToolbarRootprovides the toolbar context; each part (button/link/separator/toggle-group) is a thin styled primitive - ⌨️ Roving focus — arrow-key navigation between toolbar items, Home/End, with optional
loop; separators/disabled items are skipped - ↔️ Orientation —
horizontal(default) orvertical; separators auto-flip orientation - 🔘 Toggle group —
SToolbarToggleGroup/SToolbarToggleItemfor single/multi-select toggles withv-model - 🔗 Link support —
SToolbarLinkrenders an anchor with a leading icon (showIcon) - 📐 6 sizes — xs–2xl
size; per-slotuioverrides - ♿ Accessible —
role="toolbar",aria-orientation,aria-pressedon toggles,axe-coreclean
Component family
SToolbar(styled) — the root wrapper;toolbarVariantsrecipe (size+ orientation) withprovideToolbarUiSToolbarButton(styled) — a toolbar button (Buttonbase)SToolbarLink(styled) — a toolbar link (Linkbase with optionalshowIcon)SToolbarSeparator(styled) — an orientation-aware divider (SeparatorRootbase)SToolbarToggleGroup/SToolbarToggleItem(styled) — toggle-group controls (ToggleGroupRoot/ToggleGroupItembase)ToolbarRoot/ToolbarButton/ToolbarLink/ToolbarSeparator/ToolbarToggleGroup/ToolbarToggleItem(Aria) — the underlying primitives
Demos
API
Aria Layer
7Toolbar
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Additional class names applied to the root element. |
size | ThemeSize | — | Visual size of the component. |
ui | Partial<ToolbarUi> | — | Per-slot class overrides for the component. |
orientation | DataOrientation | — | The orientation of the toolbar. |
dir | Direction | — | The reading direction of the toolbar. |
loop | boolean | — | Whether keyboard roving focus loops. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
ToolbarButton
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | ButtonType | 'button' | The type of the button element. Can be one of 'button', 'submit', or 'reset'. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
click | PointerEvent | Emitted when click occurs. |
ToolbarLink
Props
| Prop | Type | Default | Description |
|---|---|---|---|
showIcon | boolean | — | Whether or not to show an icon when the `href` prop is provided. |
to | string | import("vue-router").RouteLocationAsRelativeGeneric | import("vue-router").RouteLocationAsPathGeneric | — | Route Location the link should navigate to when clicked on. |
replace | boolean | — | Calls `router.replace` instead of `router.push`. |
href | string | — | The URL the link should navigate to when clicked on. |
disabled | boolean | — | When `true`, the link is disabled. |
activeClass | string | — | Class to apply when the link is active |
exactActiveClass | string | — | Class to apply when the link is exact active |
inactiveClass | string | — | The class to apply to the link when it is inactive. |
prefetchedClass | string | — | A class to apply to links that have been prefetched. |
external | boolean | — | Forces the link to be considered as external (true) or internal (false). This is helpful to handle edge-cases |
ariaCurrentValue | 'true' | 'false' | 'page' | 'date' | 'time' | 'step' | 'location' | `'page'` | Value passed to the attribute `aria-current` when the link is exact active. |
viewTransition | boolean | — | Pass the returned promise of `router.push()` to `document.startViewTransition()` if supported. |
target | (string & {}) | '_blank' | '_parent' | '_self' | '_top' | null | — | Where to display the linked URL, as the name for a browsing context. |
rel | (string & {}) | 'noopener' | 'noreferrer' | 'nofollow' | 'sponsored' | 'ugc' | null | 'noopener noreferrer' | A rel attribute value to apply on the link. Defaults to "noopener noreferrer" for external links. |
noRel | boolean | — | If set to true, no rel attribute will be added to the link |
prefetch | boolean | — | When enabled will prefetch middleware, layouts and payloads of links in the viewport. |
prefetchOn | 'visibility' | 'interaction' | Partial<{ visibility: boolean; interaction: boolean; }> | — | Allows controlling when to prefetch links. By default, prefetch is triggered only on visibility. |
noPrefetch | boolean | — | Escape hatch to disable `prefetch` attribute. |
trailingSlash | 'append' | 'remove' | — | An option to either add or remove trailing slashes in the `href` for this specific link.
Overrides the global `trailingSlash` option if provided. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
ToolbarRoot
Props
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | DataOrientation | — | The orientation of the toolbar. |
dir | Direction | — | The reading direction of the toolbar. |
loop | boolean | — | Whether keyboard roving focus loops. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
ToolbarSeparator
Props
| Prop | Type | Default | Description |
|---|---|---|---|
decorative | boolean | — | Whether or not the component is purely decorative. <br>When `true`, accessibility-related attributes are updated so
that that the rendered element is removed from the accessibility tree. |
ToolbarToggleGroup<M, T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
rovingFocus | boolean | — | When `false`, navigating through items with arrow keys is disabled. |
disabled | boolean | — | When `true`, prevents interaction with all items in the group. |
orientation | DataOrientation | — | The orientation of the component. |
dir | Direction | — | The reading direction of the group when applicable. |
loop | boolean | — | When `true`, keyboard navigation loops from last to first item, and vice versa. |
modelValue | (M extends true ? T[] : T) | — | The controlled value of the selected item(s).
Use this when you need to control the state of the items. Can be bound with `v-model` |
defaultValue | (M extends true ? T[] : T) | — | The default value of the selected item(s).
Use this when you need to set the initial state of the items. |
multiple | M | — | Determines whether a "single" or "multiple" items can be selected at a time.
This prop will overwrite the inferred type from `modelValue` and `defaultValue`. |
clearable | boolean | — | Whether selected item can be cleared when `multiple` is false. |
selectionBehavior | SelectionBehavior | 'toggle' | How multiple selection should behave in the collection. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | M extends true ? T[] : T | — |
ToolbarToggleItem<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | T | — | A unique value that identifies the item inside the group. |
type | ButtonType | 'button' | The type of the button element. Can be one of 'button', 'submit', or 'reset'. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Notes
Architecture and benchmark differences
The toolbar family is a multi-slot composition: ToolbarRoot provides the roving-focus + orientation context while each part (button/link/separator/toggle-group) reuses the button, link, separator and toggle-group primitives, with the UI wrapper injecting toolbarVariants classes per slot. This mirrors radix-ui/shadcn-ui’s headless toolbar/toggle-group split. Ant Design, Element Plus, Mantine and Naive UI ship a button/segmented-control but not a dedicated roving-focus toolbar container with orientation-aware separators; VeanUI provides a complete toolbar with loop/RTL support and a size scale.
| Capability | VeanUI | shadcn/ui | Ant Design | Element Plus | Mantine | Naive UI |
|---|---|---|---|---|---|---|
| Aria/styled split | ✅ | ✅ | — | — | — | — |
| Roving focus + loop | ✅ | ✅ | — | — | ✅ | — |
| Orientation-aware | ✅ | ✅ | — | — | — | — |
| Toggle group | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Link support | ✅ | ✅ | — | — | — | — |
| Sizes (6) | ✅ | — | — | — | — | — |
— = unsupported or a different interaction model.
Cautions
SToolbarrendersrole="toolbar"witharia-orientation(horizontaldefault /vertical); separators auto-flip to match.- Roving focus uses arrow keys + Home/End;
loopwraps navigation. Disabled items and separators are skipped. SToolbarToggleGroupsupports single (model-valuestring) and multiple (model-valuearray) selection withv-model.dir/RTL is derived from theConfigProviderlocale (e.g.ar) or set explicitly on the root.SToolbarLinkrenders an anchor;showIconadds a leading icon next to the link text.
Roadmap
N/A — toolbar is feature-complete for the current parity set.
FAQ
How do I build a toolbar?
Compose buttons, links, a separator and a toggle group:
<SToolbar>
<SToolbarButton>Cut</SToolbarButton>
<SToolbarButton>Copy</SToolbarButton>
<SToolbarSeparator />
<SToolbarToggleGroup v-model="align">
<SToolbarToggleItem value="left">Left</SToolbarToggleItem>
<SToolbarToggleItem value="center">Center</SToolbarToggleItem>
</SToolbarToggleGroup>
</SToolbar>How do I make it vertical?
Set orientation="vertical":
<SToolbar orientation="vertical">
<SToolbarButton>Up</SToolbarButton>
<SToolbarButton>Down</SToolbarButton>
</SToolbar>How do I make navigation loop?
Set loop:
<SToolbar loop>
<SToolbarButton>A</SToolbarButton>
<SToolbarButton>B</SToolbarButton>
</SToolbar>How do I add a link?
Use SToolbarLink with href and show-icon:
<SToolbar>
<SToolbarLink href="https://example.com" show-icon>Website</SToolbarLink>
</SToolbar>