Toolbar
A row of related controls under one tab stop with arrow-key movement; ghost buttons, a vertical separator, and a "more" button when the row overflows.
stable · light DOM · 4.0.0. Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.
Live variants
default
<j3w1-toolbar id="example-toolbar-default"><div class="toolbar" role="toolbar" aria-label="Editor" aria-orientation="horizontal">
<button class="toolbar-button" type="button" tabindex="0">Undo</button>
<button class="toolbar-button" type="button" tabindex="-1">Redo</button>
<div class="toolbar-separator" role="separator" aria-orientation="vertical"></div>
<button class="toolbar-button toolbar-button-demo-target" type="button" aria-pressed="false" tabindex="-1">Wrap</button>
<button class="toolbar-button" type="button" aria-pressed="true" tabindex="-1">Whitespace</button>
<div class="toolbar-separator" role="separator" aria-orientation="vertical"></div>
<button class="toolbar-button" type="button" tabindex="-1">Format</button>
</div></j3w1-toolbar>overflow
<j3w1-toolbar id="example-toolbar-overflow"><div class="toolbar" role="toolbar" aria-label="Editor" aria-orientation="horizontal">
<button class="toolbar-button" type="button" tabindex="0">Undo</button>
<button class="toolbar-button" type="button" tabindex="-1">Redo</button>
<div class="toolbar-separator" role="separator" aria-orientation="vertical"></div>
<button class="toolbar-button toolbar-button-demo-target" type="button" aria-pressed="false" tabindex="-1">Wrap</button>
<j3w1-menu><div class="menu"><button class="toolbar-button toolbar-more" type="button" id="example-toolbar-overflow-toolbar-more-trigger" aria-haspopup="menu" aria-expanded="false" aria-controls="example-toolbar-overflow-toolbar-more-menu" tabindex="-1">More</button><ul class="menu-list" role="menu" id="example-toolbar-overflow-toolbar-more-menu" aria-labelledby="example-toolbar-overflow-toolbar-more-trigger" hidden=""><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="format">Format</button></li><li role="none"><button class="menu-item" type="button" role="menuitemcheckbox" tabindex="-1" aria-checked="false" data-action="whitespace">Show whitespace</button></li></ul></div></j3w1-menu>
</div></j3w1-toolbar>Install and register
Use the exact version. If npm publication is pending, install the release tarball from the installation guide.
npm install --save-exact @j3w1/ui@4.0.0import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/toolbar.css';
import '@j3w1/ui/register/toolbar';Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.
Copy the complete implementation
npx --package=@j3w1/ui@4.0.0 j3w1-ui copy toolbar --out ./vendor/j3w1/toolbarThe CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.
Public API
attributes
| Name | Type / signature | Meaning |
|---|---|---|
disabled | CustomEvent | Disable the native controls owned by this instance. |
loading | CustomEvent | Mark the primary control busy and prevent duplicate activation. |
properties
| Name | Type / signature | Meaning |
|---|---|---|
disabled | boolean | Delegates disabled state to native children. |
name | string | Native control name; application form keys remain explicit. |
methods
| Name | Type / signature | Meaning |
|---|---|---|
refresh | (): void | Reconnect behavior after replacing native child structure. |
focus | (options?: FocusOptions): void | Focus the first usable native control. |
events
| Name | Type / signature | Meaning |
|---|---|---|
j3w1-action | CustomEvent | A toggle action changed. |
Dependencies and verification
Registered components: menu. Style dependencies: menu.
Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.
Full implementation manifest, API and token dependency closure
Canonical specification
Toolbar toolbar
A row of related controls under one tab stop with arrow-key movement; ghost buttons, a vertical separator, and a "more" button when the row overflows.
Report an issue with this component
Tokens
Focus a role to inspect its values; follow its link for persistent usage and source details.
| Part | Role | Value | Use |
|---|---|---|---|
root.bg | color.surface.chromeapproveduse | #000000 | D-041 surface.chrome: color.primitive.ink.0. |
root.border | color.border.dividerapproveduse | #482b2b | D-041 border.divider: color.primitive.modern.divider. |
button.text | color.text.defaultapproveduse | #e99499 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
button.bg-hover | color.interaction.hover.bgapproveduse | #1c1010 | D-041 interaction.hover.bg: color.primitive.modern.hover. |
button.bg-pressed | color.interaction.pressed.bgobserveduse | #420f0c | Pressed fill. |
button.ring | color.interaction.focus.ringobserveduse | #e53935 | 1px dashed focus ring on controls and rows. |
button.text-disabled | color.text.disabledapproveduse | #a3676b | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
toggled.bg | color.interaction.pressed.bgobserveduse | #420f0c | Pressed fill. |
toggled.border | color.border.activeobserveduse | #e53935 | Active or focused control border. |
toggled.text | color.text.brightapproveduse | #ffa2a7 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
separator.color | color.border.defaultapproveduse | #482b2b | D-041 border.default: color.primitive.modern.divider. |
more.chevron | color.icon.decorativeapproveduse | #986f72 | D-041 icon.decorative: color.primitive.modern.control. |
Purpose
Groups a view’s frequent actions on the content beneath it into one row that costs one tab stop. Navigation between views belongs in tabs or the sidebar; mutually exclusive choices in a segmented control or radio group.
Anatomy
Parts as listed in the anatomy.
States
| State | Visual | Non-colour channel |
|---|---|---|
| default | text color.text.default; no fill; transparent border | — |
| hover | background → color.interaction.hover.bg | cursor: pointer |
| focus-visible | 1px dashed color.interaction.focus.ring ring at −2px | the ring |
| disabled | text color.text.disabled; no fill; no hover | disabled; cursor: not-allowed; skipped by the arrow keys |
| toggled | fill color.interaction.pressed.bg; 1px color.border.active border; text color.text.bright | aria-pressed="true"; the border |
A press shows color.interaction.pressed.bg only while it lasts; a toggled
button keeps it.
Keyboard
As in the key table. The roving stop is the last focused control, initially the first enabled one.
Accessibility
A page with several toolbars names each distinctly. A toggle button’s label
does not change with its state. Icon-only buttons carry aria-label and a
tooltip. Text meets 4.5:1, the toggled border and the ring 3:1. Every control
is at least 24×24 CSS pixels with 4px between neighbours in compact.
Portability
Toolkits with a native toolbar keep their own keyboard model and take the colours. The overflow menu is the menu component; hosts without one wrap the row and record the deviation.
Non-examples
Buttons bordered at rest. A filled primary button in the toolbar. Rounded
buttons or a pill-shaped toolbar. Every button in the tab order when script
is available. A toggled state by colour alone without aria-pressed. A
toolbar wrapping to two lines. A focusable separator. Disabling by opacity.
Contrast report
9 declared pairs measured on resolved sRGB values with the WCAG 2.x formula; 0 waived (decorative only), 0 failing. A pass is a design target for the named role, not an application-wide conformance claim.
| Pair | State | Kind | Foreground | Background | Ratio | Min | Result |
|---|---|---|---|---|---|---|---|
| toolbar default text | default | text | color.text.default #e99499 | color.surface.chrome #000000 | 9.16 | 4.5 | pass |
| toolbar hover text | hover | text | color.text.default #e99499 | color.interaction.hover.bg #1c1010 | 8.10 | 4.5 | pass |
| toolbar focus-visible text | focus-visible | text | color.text.default #e99499 | color.surface.chrome #000000 | 9.16 | 4.5 | pass |
| toolbar focus-visible outline | focus-visible | ui | color.interaction.focus.ring #e53935 | color.surface.chrome #000000 | 4.97 | 3 | pass |
| toolbar toggled text | toggled | text | color.text.bright #ffa2a7 | color.interaction.pressed.bg #420f0c | 8.41 | 4.5 | pass |
| toolbar toggled border | toggled | ui | color.border.active #e53935 | color.interaction.pressed.bg #420f0c | 3.81 | 3 | pass |
| disabled button text (exempt; house floor 3:1) | disabled | ui | color.text.disabled #a3676b | color.surface.chrome #000000 | 4.71 | 3 | pass |
| separator (decorative; role separator carries the grouping) | — | ui | color.border.default #482b2b | color.surface.chrome #000000 | 1.66 | 1 | pass |
| toolbar bottom edge (decorative) | — | ui | color.border.divider #482b2b | color.surface.chrome #000000 | 1.66 | 1 | pass |
Keys
| Key | Action |
|---|---|
| Tab / Shift+Tab | Enters or leaves the toolbar; one control has tabindex 0 (roving tabindex). |
| Left / Right | Moves focus to the previous or next enabled control; wraps at the ends; Up and Down when aria-orientation is vertical. |
| Home / End | Moves focus to the first or last control. |
| Enter / Space | Activates the focused button or toggles a toggle button. |
| Escape | Restores the previous value in a toolbar that edits, otherwise nothing. |
For agents
Component JSON ·Implementation brief ·Build a task kit ·
Related: button icon-button menu tabs button-group
Stress fixtures: FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-OVERFLOW FX-STATE-MATRIX