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. Panel z-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-item má 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 story PopoverStory ho 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 klonuje aria-describedby na 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), pinned pro 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 EntityRefPreview je 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

kdeco dělávztah k Popoveru
PickerMenu (packages/ui)pick-one nad Popoveremv pořádku, tenký obal
RailPickerMenu (app)používá useAnchoredMenu, ale kreslí Record select markupvedle Popoveru, vědomě
AddRefMenu (app)kreslí .acrm-popover sám + vlastní useAnchoredPanelduplicita pláště i matematiky
useAnchoredPanel (apps/web/src/lib/anchored-panel.ts)vlastní kopie flip/clampduplicita place.ts (další konzumenti: .rcpt-menu, .itm-ac-pop)
PickerPaneldatumový overlay, vědomě NE .acrm-popoverv pořádku, zdokumentované

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

#NálezStav
D1Rodina Popover neměla per-sekci stories (jen legacy přehledy)OPRAVENO (3 soubory, 14 stories)
D2Nikde nebyl vidět prázdný stav menu, .danger, :disabled, .strong, .tag, scroll 60vhOPRAVENO (sekce States a With icon & kbd)
D3Chyběly usage.md a a11y.md pro všechny tři podkomponentyOPRAVENO (6 souborů)
D4Legacy story PopoverStory kreslí neexistující .sub (druhý řádek)NEOPRAVENO — má baseline, oprava = změna baseline (rozhodnutí P-A4)
D5Registr popisoval Popover jako „panel se scrimem"; neřekl nic o portálu a stropu 60vhOPRAVENO (summary)

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

#NálezNávrhKdo rozhodne
A1Menu 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
A2Dvě kopie umístění (place.ts × anchored-panel.ts)useAnchoredPanel přepsat na place() a soubor zrušitAD ano/ne
A3AddRefMenu staví .acrm-popover ručněpřevést na <Popover>AD ano/ne
A4Legacy PopoverStory kreslí zrušený .subpřepsat na jednořádkový kanon + přefotit baselineAD (mění baseline)
A5Tooltip má 7 použití, ikonová tlačítka bez popisku jsou všudeprojít ikonová tlačítka a doplnit tooltipy tam, kde akce není zřejmáAD (rozsah vlny)
A6Entity preview bez stropu výškydoplnit max-height + vnitřní scrollAD 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: useAnchoredPanel na place() a AddRefMenu na <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ď

  1. MR do acrm polish/ds-overlays-stories (Dialog + Popover) se zámkem no-auto-merge.
  2. DS repo: registr, docs, tenhle review.
  3. Po schválení: approvedAt, pak P2 jako samostatný MR (chování, ne vzhled).

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