# Toolbar

A labelled bar of related tools for a view, a selection or an editor: what it acts on, groups of tools, and its main action, moved through with the arrow keys as one Tab stop.

Block: `smbk-toolbar`. Status: experimental. Figma: the Figma file, https://www.figma.com/community/file/1688324308358870630. Desktop and mobile: differ by presentation only.

## Options

| Axis | Values | Default | Meaning |
|---|---|---|---|
| `placement` | `floating`, `docked` | `floating` | Floating: a raised bar as wide as its tools, with its rim, rounded corners and shadow, over a page, a map or a text selection. Docked: flat across the top of a panel, a line under it, the actions pushed to its end. Where it sticks (the top, the foot of the window) is the page’s to set. Figma: Placement. |

Parts: `smbk-toolbar__row`, `smbk-toolbar__context`, `smbk-toolbar__tools`, `smbk-toolbar__actions`, `smbk-toolbar__divider`, `smbk-toolbar__icon`, `smbk-toolbar__title`, `smbk-toolbar__value`, `smbk-toolbar__text`, `smbk-toolbar__meta`, `smbk-toolbar__status`, `smbk-toolbar__field`, `smbk-toolbar__details`, `smbk-toolbar__wide-only`, `smbk-toolbar__narrow-only`

## Markup

```html
<div
  role="toolbar"
  aria-label="Projects, preview"
  aria-orientation="horizontal"
  class="smbk-toolbar smbk-toolbar--placement-floating"
>
  <div class="smbk-toolbar__row">
    <div class="smbk-toolbar__context">
      <span class="smbk-toolbar__title">Projects</span>
      <span class="smbk-badge smbk-badge--look-soft smbk-badge--tone-default smbk-badge--size-sm">
        <span class="smbk-badge__label">24</span>
      </span>
    </div>
    <div role="group" aria-label="Commands" class="smbk-toolbar__tools">
      <span
        role="separator"
        aria-orientation="vertical"
        class="smbk-divider smbk-divider--orientation-vertical smbk-toolbar__divider"
      ></span>
      <button
        type="button"
        class="smbk-btn smbk-btn--tone-ghost smbk-btn--size-sm smbk-btn--icon-only"
        aria-label="Refresh"
      >
        <i
          class="ph ph-arrows-clockwise smbk-icon smbk-icon--size-md smbk-btn__icon"
          aria-hidden="true"
        ></i>
      </button>
      <span class="smbk-tooltip__layer"><span role="tooltip" id="react-aria-toolbar-1" aria-hidden="true" class="smbk-tooltip smbk-tooltip--arrow-top-center" hidden=""><span class="smbk-tooltip__bubble">Refresh</span><span class="smbk-tooltip__arrow" aria-hidden="true"></span></span></span>
      <button
        type="button"
        class="smbk-btn smbk-btn--tone-ghost smbk-btn--size-sm smbk-btn--icon-only"
        aria-label="Search"
      >
        <i
          class="ph ph-magnifying-glass smbk-icon smbk-icon--size-md smbk-btn__icon"
          aria-hidden="true"
        ></i>
      </button>
      <span class="smbk-tooltip__layer"><span role="tooltip" id="react-aria-toolbar-2" aria-hidden="true" class="smbk-tooltip smbk-tooltip--arrow-top-center" hidden=""><span class="smbk-tooltip__bubble">Search</span><span class="smbk-tooltip__arrow" aria-hidden="true"></span></span></span>
      <button
        type="button"
        class="smbk-btn smbk-btn--tone-ghost smbk-btn--size-sm smbk-btn--icon-only"
        aria-label="Duplicate"
      >
        <i class="ph ph-copy smbk-icon smbk-icon--size-md smbk-btn__icon" aria-hidden="true"></i>
      </button>
      <span class="smbk-tooltip__layer"><span role="tooltip" id="react-aria-toolbar-3" aria-hidden="true" class="smbk-tooltip smbk-tooltip--arrow-top-center" hidden=""><span class="smbk-tooltip__bubble">Duplicate</span><span class="smbk-tooltip__arrow" aria-hidden="true"></span></span></span>
      <button
        type="button"
        class="smbk-btn smbk-btn--tone-ghost smbk-btn--size-sm smbk-btn--icon-only"
        aria-label="Download"
      >
        <i
          class="ph ph-download-simple smbk-icon smbk-icon--size-md smbk-btn__icon"
          aria-hidden="true"
        ></i>
      </button>
      <span class="smbk-tooltip__layer"><span role="tooltip" id="react-aria-toolbar-4" aria-hidden="true" class="smbk-tooltip smbk-tooltip--arrow-top-center" hidden=""><span class="smbk-tooltip__bubble">Download</span><span class="smbk-tooltip__arrow" aria-hidden="true"></span></span></span>
    </div>
    <div class="smbk-toolbar__actions">
      <span
        role="separator"
        aria-orientation="vertical"
        class="smbk-divider smbk-divider--orientation-vertical smbk-toolbar__divider"
      ></span>
      <div class="smbk-dropdown__anchor">
        <button
          type="button"
          class="smbk-btn smbk-btn--tone-ghost smbk-btn--size-sm smbk-btn--icon-only"
          aria-label="More actions"
          id="toolbar-5-opener"
          aria-haspopup="menu"
          aria-expanded="false"
          aria-controls="toolbar-5-panel"
        >
          <i
            class="ph ph-dots-three smbk-icon smbk-icon--size-md smbk-btn__icon"
            aria-hidden="true"
          ></i>
        </button>
        <div class="smbk-dropdown__layer">
          <div
            id="toolbar-5-panel"
            role="menu"
            aria-label="More actions"
            class="smbk-dropdown smbk-dropdown--size-sm smbk-dropdown--align-end"
            tabindex="-1"
            data-scrollbar=""
            hidden=""
          >
            <button type="button" role="menuitem" tabindex="-1" class="smbk-dropdown__item">
              <i
                class="ph ph-pencil-simple smbk-icon smbk-icon--size-md smbk-dropdown__icon"
                aria-hidden="true"
              ></i>
              <span class="smbk-dropdown__text">Rename</span>
            </button>
            <button type="button" role="menuitem" tabindex="-1" class="smbk-dropdown__item">
              <i
                class="ph ph-share-network smbk-icon smbk-icon--size-md smbk-dropdown__icon"
                aria-hidden="true"
              ></i>
              <span class="smbk-dropdown__text">Share</span>
            </button>
            <hr
              class="smbk-divider smbk-divider--orientation-horizontal smbk-dropdown__divider"
              role="separator"
            >
            <button type="button" role="menuitem" tabindex="-1" class="smbk-dropdown__item">
              <i
                class="ph ph-archive smbk-icon smbk-icon--size-md smbk-dropdown__icon"
                aria-hidden="true"
              ></i>
              <span class="smbk-dropdown__text">Archive</span>
            </button>
          </div>
        </div>
      </div>
      <span class="smbk-tooltip__layer"><span role="tooltip" id="react-aria-toolbar-6" aria-hidden="true" class="smbk-tooltip smbk-tooltip--arrow-top-center" hidden=""><span class="smbk-tooltip__bubble">More actions</span><span class="smbk-tooltip__arrow" aria-hidden="true"></span></span></span>
      <button type="button" class="smbk-btn smbk-btn--tone-brand smbk-btn--size-sm">
        <i class="ph ph-plus smbk-icon smbk-icon--size-md smbk-btn__icon" aria-hidden="true"></i>
        <span class="smbk-btn__label">New project</span>
      </button>
    </div>
  </div>
</div>
```

