A wrapping row of controls with groups, attached (segmented) groups, separators, and a spacer to push actions to the end. Toggle buttons use aria-pressed.
Structure
| Class | Description |
|---|---|
| .mdst-toolbar | Wrapping row of controls. Form controls inside size to their content |
| .mdst-toolbar-group | Keeps related controls together with a tighter gap |
| .mdst-toolbar-spacer | Empty element that pushes everything after it to the far end |
| .mdst-toolbar-separator | Vertical rule between groups. Use on <hr> or an element with role="separator" |
Modifiers & States
| Class / Attribute | Example |
|---|---|
| .mdst-toolbar-group--attached | |
| aria-pressed="true" | |
| .mdst-toolbar--bordered |
Table Toolbar
Interactive Demo: Formatting Toolbar
role="toolbar" tells assistive tech to expect arrow-key navigation, so the JavaScript below toggles
aria-pressed and adds a roving tabindex: Tab enters the toolbar once,
arrows move between controls. It is not part of modest-ui. If you don’t add arrow-key handling, leave
role="toolbar" off and use a plain container.
The quick brown fox jumps over the lazy dog.
Demo source
const toolbar = document.querySelector("#toolbar");
const items = [...toolbar.querySelectorAll("button")];
// Roving tabindex: only one control is in the tab order at a time
items.forEach((item, i) => (item.tabIndex = i === 0 ? 0 : -1));
toolbar.addEventListener("keydown", (event) => {
const keys = { ArrowRight: 1, ArrowLeft: -1, Home: "first", End: "last" };
if (!(event.key in keys)) return;
event.preventDefault();
const current = items.indexOf(document.activeElement);
const step = keys[event.key];
const next =
step === "first" ? 0 :
step === "last" ? items.length - 1 :
(current + step + items.length) % items.length;
items[current].tabIndex = -1;
items[next].tabIndex = 0;
items[next].focus();
});
// Independent toggles (bold, italic, underline)
toolbar.querySelectorAll("[data-style]").forEach((button) => {
button.addEventListener("click", () => {
const pressed = button.getAttribute("aria-pressed") === "true";
button.setAttribute("aria-pressed", String(!pressed));
});
});
// Exclusive toggles (alignment): exactly one is pressed
const alignButtons = toolbar.querySelectorAll("[data-align]");
alignButtons.forEach((button) => {
button.addEventListener("click", () => {
alignButtons.forEach((b) => b.setAttribute("aria-pressed", String(b === button)));
});
});
Usage
<!-- Filters on the left, actions pushed to the right -->
<div class="mdst-toolbar">
<input type="search" class="mdst-input" placeholder="Search…" aria-label="Search" />
<div class="mdst-toolbar-spacer"></div>
<div class="mdst-toolbar-group">
<button class="mdst-button">Export</button>
<button class="mdst-button mdst-button--inverted">Add</button>
</div>
</div>
<!-- Attached toggle group with a separator -->
<div class="mdst-toolbar mdst-toolbar--bordered" role="toolbar" aria-label="Formatting">
<div class="mdst-toolbar-group mdst-toolbar-group--attached">
<button class="mdst-button mdst-button--sm" aria-pressed="true">B</button>
<button class="mdst-button mdst-button--sm" aria-pressed="false">I</button>
</div>
<hr class="mdst-toolbar-separator" />
<button class="mdst-button mdst-button--sm mdst-button--ghost">Undo</button>
</div>