73 lines
3.6 KiB
Markdown
73 lines
3.6 KiB
Markdown
# #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](../ROADMAP.md) · [Changelog](../../CHANGELOG.md) ·
|
|
> [#154](./xlsx-ui-redesign.md) · [#155](./xlsx-context-menu.md) · [#156](./xlsx-editor-completeness.md)
|
|
|
|
## 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).
|