## React

```tsx
import { Toolbar, ToolbarContext, ToolbarTitle, ToolbarTools, ToolbarTool, ToolbarActions, ToolbarOverflow } from './design-system/components/toolbar/toolbar.js';
import { Badge } from './design-system/components/badge/badge.js';
import { DropdownItem, DropdownDivider } from './design-system/components/dropdown/dropdown.js';
import { Button } from './design-system/components/button/button.js';

<Toolbar placement="floating" label="Projects, preview">
  <ToolbarContext>
    <ToolbarTitle>Projects</ToolbarTitle>
    <Badge size="sm">24</Badge>
  </ToolbarContext>
  <ToolbarTools label="Commands">
    <ToolbarTool icon="ArrowsClockwise" label="Refresh" />
    <ToolbarTool icon="MagnifyingGlass" label="Search" />
    <ToolbarTool icon="Copy" label="Duplicate" />
    <ToolbarTool icon="DownloadSimple" label="Download" />
  </ToolbarTools>
  <ToolbarActions>
    <ToolbarOverflow>
      <DropdownItem icon="PencilSimple">Rename</DropdownItem>
      <DropdownItem icon="ShareNetwork">Share</DropdownItem>
      <DropdownDivider />
      <DropdownItem icon="Archive">Archive</DropdownItem>
    </ToolbarOverflow>
    <Button tone="brand" size="sm" leadingIcon="Plus">New project</Button>
  </ToolbarActions>
</Toolbar>
```

