Sidebar nav item
The row the left navigation is made of. Three kinds, one rhythm: a top-level row (.as-row), a section divider (.as-grp) and a sub-item (.as-sub) — plus the split "parent" variants whose body navigates and whose chevron folds. CSS apps/web/src/ds/app-shell.css; the React implementation is WorkspaceNav / NavGo in apps/web/src/components/AppShell.tsx (app-side, not in @acrm/ui).
The navigation is one flat model (NavItem[]), not a nested tree: depth is expressed by the item kind and its indent, so a row can move between levels without being re-parented.
When to use
- Any destination in the left navigation of a workspace: a section (Obchody, Lidé), a saved segment under it, or a group heading that folds a block.
- A row that both navigates and folds — that is the split parent variant.
When not to use
- Tabs inside a record or a page — that is Tab strip.
- A menu that opens on click — that is Popover / Picker menu.
- A settings sub-navigation: settings has its own rail (
.set-rail,apps/web/src/ds/settings.css), a separate family. - An action (create, export). The navigation navigates; actions live in the Section top bar.
Anatomy
- Row
.as-row:height: var(--row-h-nav),padding: 0 var(--sp-3),gap: 10px,radius-md,500 13px, text--ink-700, icon 16px in--ink-500. Hover--hover-surface; active--active-surfacewith--ink-900text. - Group
.as-grp: quiet divider with a chevron that rotates when folded (.chev.col); it keeps its top margin so the block above stays separated. - Sub-item
.as-sub: a leading tile.sg(the segment's colour) or the wizard.wand, then the label; indents.lvl1/.lvl2. - Split parent (
.as-row.parent/.as-sub.parent): two sibling controls —.as-row-nav(link) and.as-row-chev(button). They are siblings on purpose: a button inside a link is invalid HTML and would fire twice. - Count
.as-navcnt(NavItem.quietCount): a quiet number at the end of the row,--fg-muted/--small, no capsule;--ink-700on the active row; zero is not drawn. An optional category dot.il-dotsits before it (NavItem.dot). Úkoly counts only my tasks due today + overdue (open, in progress, blocked). - Critical badge
.acrm-pill.sm.critical(NavItem.badge): the only capsule in the sidebar, for a queue that needs action (Komunikace Důležité). Never drawn together with the quiet count. - Row actions on saved lists:
⋯= canonical MenuButton (Přejmenovat · Duplikovat · separator · Smazat danger with Confirm „Smazat seznam?“ / „Seznam „…“ se nevratně smaže.“), a sibling of the link; on hover on desktop (24 px compact), always visible on touch with a 44 px target. Duplikovat only for filter lists. Section header Seznamy has+(Seznam lidí / Seznam institucí → wizard). - Top block: six daily queues (Dashboard, Úkoly, Kalendář, Email, Setkání, Aktivita); rarely used reports (Statistika hovorů, Kariéra) live in the folded group Přehledy (acrm !4319, measured by 7-day API usage).
- Footer
.as-side-foot: the rail toggle, outside the scrolling nav. - Rail (
.as-side.rail, ≥901px): icon-only, 56px; labels, groups, sub-items and chevrons are hidden and the name survives astitle/aria-label.
Collapsible section, dots, bare glyphs (Komunikace, 2026-10-20)
- Section "Další" (
.as-grp.as-more): a collapsible heading styled like "Chaty", collapsed by default. It holds rarely used views; collapsed, it shows the count of hidden unread items on the right. The active hidden view is shown as a copy above it. Rows drag within and between groups and move with Alt+↑/↓ (the move is announced in an aria-live region). No ⋮ menu on views. sgDot— a colour dot in the label colour instead of a tile (labels).sgPlain— a bare muted glyph (the "+ New …" rows).sgTint— a bare glyph in the channel colour (chats). A folder keeps a tile in its own icon and tone, greyfolderby default.- Token
--ic-mint(#34c759) is the SMS channel colour.
Menu axis and sharing badge (AD 2026-10-24, acrm !5560)
- One axis on the right. The row chevron (
.as-row-chev), the sub-row chevron (.as-sub-chev) and the sub-menu ⋯ (.as-sub-more) share one vertical axis. The ⋯ sits exactly where the count is; the count hides while you hover or while the menu is open, so the two never stand side by side. - Sharing badge
.as-sharedhas one meaning only: this subject is shared with other users. Don't reuse it for delegation direction, status or ownership. Who and at what level must be reachable on touch too (⋮ or the detail), not only in a hover tooltip. - Counts stay quiet (
.as-navcnt). The only coloured capsule in the menu is.acrm-pill.sm.critical; amber or blue capsules are not part of the canon.
Best practices
Do
- Give every row an icon — in the rail it is the only thing left.
- Keep the active row tied to how the screen was opened, not to the raw URL: opening a contact from Hovory keeps Hovory highlighted.
- Fold with the chevron, navigate with the body; never make one control do both.
- Let a group disappear when everything in it is hidden by permissions (
withoutEmptyGroups) — an empty heading is noise.
Don't
- A row without a destination that only opens a menu; that is a control, not navigation.
- A second colour system in the sidebar — the segment tile is the only coloured mark.
- A count on a row that is not a queue: numbers belong where the user is expected to act (Pošta, Úkoly).
- A coloured capsule for an ordinary count; only the critical badge is a capsule.
- A menu item that does nothing yet (e.g. Do oblíbených before favourites exist).
- Deep nesting: two indents are the floor plan, a third is a sign the model is wrong.
Content
- Labels are nouns in sentence case, as short as they can be while staying unambiguous:
Obchody,Poznámky,Bonitní Pražané. - Group headings are one word where possible (
Obchod,Nastavení). - No counts in labels ("Úkoly (3)") — the quiet count carries the number.
Related
top-bar— the bar above the sidebar.drawer-slot— the panel slot next to the page.section-top-bar— the per-screen bar, not part of the shell.- Stories:
components--sidebar-nav-item--default,--variants,--states,--with-icon-and-kbd,--composition.