j3w1 / ToolbarVue · HTML · React · Astro

J3W1 / DESIGN SYSTEM

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 · 1.1.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@1.1.0
import '@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.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

npx --package=@j3w1/ui@1.1.0 j3w1-ui copy toolbar --out ./vendor/j3w1/toolbar

The 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

NameType / signatureMeaning
disabledCustomEventDisable the native controls owned by this instance.
loadingCustomEventMark the primary control busy and prevent duplicate activation.

properties

NameType / signatureMeaning
disabledbooleanDelegates disabled state to native children.
namestringNative control name; application form keys remain explicit.

methods

NameType / signatureMeaning
refresh(): voidReconnect behavior after replacing native child structure.
focus(options?: FocusOptions): voidFocus the first usable native control.

events

NameType / signatureMeaning
j3w1-actionCustomEventA 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

Purpose

Groups the frequent actions of a view into one row that costs one tab stop. A toolbar is for actions on the content beneath it; navigation between views belongs in tabs or the sidebar, and a set of mutually exclusive choices in a segmented control or radio group.

Anatomy

A div with role="toolbar" on color.surface.chrome with a 1px color.border.divider bottom edge. Inside, ghost buttons in color.text.default with a transparent 1px border, vertical separators in color.border.default between groups, and in the overflow variant a trailing “More” button that opens a menu with the controls that do not fit. Toggle buttons carry aria-pressed.

States

StateVisualNon-colour channel
defaulttext color.text.default; no fill; transparent border
hoverbackground → color.interaction.hover.bgcursor: pointer
focus-visiblering 1px dashed color.interaction.focus.ring at −2pxthe ring
disabledtext color.text.disabled; no fill; no hoverdisabled; cursor: not-allowed; skipped by the arrow keys
toggledfill color.interaction.pressed.bg; 1px color.border.active border; text color.text.brightaria-pressed="true"; the border

Pressing a button uses color.interaction.pressed.bg for the duration of the press only; a toggled button keeps it.

Keyboard

The toolbar is one tab stop: the last focused control (initially the first enabled one) has tabindex="0", every other control tabindex="-1". Left and Right move between controls and wrap; Home and End jump to the ends; Enter and Space activate. Disabled controls are skipped. Vertical toolbars declare aria-orientation="vertical" and use Up and Down. Without script every button is a tab stop, which is acceptable, not ideal.

Accessibility

aria-label names the toolbar; a page with several toolbars gives each a distinct name. Toggle buttons expose aria-pressed; their label does not change with the state. Separators are role="separator" with aria-orientation="vertical" and are never focusable. Icon-only buttons carry aria-label and a tooltip. Contrast: text 8.60:1 on the chrome surface, toggled text 8.41:1 on the pressed fill, the toggled border 3.81:1, ring 4.66:1. Every control is at least 24×24 CSS pixels with 4px between neighbours in compact density.

Portability

Ghost buttons with a background and a border; the separator is a 1px rule. Toolkits with a native toolbar keep their own keyboard model and take the colours. The overflow menu is a menu component; hosts without one wrap the row instead and record the deviation.

Non-examples

Buttons with a visible border at rest. A filled primary button inside the toolbar. Rounded buttons or a pill-shaped toolbar. Every button in the tab order when script is available. A toggled state shown by colour alone without aria-pressed. A toolbar that wraps to two lines. A separator that receives focus. Disabling by opacity.

j3w1 / command

  • SPEC Overview
  • SPEC Foundations
  • SPEC Components
  • SPEC Patterns
  • SPEC Tokens
  • SPEC Tools
  • SPEC Implement
  • SPEC For agents
  • SPEC Ports
  • SPEC Releases
  • DEMO Vue application demo
  • SPEC Complete UI theme specification