## Stylesheet

```css
/* smbk-toolbar — Toolbar. Figma "Toolbar" 7343:1575 (Placement: Floating, Docked), holding ToolbarContext 7339:1264,
 * ToolbarTools 7341:1454 and ToolbarActions 7342:1452.
 * A column on the raised surface, the medium inset all round: a row of zones (what the bar acts on, one or two groups
 * of tools, the overflow menu and the main action), and under it, when there is one, a row of details (the filters
 * applied and the result count). Each zone is a row of the system's own controls at their small size, 32 tall, the
 * small inline space apart; zones sit the medium inline space apart, and a tools or actions zone starts with a
 * vertical divider. Every tool keeps its own look: this sheet draws only the bar, the zones and a few words.
 * The edge is drawn inside, as Figma draws it, so each padding gives its width back: the bar is 48 tall.
 * Narrow (the layout switch): a part marked wide-only goes, and one marked narrow-only comes, so a phone can fold the
 * tools into one opener or the overflow menu. */

.smbk-toolbar {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: var(--smbk-space-inline-md);
  inline-size: fit-content;
  max-inline-size: 100%;
  padding: calc(var(--smbk-space-inset-md) - var(--smbk-border-width-hairline));
  border: var(--smbk-border-width-hairline) solid var(--smbk-color-border-rim);
  border-radius: var(--smbk-radius-container-md);
  background: var(--smbk-color-surface-raised);
  box-shadow: var(--smbk-elevation-raised);
  color: var(--smbk-color-text-default);
}

/* Docked: flat across the top of a panel, as wide as it, with a subtle line under it and no corners or shadow. */
.smbk-toolbar--placement-docked {
  inline-size: auto;
  padding: var(--smbk-space-inset-md) var(--smbk-space-inset-md) calc(var(--smbk-space-inset-md) - var(--smbk-border-width-hairline));
  border: 0;
  border-block-end: var(--smbk-border-width-hairline) solid var(--smbk-color-border-subtle);
  border-radius: 0;
  box-shadow: none;
}

/* ---- the row of zones: wraps onto a second line rather than pushing the page sideways ---- */

.smbk-toolbar__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--smbk-space-inline-md);
  min-inline-size: 0;
}

.smbk-toolbar__context,
.smbk-toolbar__tools,
.smbk-toolbar__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--smbk-space-inline-sm);
  min-block-size: var(--smbk-size-control-sm);
  min-inline-size: 0;
}

/* Docked: the free room goes before the actions, so they sit at the bar's end. */
.smbk-toolbar--placement-docked .smbk-toolbar__actions {
  margin-inline-start: auto;
}

/* The divider that starts a zone: the vertical divider, 24 tall in the 32 row, as Figma draws it. A divider that
   would start the whole row has nothing to divide, so it goes. */
.smbk-toolbar .smbk-toolbar__divider {
  align-self: center;
  block-size: var(--smbk-size-24);
  min-block-size: var(--smbk-size-20);
}

.smbk-toolbar__row > :first-child > .smbk-toolbar__divider:first-child {
  display: none;
}

/* ---- the bar's own words ---- */

/* What the bar acts on, the period a calendar shows, a setting's value: Label MD in the primary text color. */
.smbk-toolbar__title,
.smbk-toolbar__value {
  color: var(--smbk-color-text-default);
  font-family: var(--smbk-typography-label-md-font-family);
  font-size: var(--smbk-typography-label-md-font-size);
  font-weight: var(--smbk-typography-label-md-font-weight);
  line-height: var(--smbk-typography-label-md-line-height);
  letter-spacing: var(--smbk-typography-label-md-letter-spacing);
  white-space: nowrap;
}

/* Figures of one width in all the bar's words, so a number that changes in place (a count of what is selected, a
   status such as "Updated 12 s ago", a value) never moves the words after it. */
.smbk-toolbar__title,
.smbk-toolbar__value,
.smbk-toolbar__text,
.smbk-toolbar__meta {
  font-variant-numeric: tabular-nums;
}

/* A line of status, a summary, a setting's name, a note beside an action: Body SM in the secondary text color. */
.smbk-toolbar__text,
.smbk-toolbar__meta {
  color: var(--smbk-color-text-subtle);
  font-family: var(--smbk-typography-body-sm-font-family);
  font-size: var(--smbk-typography-body-sm-font-size);
  font-weight: var(--smbk-typography-body-sm-font-weight);
  line-height: var(--smbk-typography-body-sm-line-height);
  letter-spacing: var(--smbk-typography-body-sm-letter-spacing);
  white-space: nowrap;
}

/* Something quieter after it, such as when it last changed: the same type in the faintest text color. */
.smbk-toolbar__meta {
  color: var(--smbk-color-text-subtlest);
}

/* An icon before the title, the size Label MD's text takes. */
.smbk-toolbar .smbk-toolbar__icon {
  flex: none;
  font-size: var(--smbk-size-icon-sm);
  color: var(--smbk-color-icon-default);
}

/* A status: its dot or the spinner's ring, its words, and a quieter note, read out when they change. */
.smbk-toolbar__status {
  display: inline-flex;
  align-items: center;
  gap: var(--smbk-space-inline-sm);
}

/* A field in the bar (a list to pick what it acts on, a search field, a time range), at the width Figma draws it,
   since a field fills the room it is given; never wider than the bar. */
.smbk-toolbar__field {
  display: flex;
  flex: none;
  inline-size: var(--smbk-size-toolbar-field-width);
  max-inline-size: 100%;
}

/* ---- the details under the row: the filters applied, then the result count at the end. Never wider than the
   row: its own content does not widen the bar, and its chips wrap instead. ---- */

.smbk-toolbar__details {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--smbk-space-inline-sm);
  contain: inline-size;
}

.smbk-toolbar__details > .smbk-filter-bar__count {
  margin-inline-start: auto;
}

/* ---- wide and narrow ---- */

.smbk-toolbar .smbk-toolbar__narrow-only {
  display: none;
}

@container style(--smbk-layout: narrow) {
  .smbk-toolbar .smbk-toolbar__wide-only {
    display: none;
  }

  /* Anything else marked narrow-only is a wrapper that lends its content to the row or the menu around it. */
  .smbk-toolbar .smbk-toolbar__narrow-only {
    display: contents;
  }

  .smbk-toolbar .smbk-toolbar__narrow-only:is(.smbk-toolbar__context, .smbk-toolbar__tools, .smbk-toolbar__actions) {
    display: flex;
  }
}

/* ---- touch: the tools stop their press areas halfway to each other ----
   Every button takes an invisible press area on a touch screen. In the toolbar's rows of tools and actions, which
   stand closer than that and wrap, each area reaches only halfway into the row's gap, side to side and up and down,
   so every tool stays one press. Nothing drawn moves. */

@media (pointer: coarse) {
  :is(.smbk-toolbar__tools, .smbk-toolbar__actions) .smbk-btn::after {
    inset: max(min(0%, (100% - var(--smbk-size-target-comfortable)) / 2), var(--smbk-space-inline-sm) / -2);
  }

  :is(.smbk-toolbar__tools, .smbk-toolbar__actions) .smbk-segmented__item::after,
  :is(.smbk-toolbar__tools, .smbk-toolbar__actions) .smbk-btn-group .smbk-btn::after {
    inset-block: max(min(0%, (100% - var(--smbk-size-target-comfortable)) / 2), var(--smbk-space-inline-sm) / -2);
  }

  :is(.smbk-toolbar__tools, .smbk-toolbar__actions) :is(button, a[href]).smbk-chip::after {
    inset: max(min(0%, (100% - var(--smbk-size-target-comfortable)) / 2), var(--smbk-space-inline-sm) / -2);
  }
}
```

