Section top bar — accessibility
Keyboard
- Every control in the bar is a real
<button>or<input>; Tab walks identity → view controls → search → actions → primary action, which is the reading order of the bar. - Chips that open a menu carry
aria-haspopupandaria-expandedthrough the control that opens them; Escape closes the menu (Popover's contract). - The search is a normal input: typing filters, Escape is left to the screen.
- Inline rename: Enter commits, Escape cancels, and both stop propagating so the record's own Enter/Escape handlers do not fire as well. Blur commits only if Enter has not already done it (a latch prevents double-saving).
- The bar has no shortcut of its own; a shortcut belongs to the action that answers to it.
ARIA
- The bar is a plain container; its accessible structure comes from the controls inside. The identity is a heading-level text, not an
<h1>— the page supplies its own heading semantics. SectionTopBarChipsetsaria-haspopup="menu"andaria-expandedonly when it is a menu trigger (chevron/open), so a plain toggle chip is not announced as a menu.- The search input is named by
ariaLabel; the placeholder is not a name. - Rename mode swaps the text for an input with an accessible name from
renameAriaLabel; whilerenamingthe input is disabled and cannot be reopened. - Dev-only warnings guard the semantics that matter: identity missing,
onRenamecombined with a dropdown,iconcombined with a click handler.
- Phone ⋮:
IconButtonnamed „Další akce" witharia-haspopup="menu"/aria-expanded; its bottom sheet is titled „Další akce". - Filtr icon button on a phone: its visible label is hidden, so the name carries both — „Filtr, aktivní podmínky: N".
Focus
.tbar-pos.is-linkand.tbar-markdeclare their own:focus-visiblering inds.css; everything else in the bar is a<button>and takes the foundation ring (outline: 2px solid var(--accent); outline-offset: 1px).- The search box shows focus through
:focus-withinon the wrapper (accent border) rather than a ring on the input. - Entering rename mode moves focus into the input and selects nothing — the caret lands where the user clicked.
Contrast
Computed from packages/ui/src/tokens/tokens.css:
- Identity name: ink on
--surface-100= 17.59:1 light, 14.53:1 dark. - Chip value
.vink = 17.59:1 light; chip key.k--fg-muted= 2.85:1 light, 3.63:1 dark — below AA for text, the value carries the meaning. - Chip border
--border-strongon--surface-100= 1.38:1 light — hairline, below the 3:1 non-text minimum. - Search placeholder
--fg-muted= 2.85:1 light. - Focus ring
--accent= 4.44:1 light, 3.83:1 dark — passes 3:1.
Phone view row (acrm !4114)
- Icon-only tools in row 2 (Seskupit, Řadit, search) have an
aria-label; when Seskupit or Řadit is off its default, the label and thetitlecarry the chosen option („Řadit: Termín") — the accent dot is decorative and never the only signal. - The tools open a bottom sheet (
role="menu", rowsmenuitemradiowitharia-checked); the sheet is closed by „Hotovo", the scrim or Escape. - Expanded search has its own
aria-labeland a labelled × („Zavřít"); closing clears the query.
Known limits
- Muted keys and placeholders sit at 2.85:1 in light theme.
- No disabled style exists for a chip or the search; a control that cannot be used has to be left out instead.
- On a narrow screen the bar scrolls sideways: a control can be off-screen with no visual hint other than the cut edge.
- Screens that hand-roll the identity (status star, logo trigger, colour swatch) bypass the component's guardrails, so their semantics depend on the screen.
Source: docs/section-top-bar/section-top-bar.a11y.md · GitLab