Review rodiny Popover — nálezy, bug list, rozhodnutí pro AD
Datum: 4. 9. 2026 · zdroj pravdy: origin/main acrm (/root/acrm-main, ea77d2cdb) · web: <http://192.168.230.131:3777/ds/components/popover/popover?preview=ds-overlays-stories>
0. Shrnutí
Popover je nosná vrstva celé aplikace — 60 volání <Popover> ve 41 souborech plus všechno, co z něj staví Select, Record select, Filter chip, PickerMenu. O to víc bolí, že menu se nedá ovládat z klávesnice: při otevření se do něj nepřesune fokus, mezi řádky nejezdí šipky a panel je portálovaný na konec <body>, takže Tab z chipu jde do zbytku stránky. To je jedna oprava na jednom místě, která spraví každou nabídku v systému.
Druhý nález: stejná matematika umístění existuje dvakrát — packages/ui/src/lib/place.ts a apps/web/src/lib/anchored-panel.ts.
1. Nálezy per podkomponenta (ověřeno v kódu)
1.1 Popover (packages/ui/src/components/Popover.tsx, lib/place.ts)
- Umístění: 4px pod kotvou, svislý překlop nahoru při nedostatku místa, vodorovné oříznutí 8px od hrany, šířka podle kotvy nebo
width. Žádné boční umístění a žádná šipka — to je v pořádku, systém je nepoužívá. - Zavírá na Esc, klik mimo (scrim
z-index: 85), scroll kotvy a resize. Panelz-index: 101, portál do<body>. - Klávesnice: implementovaný je jen Escape. Žádný přesun fokusu při otevření, žádné šipky, žádný návrat fokusu. Vzor WAI-ARIA menu tohle vyžaduje.
- CSS
.acrm-popover-itemmá hover,:disabled,.danger,.strong,.chk,.tag,.ic, separator i prázdný stav. Nemá stav „vybráno klávesnicí" (a bez šipek ani nemá proč). .acrm-popover-item .sub(druhý řádek) v CSS neexistuje — a legacy storyPopoverStoryho přesto vykresluje. Katalog tím ukazuje tvar, který kanon zrušil (jednořádkový kanon D1–D5,- 8. 2026).
1.2 Tooltip (Tooltip.tsx)
- JS umístění (ne
::after), portál,z-index: 120, prodleva 80 ms, otevírá se i na fokus a klonujearia-describedbyna dítě — po stránce přístupnosti nejlepší kus rodiny. - Adopce je ale nízká: 7 použití ve 2 souborech (
ComposeForm,PlaudPickerDialog), přičemž ikonových tlačítek bez popisku je v appce mnohem víc. - Jen nad/pod, bez boční varianty; na dotyku nefunguje (hover neexistuje).
1.3 Entity preview (EntityPreview.tsx)
- Deset typů záznamu, tři stavy (
ready/loading/unavailable),pinnedpro otevřené podmenu, kanon K1–K4 je vynucený API (řádek = ikona + hodnota, žádné pilulky). - Přímých volání je málo, ale přes obal
EntityRefPreviewje to 39 souborů — reálně nosný prvek. - Karta nemá strop výšky ani vnitřní scroll (pevná šířka 280px) — přeplněná karta přeteče krátký viewport.
1.4 Paralelní implementace
| kde | co dělá | vztah k Popoveru |
|---|---|---|
PickerMenu (packages/ui) | pick-one nad Popoverem | v pořádku, tenký obal |
RailPickerMenu (app) | používá useAnchoredMenu, ale kreslí Record select markup | vedle Popoveru, vědomě |
AddRefMenu (app) | kreslí .acrm-popover sám + vlastní useAnchoredPanel | duplicita pláště i matematiky |
useAnchoredPanel (apps/web/src/lib/anchored-panel.ts) | vlastní kopie flip/clamp | duplicita place.ts (další konzumenti: .rcpt-menu, .itm-ac-pop) |
PickerPanel | datumový overlay, vědomě NE .acrm-popover | v pořádku, zdokumentované |
2. Bug list — DS (web, registr, stories, docs)
| # | Nález | Stav |
|---|---|---|
| D1 | Rodina Popover neměla per-sekci stories (jen legacy přehledy) | OPRAVENO (3 soubory, 14 stories) |
| D2 | Nikde nebyl vidět prázdný stav menu, .danger, :disabled, .strong, .tag, scroll 60vh | OPRAVENO (sekce States a With icon & kbd) |
| D3 | Chyběly usage.md a a11y.md pro všechny tři podkomponenty | OPRAVENO (6 souborů) |
| D4 | Legacy story PopoverStory kreslí neexistující .sub (druhý řádek) | NEOPRAVENO — má baseline, oprava = změna baseline (rozhodnutí P-A4) |
| D5 | Registr popisoval Popover jako „panel se scrimem"; neřekl nic o portálu a stropu 60vh | OPRAVENO (summary) |
3. Bug list — aplikace (kanon v kódu)
| # | Nález | Návrh | Kdo rozhodne |
|---|---|---|---|
| A1 | Menu nejde ovládat klávesnicí (bez fokusu, bez šipek) | doplnit do Popover.tsx: fokus na první položku při otevření, šipky nahoru/dolů, Home/End, Esc zpět na spouštěč | AD ano/ne, FE provede |
| A2 | Dvě kopie umístění (place.ts × anchored-panel.ts) | useAnchoredPanel přepsat na place() a soubor zrušit | AD ano/ne |
| A3 | AddRefMenu staví .acrm-popover ručně | převést na <Popover> | AD ano/ne |
| A4 | Legacy PopoverStory kreslí zrušený .sub | přepsat na jednořádkový kanon + přefotit baseline | AD (mění baseline) |
| A5 | Tooltip má 7 použití, ikonová tlačítka bez popisku jsou všude | projít ikonová tlačítka a doplnit tooltipy tam, kde akce není zřejmá | AD (rozsah vlny) |
| A6 | Entity preview bez stropu výšky | doplnit max-height + vnitřní scroll | AD ano/ne |
4. Rozhodnutí pro AD
- P1 — Popover, Tooltip, Entity preview jako kanon. Schválit podle ukázek na webu. Doporučuji ano.
- P2 — klávesnice v menu (A1). Doporučuji ano a jako první. Je to jedna oprava na jednom místě, která spraví každou nabídku v aplikaci (filtr, select, record select, akce záznamu). Vizuálně se nic nemění.
- P3 — jedna matematika umístění (A2+A3). Doporučuji ano, v jednom MR:
useAnchoredPanelnaplace()aAddRefMenuna<Popover>. - P4 — vlna tooltipů (A5). Doporučuji vzít samostatně až po schválení rodiny; je to obsahová práce (co má který ovládací prvek říkat), ne technická.
- P5 — legacy story se
.sub(A4). Doporučuji přepsat při nejbližší vlně baseline.
5. Co teď
- MR do acrm
polish/ds-overlays-stories(Dialog + Popover) se zámkemno-auto-merge. - DS repo: registr, docs, tenhle review.
- Po schválení:
approvedAt, pak P2 jako samostatný MR (chování, ne vzhled).
Source: docs/REVIEW-popover-family.md · GitLab