## Tokens it reads

```json
{
  "space": {
    "inline": {
      "md": {
        "$type": "dimension",
        "$value": "{{space.8}}",
        "$description": "Gap between things side by side, medium."
      },
      "sm": {
        "$type": "dimension",
        "$value": "{{space.6}}",
        "$description": "Gap between things side by side, small."
      }
    },
    "inset": {
      "md": {
        "$type": "dimension",
        "$value": "{{space.8}}",
        "$description": "Padding inside a component, medium."
      }
    }
  },
  "border-width": {
    "hairline": {
      "$type": "dimension",
      "$value": "{{border-width.1}}",
      "$description": "Thin lines: dividers and almost every edge."
    }
  },
  "color": {
    "border": {
      "rim": {
        "$type": "color",
        "$value": "{{color.alpha.white.90}}",
        "$description": "The light rim that makes a surface look lit: fields, chosen pills, cards."
      },
      "subtle": {
        "$type": "color",
        "$value": "{{color.grey.300}}",
        "$description": "Dividers and quiet edges."
      }
    },
    "surface": {
      "raised": {
        "$type": "color",
        "$value": "{{color.grey.50}}",
        "$description": "One floor above default: popovers, raised panels."
      }
    },
    "text": {
      "default": {
        "$type": "color",
        "$value": "{{color.grey.900}}",
        "$description": "Main text."
      },
      "subtle": {
        "$type": "color",
        "$value": "{{color.grey.700}}",
        "$description": "Secondary text: descriptions, metadata."
      },
      "subtlest": {
        "$type": "color",
        "$value": "{{color.grey.600}}",
        "$description": "Quietest text: hints, captions, placeholders."
      }
    },
    "icon": {
      "default": {
        "$type": "color",
        "$value": "{{color.grey.900}}",
        "$description": "Icons."
      }
    }
  },
  "radius": {
    "container": {
      "md": {
        "$type": "dimension",
        "$value": "{{radius.12}}",
        "$description": "Corners of cards, panels and dialogs, medium."
      }
    }
  },
  "elevation": {
    "raised": {
      "$type": "shadow",
      "$value": {
        "light": "0px 2px 8px 1px #373d431a, 0px 1px 2px 0px #373d431a",
        "dark": "0px 2px 8px 1px #00000026, 0px 1px 2px 0px #00000026"
      }
    }
  },
  "size": {
    "20": {
      "$type": "dimension",
      "$value": "20px",
      "$description": "Raw size step, 20 px. Only for fixed sizes inside a component; semantic sizes (size/control, icon, mark) point here."
    },
    "24": {
      "$type": "dimension",
      "$value": "24px",
      "$description": "Raw size step, 24 px. Only for fixed sizes inside a component; semantic sizes (size/control, icon, mark) point here."
    },
    "control": {
      "sm": {
        "$type": "dimension",
        "$value": "{{size.32}}",
        "$description": "Height of a small control: 32 comfortable, 28 compact. Dashboard recipe: use compact density; 40 for the page’s one main action and for forms; 32 for toolbars and filters, the size used most; 28 for actions inside table rows and cards. On phones switch to comfortable density, or give small controls an invisible 44 px tap area (size/target/comfortable)."
      }
    },
    "icon": {
      "sm": {
        "$type": "dimension",
        "$value": "{{size.16}}",
        "$description": "Icon box, small."
      }
    },
    "toolbar": {
      "field-width": {
        "$type": "dimension",
        "$value": "200px",
        "$description": "Width of a field in a toolbar: the list that picks what the bar acts on, a search field, a time range. A fixed frame width in Figma (the Picker, the Filter tools' search) with no variable behind it; it should become one."
      }
    },
    "target": {
      "comfortable": {
        "$type": "dimension",
        "$value": "{{size.44}}",
        "$description": "Comfortable touch target (44)."
      }
    }
  },
  "typography": {
    "label-md": {
      "$type": "typography",
      "$value": {
        "fontFamily": "Geist, Geist Fallback, system-ui, sans-serif",
        "fontSize": "14px",
        "fontWeight": 500,
        "lineHeight": 1.4,
        "letterSpacing": "0px"
      },
      "$description": "Label MD: labels on controls and short UI text (buttons, chips, tabs, menu headings). Geist Medium, sentence case. Code and keys use Code SM and Code MD."
    },
    "body-sm": {
      "$type": "typography",
      "$value": {
        "fontFamily": "Geist, Geist Fallback, system-ui, sans-serif",
        "fontSize": "14px",
        "fontWeight": 400,
        "lineHeight": 1.5,
        "letterSpacing": "0px"
      }
    }
  }
}
```

