Files
ObsiGate/docs/features/xlsx-menus-179.md
T
bruno d79202e698
CI / lint (push) Successful in 2m52s
CI / security (push) Successful in 2m11s
CI / test (push) Successful in 4m48s
CI / build (push) Successful in 2m0s
CI / e2e (push) Failing after 16m50s
feat: menus tableur a icones, fermeture au focus et polish mobile #179
2026-10-04 19:27:50 -04:00

3.6 KiB

#179 — Éditeur tableur : icônes des menus & boutons, fermeture au focus, polish mobile

Statut : 🔵 en cours (2026-10-04) | Effort : 1-2 jours | Impact : 🟡 Références : Roadmap · Changelog · #154 · #155 · #156

1. Constat

La grille (#155), les menus Structure / Mise en forme / Export (#156-A8/A11/A14) et les boutons du ruban (#154) étaient textuels, et les menus Structure / Mise en forme / Export restaient ouverts quand le focus les quittait (seul le menu grille se fermait, au clic extérieur / Échap uniquement).

2. Livré (A1-A4)

A1 — Icônes du menu contextuel de la grille

Chaque entrée de buildContextItems (viewer.js) porte une icône Lucide (scissors, copy, clipboard-paste, rows/columns, trash-2 danger, arrow-up/arrow-down, eraser). Rendu dans xlsx/context-menu.js (<i data-lucide> + <span class="xlsx-menu-label">, label en textContent — jamais d'HTML injecté), hydraté par safeCreateIcons() (jamais lucide.createIcons() direct).

A2 — Icônes Structure / Mise en forme / Export + boutons

  • Structure : file-plus, pencil, copy, trash-2 (danger), rows, columns ; suppressions marquées .xlsx-context-danger.
  • Mise en forme : bold/italic/underline, remove-formatting, align-left/center/right, palette/paint-bucket (sélecteurs natifs), type/hash/percent/euro/calendar/pilcrow (formats), combine/ungroup, snowflake/sun (figer/libérer), move-horizontal/move-vertical (largeur/hauteur).
  • Export : file-text (MD), code (HTML), printer (impression).
  • Ruban : bouton Enregistrer (save + libellé), onglet « + » (plus), aria-haspopup="menu" / aria-expanded sur les 3 boutons à menu.

A3 — Fermeture à la perte de focus + clavier

  • trackDismissable(menu, { toggle, onClose }) dans context-menu.js : clic extérieur (le toggle garde ses propres clics), Échap, focusout (vers menu et toggle exemptés), scroll (capture), resize ; dismiss() idempotent qui débranche tout (pas de fuite entre re-rendus).
  • Menu grille : focusout + scroll/resize en plus de l'existant ; enableArrowNav() (↓/↑/Home/End, désactivés sautés), autofocus de la 1ʳᵉ entrée à l'ouverture (preventScroll), :focus toujours visible.
  • Menus Structure / Mise en forme / Export branchés sur le helper.

A4 — Polish mobile

  • @media (pointer: coarse) : entrées ≥ 44 px, police 0,9 rem.
  • Menus bornés au viewport (grille : min(320px, 86vw) + max-height: 80vh scrollable ; structure : min(320px, 92vw) ; export : 86vw).
  • Le ruban s'enroule déjà (flex-wrap), l'inspecteur s'empile ≤ 900 px : vérifié sans débordement horizontal à 393 px (E2E projet mobile).

3. Tests

  • tests/frontend/xlsx-menus.test.mjs (11) : rendu icônes + XSS, autofocus, navigation clavier, Échap / clic / focusout / scroll / resize, trackDismissable, icônes du ruban.
  • tests/frontend/xlsx-viewer.test.mjs (+6, 113 total) : icônes et fermetures au niveau viewer réel.
  • tests/e2e/xlsx-viewer.spec.js (+5) : icônes par entrée, fermeture clic/Échap, Structure au focus perdu, Export au clic extérieur, mobile (ruban, 44 px, viewport) — ce dernier skip hors viewport ≤ 768 px.

4. Limites assumées

  • Noms d'icônes de la gamme Lucide 0.344.0 (CDN unpkg) : si le CDN est injoignable, les libellés restent (dégradation texte, jamais de crash).
  • Pas de nouveaux libellés i18n (icônes + aria-expanded uniquement).