Record tabs
canonRecord tab row: tab strip plus „+ N další“ overflow and a personal layout; an empty tab drops out, a loading one does not.
React implementation lives in the app (record/RecordTabsRow.tsx + record-tabs.ts); it uses TabStrip internally and adds the overflow trigger and the layout menu. 14 Oct 2026 (owner "24g scvaleno", proto/zalozky-jeden-ovladac@489bb3bd6, acrm !5043): ONE icon button „Záložky" with a count badge of hidden tabs replaces „+ N další" and ⚙; its menu lists all tabs — name = open, switch = show/hide, grip/Alt+↑↓ = order; phone = bottom sheet with „Hotovo". Badge --accent-press + white, 5.73:1. Dev check 14 Oct 1440 + 390 (company Druid): badge 8, 15 switches, sheet ok.
Used in 4 files · 4 areas · 4× — components/company, pages/CompanyRecordPage, pages/ObchodDetailPage, pages/PersonRecordPage
Keyboard
- The strip behaves exactly as Tab strip does: each tab is a
<button role="tab">, arrow keys and Home/End move focus within one tab stop, Enter and Space switch. - The overflow trigger is a button that opens a canonical popover: Enter opens, Escape closes.
- The gear is an icon button with an accessible name. Reordering: Alt+↑/↓ on a focused row moves it by one place and saves; focus stays on the moved row and a polite live region announces "<label>: position N of M". At an edge nothing is saved, the position is only announced. Dragging does the same thing with a pointer (NAV-3, 11 Sep 2026).
ARIA
- The row itself is a plain container; the semantics come from
TabStrip(role="tablist"/role="tab"/aria-selected). - No
aria-controlshere: the strip lives inRecordTabsRowand the panels in the record page, so the strip has no panel id to point at. - The overflow trigger is announced by its own text („+ 3 další“), so the number of hidden tabs is available without opening it.
- Counts are read as part of the tab's name; a loading count is simply absent rather than announced as zero.
- The gear's menu is a list of toggles; the state of each is carried by the toggle, not by the row's appearance.
Focus
- Foundation ring from
ds.csson every control in the row (tabs, overflow trigger, gear). - Picking a tab from the overflow closes the menu and switches the tab; focus returns to the trigger, not to the newly active tab.
- The active tab is forced into the visible part of the strip, so focus never lands on a tab hidden behind the fade.
Contrast
Computed from packages/ui/src/tokens/tokens.css:
- Tabs: as in Tab strip — active tab ink plus the accent underline (
--accent= 4.44:1 light, 3.83:1 dark), inactive muted. - Overflow trigger: quiet link-like button in muted ink; it is text, so it inherits the same limit as other muted text (2.85:1 in light theme).
- Gear: icon button in
--fg-muted— below the 3:1 non-text minimum in light theme, with hover raising it. - Row hairline
--border: below the 3:1 boundary minimum, as every hairline in the system.
Known limits
- No
aria-controlswiring to the panel (it lives outside this component). - The overflow trigger and the gear are muted (2.85:1 in light theme).
- Hiding a tab is still silent; reordering is announced.
Source: docs/tabs/record-tabs.a11y.md · GitLab