## Purpose

A labelled bar of related tools for one view, one selection or one editor: what the bar acts on, a group or two of tools, and its main action. A keyboard reaches it with one Tab and moves along it with the arrow keys, so a bar of twenty tools costs one stop, not twenty. It differs from a button group, which is a few actions side by side with a Tab stop each, and from an app bar, which is the application's own navigation and is not a toolbar.

## Anatomy

- The block: the bar, labelled, on the raised surface. Floating, it is as wide as its tools, with a rim, rounded corners and a shadow; docked, it runs flat across the top of a panel with a line under it.
- `row`: the zones, side by side. When the space is too narrow for them all, the row wraps onto a second line rather than pushing the page sideways.
- `context`: what the bar acts on, always first. A title with an optional icon and a count, a back button with a trail of pages, the selection in words, a status, a person, a notice of the mode the page is in, a summary, or a list to pick from.
- `tools`: one group of tools, after a vertical divider. Icon-only tools (the small ghost icon button, or the ghost toggle button for a tool that stays on, each named in a tooltip), buttons with words, a segmented control, a search field and a filters opener, chips, a switch, a slider, the value of a setting. A bar may hold two.
- `actions`: always last, after a divider: the overflow menu and at most one main action, a split button, a pair such as Cancel and Save, a few icon buttons, a close button, or stop and start. Docked, it sits at the bar's end.
- `divider`: the vertical divider that starts a tools or actions zone. A divider that would start the whole row is not drawn.
- `title`, `value`: what the bar acts on, the period a calendar shows, a setting's value, in Label MD. `icon` goes before a title.
- `text`, `meta`: a status, a summary, a setting's name, a note beside an action, in Body SM; `meta` is the quieter note after it, such as when it last changed.
- `status`: a status's dot, or the spinner's ring while busy, with its words and its note.
- `field`: a field in the bar, such as the list that picks what it acts on or a search field, at the width the bar gives a field.
- `details`: an optional row under the zones: the filters applied as removable chips with Clear all, then the result count at the row's end, the filter bar's own parts.
- `wide-only`, `narrow-only`: keep a zone, or anything wrapped in one of them, to a wide or a narrow space.

