ACRM Design System — analýza stavu a plán přestavby na špičkový DS
Datum: 2. 9. 2026 · pro Štěpána (Art Director) · vzor kvality: atlassian.design Čísla jsou změřená (skripty v této session), ne odhadnutá. Zdroj appky =
origin/mainacrm (ne checkout/root/crm, který je 1 119 commitů pozadu).
0. Shrnutí
Diagnóza. To, čemu říkáme „kanon DS", je export z claude.ai/design: 97 HTML mockupů, tři paralelní kopie CSS a vlastní JavaScriptové „enginy", které znovu implementují obrazovky appky. Od exportu (9. 8.) se 35 z 36 komponentových karet nezměnilo, zatímco appka udělala 354 commitů do DS kódu. Tokeny naopak sedí (136 tokenů, shoda s tokens.css na mainu až na uvozovky). Pravda o komponentách dnes žije v kódu — @acrm/ui (39 komponent, typované props, 33 stories, 66 vizuálních snímků) a ds/*.css — a RULES §0.1 to už dnes říká: „zdroj pravdy je reálná appka, portuj z ní". DS web (fáze 1 z dneška) má správnou kostru, ale ukazuje zastaralé mockupy.
Cíl. DS na úrovni vzoru: rodiny komponent → podkomponenty, každá se stejnou anatomií stránky (Examples · Code · Usage · Accessibility · Changelog), příklady = živé komponenty z kódu s ukázkou kódu, props tabulky generované z typů, usage s Do/Don't, verzování a changelog, distribuce balíčkem do všech rep.
Cesta. Otočit zdroj pravdy na kód (packages/ui = komponenty + tokeny + stories + styly), DS repo = dokumentace + registr + web, HTML export → legacy/. Pět fází, měřitelné „hotovo" u každé komponenty, appka se konsoliduje ratchetem, distribuce balíčkem @acrm/ui místo zrcadel. Detail v §5–§8.
1. Současný stav — DS interně (/root/ds-export/extracted, repo acrm/design-system)
1.1 Obsah
| Položka | Stav | Hodnocení |
|---|---|---|
| Karty | 97 HTML (95 s @dsCard), 91 v manifestu: 19 Foundations · 36 Components · 27 Screens · 8 Registrace · 1 Shell; 6 mimo manifest | Struktura plochá, „karta" = mockup, ne dokumentace |
| Stáří | 35/36 Components karet netknuto od exportu 9. 8.; appka od té doby 354 commitů do packages/ui/src/components + apps/web/src/ds (RecordRail 10×, EntityPreview 9×, DealCard 7×, TaskList 5×, Dialog 3×…) | Karty jsou snímek léta, ne pravda |
| Tokeny | colors_and_type.css 136 tokenů vč. dark bloku = tokens.css na mainu (liší se jen uvozovky/mezery ve 4 hodnotách) | ✅ jediná vrstva, která sedí |
Enginy _ds/ | 18 CSS (2 497 ř.) + 14 JS (2 956 ř., segment-screen.js 52 KB) — vanilla JS, které kreslí obrazovky do mockupů | Druhá implementace appky; nikdo ji nespouští v produktu |
rt-real/ | 11 souborů, 11 285 řádků zkopírovaného app CSS | Třetí kopie téhož CSS |
| Kvalita mockupů | 1 857 inline style="", 836 použití app tříd .acrm-* smíchaných s vlastními | Mockupy nejsou strojově porovnatelné s appkou |
| Duplicity konceptu | entity-ref ×3 karty, dialog ×6, taby ×3 (tabs, Record tabs (unified), Record tabs – handoff), výpisy ×3 (Record list, list-view, table-row), Person detail ×2 | Jeden vzor = víc karet → čtenář neví, která platí |
| Pracovní dokumenty jako karty | „Tab system – plán sjednocení", „Record tabs – handoff", „Person detail – migrated (ukázka)", 3 karty „(návrh)" | Kanon obsahuje ne-kanon |
| Balast | uploads/ 20 MB (120 souborů), screenshots/ 1,5 MB (41), vnořený legacy bundle 972 KB, _zachraneno 1 MB | ~85 % objemu repa není DS |
| Jazyk | názvy karet 69 EN / 22 CZ, skupina „Registrace", popisky CZ | Nekonzistentní; web je EN |
| Dokumentace | RULES.md (18 KB, silná pravidla: containment budget, jeden accent, App Shell master…), CONSOLIDATION.md, DS_UPDATE_CHECKLIST.md; popis karty = 1 věta až odstavec v @dsCard subtitle (medián 200 znaků, max 664) | Pravidla existují, ale nejsou navázaná na komponenty; žádná per-komponentová dokumentace (kdy použít, props, kód, a11y) |
| Verzování / changelog | git až od 2. 9. 2026; před tím nic | Historie designových rozhodnutí je jen v paměti a v MR appky |
| Stavový životní cyklus | „(návrh)" v názvu; jinak nic (kandidát/beta/kanon/zastaralé) | Nelze rozlišit platné od rozpracovaného |
1.2 Vazba na appku (měřeno ds:sync-check + porovnání souborů)
- Zrcadlo v repu (
packages/ui/reference/screens): 20 karet z kanonu chybí, 23 se liší, 8 enginů_ds/*se liší → zrcadlo je kurátorská, zastaralá podmnožina. ds:sync-check(29 portů): 0 hodnotových driftů proti zrcadlu, ale 161 neadoptovaných selektorů (Person detail 82, segment-screen 22, app-shell 16), 85 chybějících, 148 schválených odchylek (ds-ok). Appka od karet vědomě odchází.
Závěr §1: Interní DS není systém, je to archiv designových záměrů z jedné epochy + tři kopie CSS. Tokeny a pravidla mají hodnotu; mockupy a enginy ne.
2. Současný stav — prezentace (:3777/ds, fáze 1 z 2. 9.)
| Co je | Stav |
|---|---|
| IA | Home · Get started · Rules · Foundations (tokeny z CSS) · Components v 7 schválených kategoriích · Patterns · Adoption · Candidates · Changes; strom v levé navigaci; ⌘K hledání; EN UI ✅ |
| Stránka komponenty | 4 taby (Examples · Usage · Code · Status); Examples = jeden iframe mockupu; Usage = subtitle + CSS komentáře; Code = import + třídy + port; Status = zrcadlo + kde se používá ✅ kostra |
| Chybí proti vzoru | úroveň rodina → podkomponenta (Button → Icon button → Split button); příklady per stav s kódem; props tabulky; snippety; Accessibility; changelog a verze per komponenta; lozenge stavu (beta/GA/deprecated); dark-mode přepínač (tokeny ho mají, appka ho používá v 18 souborech); Content guidelines; Contributing; Release notes; obsah CZ/EN smíšený |
Závěr §2: kostra webu je správná a stojí na tokenech; obsah, který ukazuje, je špatný (mockupy). Web musí číst z kódu.
3. Aplikace a reálná implementace kanonických komponent (origin/main)
3.1 Co existuje
| Vrstva | Rozsah | Poznámka |
|---|---|---|
packages/ui (@acrm/ui) | 39 komponentových souborů, 8 050 řádků; exporty: Button, IconButton, Input, Textarea, Field, Select, MultiSelect, Combobox, RecordSelect, NavSelect, PickerMenu, Popover, Tooltip, Dialog, Confirm, DrawerForm/DrawerField, Segmented, Checkbox, TabStrip, DateField/TimeField/DateRangeField/DateTimeRangeField/Calendar/PickerPanel, RecordList, RecordRail/EditableField, TaskList, DealCard, Avatar, EntityRef, EntityPreview, EmptyState, ErrorState, Skeleton, Loader/ListLoader, DetailStateScreen, SectionTopBar, ds-icons | Typované props (ButtonProps: variant primary·default·ghost·danger, kbd, loading…) → props tabulky jdou generovat |
| Tokeny | tokens.css 310 ř., 136 tokenů, dark blok | = kanon |
| Sdílené třídy | ds.css 2 808 ř., 457 selektorů .acrm-* (input, inputwrap, textarea, slider, radio, switch, optchip, taginput, rmchip, checkbox, segmented, select-trigger, popover, dialog 38 pravidel, tab(s), pill, count, avatar, dealcard, icobtn…) | Kanonické primitivy jako třídy |
| Obrazovkové vrstvy | ds/*.css 73 souborů, 31 055 řádků; prefixy .sgb- 168 · .kalendar- 161 · .mr- 150 · .acc- 150 · .dp- 139 · .dlr- 138 · .rr- 131 · .aichat- 127 · .as- 122 · .pr- 113 · .au- 110 · .nastaveni- 109 · .pdr- 104 … (25+ prefixových systémů) | Většina DS CSS je screen-specifická; enginy (record-rail, record-list, task-list, email-list, dialog-window, filter-bar, stat-tile, section-block, timeline, note-card, toast, notifications…) tu jsou, ale v appce, ne v balíčku → jiná repa je nemají |
| Katalog | Ladle: 11 story souborů, 33 stories; catalog:build existuje; vizuální CI: 66 snímků (33 × light/dark) | Základ pro živé příklady; pokrytí ~1 story na komponentu, ne per stav |
| Brány CI | ds-validate = ds:validate:strict + ratchet (baseline 80 souborů: DIM 835 · TYPE 183 · TONE 12 · suppressed 361) + ds:index:check + ds:sync-check --check; visual (Ladle × Playwright); validate-ds-usage 11 pravidel (4 hard) | Vynucování existuje a funguje — jen měří proti špatné referenci (zrcadlo) |
| DS index | 38 řádků: 35 OK · 2 ★ · 1 NÁVRH; 5 „app-only" (DrawerForm, Segmented, Empty/Error, DetailStateScreen, Skeleton) + řada komponent bez karty vůbec (Date rodina, Combobox, RecordSelect, MultiSelect, NavSelect, TabStrip, Loader, ListLoader) | Kód je před DS |
3.2 Dluh v appce
| Metrika | Hodnota | |
|---|---|---|
Inline style={{ v TSX | 1 250 ve 191 z 655 souborů | |
| Hex barvy v TSX | 17 | |
Schválené odchylky ds-ok | 462 v CSS + 84 v TSX = 546 | |
| Paralelní třídní systémy | 25+ prefixů; historicky 3 topbary (.sgb-top/.tbar/.acrm-page-head) — .sgb-top už migrován na SectionTopBar ✅ | |
| Komponenty bez story | ~½ exportů @acrm/ui (Date rodina, Combobox, MultiSelect, RecordSelect, Loader, TabStrip, SectionTopBar varianty…) | |
| Distribuce | @acrm/ui je private, main: ./src/index.ts — jiná repa ho nemohou nainstalovat; enginy CSS žijí v apps/web | Sdílení do jiných rep dnes technicky neexistuje |
Závěr §3: appka má skutečný, typovaný, testovaný komponentový systém a brány. Chybí mu (a) rozdělení „balíček vs. obrazovky" — enginy jsou v appce, (b) pokrytí stories per stav, (c) dokumentace, (d) publikace. To jsou přesně věci, které špičkový DS web potřebuje jako vstup.
4. Rozdíl proti vzoru (atlassian.design)
| Oblast | Vzor | My dnes | Mezera |
|---|---|---|---|
| Zdroj pravdy | kód (@atlaskit/*), web z něj generovaný | HTML export; kód odděleně | otočit |
| Hierarchie | Components › Button › {Button, Icon button, Link button, Link icon button, Split button, Button group} | 40 plochých karet v 7 kategoriích | rodiny + podkomponenty |
| Anatomie stránky | hlavička (název, věta, stav, balíček, odkazy: zdroj · npm · Figma · changelog) · taby Examples · Code · Usage · Accessibility · Changelog | 4 taby, bez props/a11y/changelogu | doplnit + sjednotit |
| Examples | pevný sled sekcí (Default · Appearance · Spacing · States · Icons · …), každý = živý render + přepínač kódu | 1 iframe mockupu | stories per sekce + snippet |
| Code | install/import, props tabulka (name · type · default · description) z typů | import + třídy | generátor z TS |
| Usage | When to use · When not · Anatomy · Best practices (Do/Don't páry) · Content · Related | subtitle | psát (máme AD rulingy jako zdroj) |
| Accessibility | klávesnice, ARIA, kontrast per komponenta | nic | psát + testovat |
| Stav a verze | lozenge (alpha/beta/GA/deprecated), semver balíčku, changelog per komponenta | „(návrh)" v názvu | životní cyklus + changesets |
| Foundations | tokeny s ukázkou, kopírování, dark | ✅ (od dneška) | dark přepínač na webu |
| Patterns | složené vzory s reálnými ukázkami | 27 ručních mockupů | reálné screenshoty + kompozice |
| Distribuce | npm balíčky, verze, migrace | zrcadlo HTML v repu + ruční port | balíček |
| Přispívání | Contributing, RFC/kandidát, release phases | candidates/ (od dneška) | proces + DoD |
5. Cílová architektura
acrm/acrm (monorepo) acrm/design-system (DS repo)
┌──────────────────────────────────┐ ┌──────────────────────────────────────┐
│ packages/ui = @acrm/ui │ build artefakty │ site/registry.json (rodiny → pod- │
│ ├ src/components (39+) │ ───────────────▶ │ komponenty → {react, třídy, stories,│
│ ├ src/tokens/tokens.css │ • ladle static │ status, since, docs}) │
│ ├ styles/*.css (enginy z ds/) │ • props.json │ docs/<family>/<sub>.usage.md │
│ ├ stories/** (per podkomp.) │ • tokens.css │ docs/<family>/<sub>.a11y.md │
│ └ CHANGELOG (changesets) │ • git changelog │ patterns/*.md + screenshoty devu │
│ apps/web = obrazovky (jen │ │ rules/*.md (RULES rozdělený) │
│ kompozice, žádný vlastní styl) │ │ site/ (renderer :3777/ds, CSS) │
│ CI: ds-validate · visual · ratchet│ │ legacy/ (HTML export, read-only) │
└──────────────────────────────────┘ └──────────────────────────────────────┘
│ publish @acrm/ui (GitLab package registry, semver)
▼
jiná repa: `pnpm add @acrm/ui` — tokeny + komponenty + enginy; žádné zrcadlo, žádný ruční portPrincipy
- Kód je pravda. Komponenta existuje, když má typovaný export v
@acrm/ui(nebo kanonickou třídu vstyles/), stories per stav a vizuální snímek. Mockup není důkaz. - DS repo = dokumentace, registr, web. Nic, co by muselo být duplikátem kódu. Web vše ostatní generuje z artefaktů buildu.
- Jedna rodina = jedna stránka na podkomponentu, stejná anatomie. Registr (
registry.json) je jediné místo, kde se definuje hierarchie a mapování na kód. - Distribuce balíčkem. Zrcadla a
ds:sync-checkskončí; nahradí je verze balíčku + changelog + migrace. - Export z claude.ai →
legacy/. Zůstane čitelný jako historie záměru; není linkovaný jako kanon; nic z něj se neportuje bez rozhodnutí AD.
6. Taxonomie: rodiny → podkomponenty (návrh, ukotveno v kódu)
Legenda: ✅ v kódu (@acrm/ui / .acrm-*) · ◐ v kódu jen jako obrazovková vrstva ds/*.css · ◯ jen v mockupu (kandidát).
Forms & input
- Button — Button (primary · default · ghost · danger) ✅ · Icon button ✅ · Split button ◯ · Save button (dialer completion) ◐ · Kbd hint ✅
- Text field — Input (text · email · url · code · number · short) ✅ · Textarea ✅ · Field (label · hint · error) ✅ · Input with icon/kbd ✅ · Slider ✅ · Tag input ✅ · Mention input ◐
- Select — Select ✅ · Multi-select ✅ · Combobox ✅ · Record select ✅ · Nav select ✅ · Picker menu ✅
- Choice — Checkbox ✅ · Radio ✅ · Switch ✅ · Segmented control ✅ · Option chips ✅
- Date & time — Date field ✅ · Time field ✅ · Date range ✅ · Date-time range ✅ · Calendar ✅ · Picker panel ✅
- Filter — Filter bar ◐ · Filter chip ◐ · Removable chip ✅
Overlays & dialogs
- Dialog — Dialog (s · m · l) ✅ · Confirm ✅ · Window states (modeless · compact · min) ◐ · Drawer form ✅ · Record drawer ◐
- Popover — Popover ✅ · Tooltip ✅ · Entity preview ✅
Navigation
- App shell — Sidebar nav item ◐ · Top bar ◐ · Drawer slot ◐
- Section top bar — Section top bar ✅ · Title with entity tile ✅
- Tabs — Tab strip ✅ · Record tabs ◐
Records & data
- Record list ✅ · 13. Record rail — Rail ✅ · Key-value row ✅ · Editable field ✅ · Multi-value ◐ · 14. Table — Segment table ◐ · Table row ◐ · 15. Task list ✅ · 16. Email list ◐ · 17. Deal card ✅ · 18. Stat tile ◐ · 19. Section block ◐ · 20. Timeline ◐ · 21. Note card ◐
Identity
- Avatar — person · company × 16/24/32 ✅ · 23. Entity reference — default · mini · removable ✅ (jedna komponenta, 3 varianty — dnes 3 karty)
States & feedback
- Empty state ✅ · 25. Error state ✅ · 26. Loading — Skeleton line · Skeleton list · Loader · List loader · Detail state screen ✅ · 27. Toast ◐ · 28. Notifications ◐ · 29. Status — Pill · Count badge ✅
AI
- AI assistant ◐ · 31. Discussion ◯ (návrh)
Výsledek: 31 rodin, ~75 podkomponent; z toho ✅ 44, ◐ 27 (přesun ds/*.css → packages/ui/styles + story), ◯ 4 (kandidáti).
7. Anatomie stránky podkomponenty (pevná, generovaná z registru)
Components › Button › Icon button
Icon button [canon ▾ since 0.3.0] @acrm/ui · <IconButton> Source · Story · Changelog
„Tlačítko, jehož význam nese ikona; vždy s tooltipem."
────────────────────────────────────────────────────────────────
Examples │ Code │ Usage │ Accessibility │ Changelog
────────────────────────────────────────────────────────────────
Examples = sekce v pevném pořadí per rodina: Default · Variants · Sizes · States (hover/focus/
disabled/loading/selected) · With icon/kbd · Composition; každá = živý render (Ladle
story v iframe) + přepínač „Code" se snippetem přesně té story.
Code = install/import · Props (name · type · default · description — z TS typů) · CSS classes
(kanonické třídy + tokeny, které komponenta používá) · Related.
Usage = When to use · When not to use · Anatomy (očíslované části) · Best practices (Do / Don't
páry s živým renderem) · Content (copy pravidla: sentence case, datum, částky…) · Related.
Accessibility = klávesnice · ARIA · fokus · kontrast (měřeno) · známé limity.
Changelog = commity mainu dotýkající se souborů komponenty + verze balíčku (changesets).
Vpravo: On this page · Implementation (verze, adopce per repo, počet použití).Do/Don't a Content se plní z existujících AD rozhodnutí (RULES §0–§10, pilulky-střízlivost, tabular-nums jen tabulky, konvence roku, kompaktní částky, popisek = --label, nápověda = --hint, mono jen výkazy, žádný eyebrow v menu, FilterBar = Notion model…) — obsah už máme, jen je rozptýlený v paměti a MR.
8. Postup přestavby (fáze, DoD, odhad)
| Fáze | Obsah | DoD | Odhad |
|---|---|---|---|
| 0 · Rozhodnutí + úklid | schválit §5 architekturu a §6 taxonomii; HTML export → legacy/, balast (uploads/screenshots/legacy bundle) mimo repo; site/registry.json kostra (31 rodin, 75 podkomponent, EN názvy, stav); RULES rozdělit do rules/ | registr existuje, web ho čte, každá podkomponenta má stránku (byť prázdnou) se správným místem ve stromu | 2 dny |
| 1 · Kód jako zdroj | na FE boxu čistý klon origin/main (timer fetch); pnpm --filter @acrm/ui catalog:build → /ds/catalog/; generátor props.json z TS (TypeScript compiler API) a changelog.json z gitu; web: Examples = stories z registru, Code = props + import, Changelog = git; lozenge stavu; dark přepínač | stránka Button rodiny je kompletní ze živého kódu; tokeny na webu z tokens.css mainu | 5 dní |
| 2 · Pokrytí rodin (iterativně, rodina po rodině, každá = MR do acrm + MR do DS) | per podkomponenta: stories per sekci (~5), vizuální snímek, usage.md (When/When not/Do–Don't/Content/Related), a11y.md, pravidlo do validate-ds-usage; ◐ položky = přesun CSS z apps/web/src/ds do packages/ui/styles + story | „hotová komponenta" = 5 artefaktů (story · snímek · props · usage · a11y) + zelené brány; web ukazuje % pokrytí | ~1 rodina/den pro ✅, 2–3 dny pro ◐ → 6–8 týdnů pro 31 rodin |
| 3 · Konsolidace appky (souběžně, ratchet) | inline styly 1 250 → 0; ds-ok 546 → revize (odchylka = buď nová varianta v balíčku, nebo pryč); 25 prefixových systémů → obrazovky skládají jen z balíčku; duplicity (3 topbary hotovo, další: dialogy, pilulky, výpisy) | ratchet baseline klesá každý týden; apps/web/src/ds obsahuje jen layout obrazovek | průběžně, 2–3 měsíce |
| 4 · Distribuce | @acrm/ui publikovat (GitLab package registry), semver + changesets, release notes na webu; konzumentská repa: pnpm add @acrm/ui, zrcadla a ds:sync-check zrušit; adoption matice z verzí | jiné repo postaví obrazovku jen z balíčku, bez kopírování | 3 dny + migrace konzumentů |
| 5 · Patterns & content | vzory obrazovek = reálné screenshoty devu (timer) + kompozice („z čeho je složeno"), 65 stránek → 4 skeletony (master šablony); Content guidelines (CZ copy); dark mode showcase; kandidátský proces jako RFC šablona; Figma až bude | Patterns bez ručních mockupů; každý vzor odkazuje na podkomponenty | 2 týdny |
Pořadí: 0 → 1 → (2 ∥ 3) → 4 → 5. Fáze 2 je největší a jediná, kde se píše obsah — ten schvaluje AD po rodinách, ne najednou.
9. Governance
- Role: Art Director (Štěpán) — schvaluje taxonomii, kanon, usage texty; DS maintainer (Claude/FE) — registr, generátory, web, brány; přispěvatel (kterýkoli tým) — MR do acrm (kód + story) a do DS (docs, kandidát).
- Životní cyklus:
candidate(MR vcandidates/) →beta(v balíčku, bez záruky API) →canon(5 artefaktů, brány) →deprecated(náhrada + migrace v changelogu) → odstranění. - Definition of done komponenty: story per sekci · vizuální snímek light+dark · props doc z typů · usage.md · a11y.md · usage pravidlo ve validátoru · záznam v registru.
- Pravidlo „kanon nahrazuje": nová varianta = stará mizí v témže MR (migrace), ne vedle sebe.
- Metriky na webu (Adoption): % podkomponent s DoD · dluh appky (inline styly, ds-ok, prefixy) · verze balíčku per repo.
10. Co rozhodnout teď (jedno rozhodnutí)
Schválit §5 (zdroj pravdy = kód, DS repo = docs + registr + web, export → legacy/) a §6 (31 rodin / 75 podkomponent). Po schválení začnu fází 0 a 1 (Button rodina end-to-end jako pilot, ~1 týden). Názvy podkomponent, pořadí sekcí v Examples a texty usage se ladí na webu pickerem, rodina po rodině.
Source: docs/ANALYZA-a-PLAN-spickovy-DS.md · GitLab