- ds
- Agent
- Activity rail
Activity rail
The 44px icon strip at the edge of a workbench: areas, toggles, badges and a 2px current bar.
Code
<nav class="rail" aria-label="Areas">
<div class="rail-top">
<button class="rail-item" type="button" aria-label="Sessions" aria-current="true" data-tip="Sessions Ctrl 1" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/></svg></button>
<button class="rail-item" type="button" aria-label="Files" data-tip="Files Ctrl 2" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg></button>
<button class="rail-item" type="button" aria-label="Search" data-tip="Search Ctrl Shift F" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg></button>
<button class="rail-item" type="button" aria-label="Agents, 2 running" data-tip="Agents" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg><span class="rail-badge" aria-hidden="true">2</span></button>
<button class="rail-item" type="button" aria-label="Problems, 3 errors" data-tip="Problems" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg><span class="rail-badge down" aria-hidden="true">3</span></button>
</div>
<span class="rail-spacer"></span>
<button class="rail-item" type="button" aria-label="Sidebar" aria-pressed="true" data-tip="Hide the sidebar Ctrl B" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M9 3v18"/></svg></button>
<button class="rail-item" type="button" aria-label="Settings" data-tip="Settings Ctrl ," data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><circle cx="12" cy="12" r="4"/></svg></button>
</nav>The rail is the strip at the far left of a workbench: one 32px icon button per area, on a 44px column that never hides. The current area has a 2px accent bar on the outer edge and full-contrast ink; the rest are muted until hovered. Because the rail is always there, whatever it toggles can always come back: pressing the current area, or the sidebar toggle, shows or hides the sidebar.
Every item has an aria-label and a tooltip on the right. Put the shortcut in the tooltip, not in the label.
States
Code
<nav class="rail" aria-label="Rail states" style="height:auto">
<button class="rail-item" type="button" aria-label="Current area" aria-current="true" data-tip="Current area" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/></svg></button>
<button class="rail-item" type="button" aria-label="Idle" data-tip="Idle" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg></button>
<button class="rail-item" type="button" aria-label="Toggle, on" aria-pressed="true" data-tip="Toggle, on" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M15 3v18"/><path d="m10 15-3-3 3-3"/></svg></button>
<button class="rail-item" type="button" aria-label="Agents, one running" data-tip="Running work" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg><span class="rail-badge dot" aria-hidden="true"></span></button>
<button class="rail-item" type="button" aria-label="Notes, 12 unread" data-tip="12 unread" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg><span class="rail-badge plain" aria-hidden="true">12</span></button>
<button class="rail-item" type="button" aria-label="Problems, 128 errors" data-tip="128 errors" data-tip-pos="right"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg><span class="rail-badge down" aria-hidden="true">99+</span></button>
<span class="rail-sep"></span>
<button class="rail-item" type="button" aria-label="Extensions, not available offline" disabled><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 22v-5"/><path d="M15 8V2"/><path d="M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z"/><path d="M9 8V2"/></svg></button>
</nav>aria-current marks the area shown in the sidebar. aria-pressed="true" marks a toggle that is on, such as the inspector; it gets the wash but not the bar, so an area and a toggle never look the same. A badge carries a count (accent), errors (.down), a neutral count (.plain) or just activity (.dot). The count is decoration for sighted people: say it in the label too. A disabled item dims and drops out of the pointer.
Horizontal strip
Code
<nav class="rail h" aria-label="Areas">
<div class="rail-top">
<button class="rail-item" type="button" aria-label="Sessions" aria-current="true"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/></svg></button>
<button class="rail-item" type="button" aria-label="Files"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg></button>
<button class="rail-item" type="button" aria-label="Search"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg></button>
<button class="rail-item" type="button" aria-label="Agents, 2 running"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg><span class="rail-badge" aria-hidden="true">2</span></button>
</div>
<span class="rail-spacer"></span>
<button class="rail-item" type="button" aria-label="Settings"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><circle cx="12" cy="12" r="4"/></svg></button>
</nav>.rail.h lays the same items in a 36px row, with the bar on the bottom edge and tooltips below. Use it at the top of a sheet on a phone, where a 44px column would cost too much width.
API
| Class | On | What it does |
|---|---|---|
.rail | nav | The 44px column. Sunk background, a 1px rule on the inner edge. --rail-w and --rail-i set the column and item sizes. |
.rail-top | div | The group of areas at the top. |
.rail-spacer | span | Pushes what follows to the bottom: the sidebar toggle, settings, the account. |
.rail-sep | span | A 20px rule between groups. |
.rail-item | button, a | A 32px icon button with a 16px icon. |
aria-current="true" | .rail-item | The area on show. Ink, and the 2px accent bar on the outer edge. |
aria-pressed="true" | .rail-item | A toggle that is on. A wash, no bar. |
:disabled, aria-disabled="true" | .rail-item | Dims and removes the pointer target. |
.rail-badge | span | A 16px count on the top corner. .down for errors, .plain for neutral, .dot for activity with no number. |
.h | .rail | The 36px horizontal strip. The bar moves to the bottom edge and tooltips open below. |
- Five areas at most at the top; settings and the account at the bottom.
- Put the count in the label: "Problems, 3 errors".
- Let a press on the current area hide the sidebar, and a second press bring it back.
- Text labels in the rail. That is the sidebar.
- Hiding the rail to save 44px. Then a hidden sidebar has no way back.
- A badge with no matching words in the label.
Accessibility
- Use a
navwith anaria-label, and real buttons or links. The order in the DOM is the order on screen. - The bar is a shape and the icon turns full ink, so the current area is clear without colour. Screen readers hear
aria-current. - Focus shows a 2px accent ring inside the button. The tooltip opens on focus as well as hover, after the same short delay.
- Under coarse pointers the column grows to 48px and the items to 40px.
- The badge is hidden from assistive tech; its number is in the label.