Every control in the bar is the system's own component at its small size, 32 tall, so the bar is 48 tall.

## When to use

- A view of a list, a board, a calendar or a map with commands for it: refresh, search, download, change the period.
- An editor's formatting and history tools, with the saving status beside them.
- A selection's bulk actions, with the selection's size in words.
- The header of a panel: back, its title, Cancel and Save.
- A small bar floating over a canvas or a text selection.

## When not to use

- The application's or the site's navigation. Use the [app bar](app-bar.md), the [header](header.md) or the [sidebar](sidebar.md).
- Two or three actions under a form or in a dialog. Use a [button group](button-group.md).
- Search, filters and sort above a list, with nothing else. Use the [filter bar](filter-bar.md), a search landmark whose controls each keep their own Tab stop.
- A row of choices of which exactly one is on. Use a [segmented control](segmented-control.md), inside a toolbar if it shares the bar with other tools.

## Behavior

The zones sit in their order whatever the page passes: context first, actions last. Each tools group and the actions start with a divider unless it is turned off. In a narrow space a part marked wide-only goes and one marked narrow-only comes: the tools can fold into one opener, such as a Filters button with a count, and the overflow menu can take the commands that went. Where a bar sticks, at the top of a scrolling panel or the foot of the window, is the page's to set.

An icon-only tool can show its key after its name in its tooltip, such as "Zoom in" then "]", drawn as a small key cap; the page listens for the key. The overflow menu opens a small dropdown lined up with the bar's end. The value of a setting is a small secondary button with a caret, which opens a popover holding the control that changes it, such as a fill slider.

