Review kategorie Navigation — nálezy, bug list, rozhodnutí pro AD

Datum: 4. 9. 2026 · zdroj pravdy: origin/main acrm (/root/acrm-main) · web: <http://192.168.230.131:3777/ds/components/app-shell/sidebar-nav-item?preview=ds-navigation-stories>

Rodiny: App shell (Sidebar nav item, Top bar, Drawer slot) · Section top bar (bar, Title with entity tile) · Tabs (Tab strip, Record tabs). Sedm podkomponent, dosud nula ukázek na webu.

0. Shrnutí

Navigace je paradox: je to nejvíc opsaná část systému (app-shell.css je port 1:1 s poznámkou „needituj ručně", Section top bar má v hlavičce rozhodovací tabulku i vývojářská varování, Record tabs mají tři vrstvy skladby tabů) — a přitom na DS webu nebyla vidět vůbec. Vady, které jsem našel, jsou drobné, ale dvě z nich jsou toho druhu, který se sám nikdy neopraví: mrtvý kus CSS a jméno ikony, které neexistuje.

1. Nálezy per podkomponenta (ověřeno v kódu)

1.1 Sidebar nav item (AppShell.tsx → WorkspaceNav/NavGo, ds/app-shell.css)

  • Řádky jsou skutečné <a>/<button>, aktivní nese aria-current="page". Focus ring není vada: app-shell.css výslovně jen strhává nativní chrome tlačítka a outline nevypíná, takže platí základní ring z ds.css.
  • .as-row .notif a .as-row .count jsou mrtvé — v CSS jsou plně nadefinované, v JSX je nikdo nekreslí. Počty se dnes sázejí jako .acrm-pill.blue.sm / .amber.sm.
  • Výchozí ikona řádku je circle, která v rejstříku ikon není (AppShell.tsx: <Icon name={n.icon ?? 'circle'} />). Položka bez ikony tedy tiše spadne na náhradní glyf.
  • Rail (ikonový sidebar) je jen ≥901px; pod tím je off-canvas. Obojí je otestované, ale nikde vidět.
  • Nastavení mají vlastní paralelní rail (.set-rail, ds/settings.css) — jiná rodina tříd na tutéž práci.

1.2 Top bar (AppShell.tsx → TopBar)

  • Třísloupcová mřížka 1fr minmax(280px,560px) 1fr drží hledání uprostřed nezávisle na tom, co přibude po stranách — dobré rozhodnutí, které nikde nebylo zapsané.
  • .as-ai-trigger je v CSS kompletní, ale appka mountuje jen .as-ai-btn; komentář v kódu říká, že jméno je „rezervované". Rezervovaná, nepoužitá varianta v kanonu je dluh.
  • Hledání je <button>, ne <input> — správně (otevírá paletu), ale vypadá jako pole; v docs je to teď napsané.

1.3 Drawer slot (ds/app-shell.css, shell/ShellDrawer.tsx, drawer/use-drawer-side.ts)

  • Slot se nikdy neodmountuje (jen skryje), takže obsah přežije zavření — stejný kontrakt jako u stavů okna dialogu. Strana se volí podle toho, kde uživatel klikl (panel nezakryje řádek, který ho otevřel).
  • .as-drawer.full je mrtvý kód — podle komentáře od P276 nemá konzumenta.

1.4 Section top bar (packages/ui/src/components/SectionTopBar.tsx)

  • Nejlépe „zamčená" komponenta v systému: rozhodovací tabulka v hlavičce + warnMisuse na tři chybné kombinace. To je vzor pro ostatní rodiny.
  • .plpage .tchip (pipeline) je metrická odchylka od kanonu: padding 8px místo 10px, gap 6px místo 7px, výška i velikost ikony zapsané v px místo tokenů. Chip v pipeline je tedy užší než chip všude jinde.
  • Čtyři obrazovky (PersonRecordPage, CompanyRecordPage, TeamDetailPage, ClenTymuPage) používají bar, ale identitu si kreslí ručně z .tbar-id/.tbar-h/.tbar-mark, protože potřebují něco navíc (hvězdička stavu, spouštěč loga, barevný vzorek). Únikový východ je legitimní, ale obchází všechna varování komponenty.
  • Story „DetailBar" v legacy přehledu ukazuje „N z M" — tedy přesně to, co si bar sám zakazuje (výjimka pro navigační šipky mezi záznamy je zdokumentovaná, ale na webu vypadá jako povolení).

1.5 Title with entity tile

  • Pět identit, právě jedna povinná — a komponenta to hlídá. Přejmenování má západku proti dvojímu uložení (Enter + blur) i proti oživení zrušené editace.
  • Chybí chybový stav přejmenování: renaming umí „ukládám", ale „nepovedlo se" musí vyřešit obrazovka.

1.6 Tab strip (packages/ui/src/components/TabStrip.tsx)

  • Plně řízený, role="tablist" + role="tab" + aria-selected. Přetečení řeší sám (měří scroll, rozsvítí okraj a šipku, posune o ~60 % šířky).
  • Mezi taby nejezdí šipky. Vzor tablistu očekává ←/→ a Home/End; dnes je každý tab vlastní zastávkou tabulátoru.
  • Taby nejsou svázané s panelem — chybí aria-controls / role="tabpanel".
  • Není disabled — ani prop, ani CSS. To je v pořádku jako rozhodnutí, jen to nikde nebylo napsané (teď je).

1.7 Record tabs (record/RecordTabsRow.tsx, record/record-tabs.ts)

  • Tři vrstvy skladby (katalog typu záznamu → produkční pořadí → osobní pořadí a skrytí) plus automatika „prázdný tab se schová" a rozlišení undefined (načítá se) vs 0 (opravdu prázdný). Tohle je nejchytřejší kus rodiny a nikde to nebylo popsané.
  • Řazení tabů v ⚙ je jen tažením — klávesnicí nepřestavitelné.

2. Bug list — DS (web, registr, stories, docs)

#NálezStav
D1Celá kategorie Navigation neměla per-sekci stories (0/7)OPRAVENO (7 souborů, 32 stories)
D2Chyběly usage.md a a11y.md pro všech sedm podkomponentOPRAVENO (14 souborů)
D3Katalog Ladle nenačítal ds/app-shell.css → .as-* nešlo ukázatOPRAVENO (provider)
D4Registr neříkal, že App shell i Record tabs žijí v appce, ne v @acrm/uiOPRAVENO (notes)
D5Nikde nebylo zapsané, co bar zakazuje (počet, breadcrumb, dva primáry) ani pročOPRAVENO (usage)

3. Bug list — aplikace (kanon v kódu)

#NálezNávrhKdo rozhodne
A1.as-row .notif / .count = mrtvé CSSsmazat, počty už kreslí .acrm-pillhotovo 11. 9. 2026 — acrm !3403 (appka i zrcadlo)
A2Výchozí ikona navigace circle v rejstříku neníbuď ikonu doplnit, nebo fallback změnit na existující jménoAD ano/ne (drobnost, ale tichá)
A3.as-drawer.full = mrtvý kód (bez konzumenta od P276)smazathotovo 11. 9. 2026 — acrm !3403 (appka i zrcadlo)
A4.as-ai-trigger = rezervovaná nepoužitá variantasmazat, nebo v kanonu napsat, kdy se má použítAD
A5.plpage .tchip má jiné metriky než kanon (8/6px vs 10/7px, px místo tokenů)srovnat s kanonem, nebo z odchylky udělat pojmenovanou variantuAD (vizuální změna v pipeline)
A6Čtyři obrazovky kreslí identitu baru ručněrozšířit SectionTopBarTitle o slot pro doplněk (hvězdička, logo, vzorek)AD
A7Tab strip: chybí šipky mezi taby a aria-controlsdoplnit do TabStrip.tsxAD ano/ne
A8Řazení tabů v ⚙ jen taženímdoplnit klávesovou alternativu (posunout nahoru/dolů)AD ano/ne
A9Nastavení mají vlastní rail .set-railsjednotit s .as-*, nebo zapsat do DS jako vlastní rodinuAD
A10Globální .ti (velikost a řádkování VŠECH ikon) deklarují TŘI sheety: ds/app-shell.css, ds/segment-screen.css a ds/auth.csssjednotit do jednoho pravidla (ds.css / index.css), kopie zrušithotovo 9. 9. 2026 — acrm 2e04c7d4c, globální .ti zůstalo jen v ds/app-shell.css

4. Rozhodnutí pro AD

  • N1 — sedm podkomponent Navigation jako kanon. Schválit podle ukázek na webu. Doporučuji ano.
  • N2 — úklid mrtvého CSS (A1+A3+A4 jako jeden balík). Doporučuji ano — tři kusy kódu, které nikdo nekreslí, a jeden z nich (.as-ai-trigger) svádí k použití.
  • N3 — .plpage .tchip (A5). Doporučuji srovnat s kanonem. Chip má být všude stejný; pokud pipeline opravdu potřebuje užší, ať je to pojmenovaná varianta, ne scoped kopie.
  • N4 — klávesnice v tabech (A7). Doporučuji ano, je to jedna oprava na jednom místě a týká se každého záznamu v systému.
  • N6 — tři kopie globálního .ti (A10). Doporučuji sjednotit do jednoho pravidla. Dnes se hodnoty shodují, takže se nic nekreslí jinak; jde o pojistku do budoucna — tři globální pravidla na tutéž věc znamenají, že o velikosti ikon rozhoduje pořadí načtení sheetů.
  • N5 — slot v identitě baru (A6). Doporučuji ano — čtyři obrazovky dnes obcházejí guardrails komponenty jen kvůli jednomu doplňku.

5. Co teď

  1. MR do acrm polish/ds-navigation-stories — stories + zpřístupnění app-shell.css katalogu.
  2. DS repo: registr, docs, tenhle review.
  3. Po schválení: approvedAt, pak N2–N5 jako samostatné MR (N3 a N5 mění vzhled, ty chtějí tvoje oko).

Source: docs/REVIEW-navigation-family.md · GitLab