# Toolbar

A rack of keys in one slot cut into the plate, under one tab stop. Keys, toggle keys, a copy key and a menu key sit side by side, parted into clusters by engraved lines, and the arrow keys move along it so a keyboard user passes the whole rack with one Tab.

Kit part · Free · https://tactileui.dev/parts/toolbar

- Element: `<tui-toolbar>`
- Needs: `kit.css` and `kit.mjs` ([how to install the kit](https://tactileui.dev/docs/installation#the-kit))
- Categories: Buttons
- Finishes: Aluminium, Graphite, Oak, Walnut, Porcelain, Black, Daylight, Night, Paper, Phosphor, E-paper, AMOLED
- Volumes: Tactile, Quiet

## Variants

### A rack, clusters parted

```html
<div class="tui-toolbar" role="toolbar" aria-label="Text formatting"><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="true" aria-label="Bold"><b>B</b></button><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="false" aria-label="Underline"><u>U</u></button><i class="tui-toolbar__rule" aria-hidden="true"></i><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="false" aria-label="Link"><svg class="tui-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6.8 9.2a2.6 2.6 0 0 0 3.7 0l2-2a2.6 2.6 0 0 0-3.7-3.7l-.8.8"/><path d="M9.2 6.8a2.6 2.6 0 0 0-3.7 0l-2 2a2.6 2.6 0 0 0 3.7 3.7l.8-.8"/></svg></button><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="false" aria-label="Copy"><svg class="tui-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5.5" y="5.5" width="7.5" height="7.5" rx="1.5"/><path d="M3 10.5V4a1 1 0 0 1 1-1h6.5"/></svg></button></div>
```

### Words, a copy key, a menu key

```html
<div class="tui-toolbar" role="toolbar" aria-label="Document"><button class="tui-key tui-toggle-key" type="button" tabindex="-1" aria-pressed="true"><span class="tui-lamp" data-lamp="amber" aria-hidden="true"></span>Pin</button><i class="tui-toolbar__rule" aria-hidden="true"></i><button class="tui-key tui-copy-key" type="button" aria-label="Copy" tabindex="-1"><span class="tui-lamp" aria-hidden="true"></span><span class="tui-copy-key__legend">Copy</span></button><button class="tui-key tui-menu__trigger" type="button" tabindex="-1">Share</button></div>
```

### Small keys, words

```html
<div class="tui-toolbar" role="toolbar" aria-label="Log levels"><button class="tui-key tui-toggle-key tui-key--sm" type="button" tabindex="-1" aria-pressed="true"><span class="tui-lamp" data-lamp="red" aria-hidden="true"></span>Errors</button><button class="tui-key tui-toggle-key tui-key--sm" type="button" tabindex="-1" aria-pressed="true"><span class="tui-lamp" data-lamp="amber" aria-hidden="true"></span>Warnings</button><button class="tui-key tui-toggle-key tui-key--sm" type="button" tabindex="-1" aria-pressed="false"><span class="tui-lamp" data-lamp="blue" aria-hidden="true"></span>Info</button></div>
```

### A column · aria-orientation

```html
<div class="tui-toolbar" role="toolbar" aria-label="Tools" aria-orientation="vertical"><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="true" aria-label="Draw"><svg class="tui-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 13h3l7-7-3-3-7 7z"/></svg></button><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="false" aria-label="Adjust"><svg class="tui-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2.5 5h5.5M11 5h2.5M2.5 11H5M8 11h5.5"/><circle cx="9.5" cy="5" r="1.5"/><circle cx="6.5" cy="11" r="1.5"/></svg></button><i class="tui-toolbar__rule" aria-hidden="true"></i><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="false" aria-label="Delete"><svg class="tui-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.5 4.5h9M6.5 4.5V3h3v1.5M5 4.5l.6 8.5h4.8l.6-8.5"/></svg></button></div>
```

### Wraps when narrow

```html
<div style="width:190px"><div class="tui-toolbar" role="toolbar" aria-label="Text formatting"><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="false" aria-label="Bold"><b>B</b></button><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="false" aria-label="Italic"><i style="font-family:serif;font-size:14px">I</i></button><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="false" aria-label="Underline"><u>U</u></button><i class="tui-toolbar__rule" aria-hidden="true"></i><button class="tui-key tui-toggle-key tui-key--icon" type="button" tabindex="-1" aria-pressed="false" aria-label="Link"><svg class="tui-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6.8 9.2a2.6 2.6 0 0 0 3.7 0l2-2a2.6 2.6 0 0 0-3.7-3.7l-.8.8"/><path d="M9.2 6.8a2.6 2.6 0 0 0-3.7 0l-2 2a2.6 2.6 0 0 0 3.7 3.7l.8-.8"/></svg></button><i class="tui-toolbar__rule" aria-hidden="true"></i><button class="tui-key" type="button" tabindex="-1">Clear</button><button class="tui-key" type="button" disabled>Undo</button></div></div>
```

## Every state

- Rest
- Hover
- Latched
- Focus
- Disabled

Hover, pressed and focus are forced with `.is-hover`, `.is-down` and `.is-focus`; checked and disabled are real.

## API

| Name | Kind | Values | What it does |
| - | - | - | - |
|  | element | with .tui-toolbar, role="toolbar", aria-label | The rack. Makes the keys one tab stop with arrow keys; without the script each key is in the tab order. |
| role="toolbar" · aria-label | attribute | on the element | Required, and not guessed: the name says what the keys act on. |
| aria-orientation="vertical" | attribute | on the element | Lays the keys in a column; the arrows go up and down instead. |
| .tui-toolbar__rule | class | between keys | A parting line between clusters of keys, cut in the floor of the slot. |
| .tui-key · .tui-toggle-key · .tui-copy-key | class | inside the rack | Any key of the kit. Buttons, links and checkboxes take part in the arrows; anything inside a popover keeps its own. |
| items | property | HTMLElement[] | The keys the arrows move between, in order, without hidden ones or a menu’s items. |
| rovingNext(index, key, count, options) | function | { orientation, loop, skip } | Where a key press moves the focus, or -1. The toggle group’s, shared. |
| ← → · ↑ ↓ · Home · End · Tab | key | in the rack | Move along it (wrapping); first and last; leave it. Tab comes back to the key it left. |

## Markup

```html
<tui-toolbar class="tui-toolbar" role="toolbar" aria-label="Text formatting">
  <button class="tui-key tui-key--icon tui-toggle-key" type="button" data-toggle-key aria-pressed="false" aria-label="Bold"><b>B</b></button>
  <button class="tui-key tui-key--icon tui-toggle-key" type="button" data-toggle-key aria-pressed="false" aria-label="Italic"><i>I</i></button>
  <i class="tui-toolbar__rule" aria-hidden="true"></i>
  <button class="tui-key tui-key--icon" type="button" aria-label="Link"><svg class="tui-icon" …></svg></button>
  <button class="tui-key" type="button">Clear</button>
</tui-toolbar>

<!-- A column: the arrows go up and down -->
<tui-toolbar class="tui-toolbar" role="toolbar" aria-label="Tools" aria-orientation="vertical">…</tui-toolbar>
```

```js
import { rovingNext } from '/kit/kit.mjs';   // the same one the toggle group moves by

const bar = document.querySelector('tui-toolbar');
bar.items;                                      // the keys the arrows move between, in order
rovingNext(0, 'ArrowRight', bar.items.length);  // 1
```

The demo on the page:

```html
<div class="tui-panel" style="width:min(100%,480px);display:grid;gap:16px;text-align:left"><div class="tui-panel__head" style="margin-bottom:0"><span class="tui-label">Incident note · 2291</span><span class="tui-status"><span class="tui-lamp" data-on></span>Draft</span></div>
  <tui-toolbar class="tui-toolbar" role="toolbar" aria-label="Text formatting" data-tb-bar><button class="tui-key tui-toggle-key tui-key--icon" type="button" data-toggle-key aria-pressed="true" aria-label="Bold" data-tb="bold"><b>B</b></button><button class="tui-key tui-toggle-key tui-key--icon" type="button" data-toggle-key aria-pressed="false" aria-label="Italic" data-tb="italic"><i style="font-family:serif;font-size:14px">I</i></button><button class="tui-key tui-toggle-key tui-key--icon" type="button" data-toggle-key aria-pressed="false" aria-label="Underline" data-tb="underline"><u>U</u></button><i class="tui-toolbar__rule" aria-hidden="true"></i><button class="tui-key tui-toggle-key tui-key--icon" type="button" data-toggle-key aria-pressed="false" aria-label="Link" data-tb="link"><svg class="tui-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6.8 9.2a2.6 2.6 0 0 0 3.7 0l2-2a2.6 2.6 0 0 0-3.7-3.7l-.8.8"/><path d="M9.2 6.8a2.6 2.6 0 0 0-3.7 0l-2 2a2.6 2.6 0 0 0 3.7 3.7l.8-.8"/></svg></button><i class="tui-toolbar__rule" aria-hidden="true"></i><button class="tui-key" type="button" data-tb-clear>Clear</button><button class="tui-key" type="button" disabled>Undo</button></tui-toolbar>
  <p class="tui-tray" style="margin:0;padding:12px 14px;font:400 var(--tui-t-body)/1.5 var(--tui-sans)" data-tb-sample>Invoices were off by a penny for 41 customers; a fix is out and refunds go today.</p>
  <output class="tui-muted" style="font-size:var(--tui-t-small)" data-tb-out aria-live="polite">Bold is on</output></div>
```

## Usage notes

Tab once into the rack, then move along it with the arrow keys; Home and End go to the ends and Tab leaves. Bold, italic and underline latch and change the sample, Clear lets them all go, and Undo is disabled so the arrows pass it by.

## Accessibility

- The element is `role="toolbar"` with a name, and each key is a button, so a screen reader says “Text formatting, toolbar” and then the key.
- With the script the rack is one tab stop and the arrow keys do the rest: they wrap, Home and End go to the ends, disabled keys are passed over, and the focus returns to the key it left.
- A toggle key inside it keeps its own `aria-pressed`; the toolbar does not touch it.
- Parting lines are hidden from a screen reader; they are only for the eye.
- A narrow screen wraps the rack onto a second row rather than scrolling it, and on a phone each cap is 44px square or taller.
- Nothing moves but the 70ms press of a key, which reduced motion turns off.

## How it’s built

It is the button group’s slot with the same three pixels of floor round the keys, so a key’s corner is the slot’s corner less that gap, and the clusters are parted by the toggle group’s engraved cut. What is new is the single tab stop: the toggle group’s `rovingNext` works out where each arrow goes, and the element keeps exactly one key at tabindex 0, the last one that had the focus. The keys themselves stay the kit’s keys, so every finish and both volumes draw them.

## Rules

Put the actions on one thing in one rack: a single tab stop, arrows and Home and End along it, clusters parted by a cut in the floor.

The full rules are in `toolbar.rules.md` in the brain, which ships with the Kit.

## Related parts

- [Button group](https://tactileui.dev/parts/button-group): Keys that belong together set side by side in one slot, like the transport keys of a deck. Each is still its own cap and goes down on its own; only the corners facing a neighbour are tightened, so the row reads as one bank. A split key is one action with the menu of its other ways, two caps in one slot, and a readout can be printed between keys.
- [Toggle group](https://tactileui.dev/parts/toggle-group): The segmented control’s keys, each latching on its own, so any number can be down at once: bold and italic, the columns a table shows, the filters on a log. Every key is a checkbox and posts with the form. A lone toggle is a group of one, and a parting line splits clusters of keys in one slot.
- [Toggle key](https://tactileui.dev/parts/toggle-key): One key that latches below the plate and stays there. It is the kit’s own key with one state to keep, down or up, so it is the way to say mute, pin, bold or armed without the weight of a switch. A lamp in the cap may light while it is down.
- [Menu](https://tactileui.dev/parts/menu): A card of actions and options that slides out from under its key. The key stays down while the card is out; an option that is on lights its lamp.