A status in the bar, the selection's count and the result count are read out when they change. Nothing moves when the bar appears.

## Accessibility
### What it does for you

- The bar has the toolbar role and a name of its own, given as its label.
- It is one Tab stop: Tab reaches the bar once, on the tool used last, or the first. Left and Right move between its buttons, toggles, links, chips and choices; Home and End go to the first and the last. The arrows follow the reading direction. The next Tab leaves the bar.
- A field inside the bar, such as a search field, a select, a slider or a number field, keeps its own Tab stop and its own arrow keys, so typing and choosing work as anywhere else; the arrows pass over it. A menu or a panel a tool opens keeps its own keys.
- A tool that stays on is a toggle button and says whether it is pressed; a command never does. Its name stays the same on and off.
- A tool written as the toolbar's own icon-only tool shows its name in a tooltip under it while it is pointed at or reached with the keyboard, and the overflow button does the same; the tooltip is hidden from screen readers, which hear the name once.
- An icon-only tool given a key (`shortcut`) shows it after its name in the tooltip, as a key cap, and carries it as `aria-keyshortcuts`, so a screen reader can say it too. A segmented control in the bar can take a key the same way.
- A zone given a label is a named group, so a screen reader says which group a tool is in.
- The selection's count says the scope in words ("3 selected") and is read out as it changes, so the actions after it never act on an unstated selection.
- The overflow menu keeps each tool's name, tick and disabled state; its button is named "More actions" unless given another name.

### What you must do

- Give every toolbar on a page a different name.
- Give every icon-only tool a name.
- Listen for a tool's key yourself, and press the tool when it comes: the toolbar only shows and names the key. Take a single key only outside text fields, and never one a screen reader or the browser needs.
- Hand-written markup must give the bar the toolbar role and a name, and move focus with the arrow keys itself; without script every tool is its own Tab stop.

### How to test

- Tab: focus enters the bar once, on the tool used last or the first, with the focus ring. Press Left and Right, Home and End to move along it; the next Tab leaves the bar.
- Move onto a search field or a select in the bar: it keeps its own Tab stop, and typing and choosing work as anywhere else.
- With a screen reader, the bar is read as a toolbar by its name, a tool that stays on as pressed or not pressed, a labeled zone as a named group, and a changing count is read out as it changes.
- In a right-to-left page, the arrows follow the reading direction.
- With text at 200% and the page 320 pixels wide, tools fold into the opener and overflow menu where the page marks them so.

### Keyboard

| Key | What it does |
|---|---|
| Tab | Moves focus into the bar, onto the tool used last or the first; pressed again, leaves the bar. A field in the bar keeps its own Tab stop. |
| Left Arrow or Right Arrow | Moves to the previous or next tool, following the reading direction. |
| Home or End | Moves to the first or the last tool. |
| Enter or Space | Presses the tool in focus. |

## Usage rules

### Do

- Name the bar for what it acts on.
- Order the tools by how often they are used, and group related ones.
- Keep one main action, at the end; put the rest in the overflow menu.
- Use the small size of every control in it.

### Don't

- Put two main actions in one bar.
- Make a command look pressed: only a toggle stays on.
- Hide every tool behind unnamed icons.
- Put more than one text field in one bar: each is a Tab stop of its own.
