#154 — Refonte UI/UX de la visionneuse & éditeur XLSX (ruban, grille, inspecteur)
Item de roadmap : #154 — Refonte UI/UX tableur
Origine : #152 / #153 (visionneuse XLSX fonctionnelle mais peu conviviale)
Statut : 🔵 en cours — Lots 1, 2 & 3 livrés le 2026-09-29
Effort estimé : 6-9 jours (Lot 1 ✅ · Lot 2 ✅ · Lot 3 ✅ · Lot 4)
Règle de maintenance : la Roadmap porte les cases à cocher (suivi), cette fiche porte
l'analyse, l'architecture cible et le plan par lots. Ne pas dupliquer le détail.
1. Objectif
Rendre la vue tableur d'ObsiGate intuitive, moderne et hautement utilisable en s'inspirant
des standards du marché (Excel, Google Sheets, Airtable), sans renier les contraintes du
dépôt : thème sombre, vanilla JS, zéro framework, zéro build npm
(AGENTS.md). La refonte est organique : on améliore la coquille
existante (frontend/js/viewer.js::renderXlsxViewer, frontend/style.css), on ne réécrit pas
la grille ni le backend.
2. Audit UX — les 3 problèmes majeurs
| # |
Problème |
Constat |
Résolution |
| P1 |
Aucune hiérarchie ni regroupement des commandes |
Rangée plate de boutons de poids identique (viewer.js toolbar historique) ; « Tableau de bord » prependé au runtime ; barre de formule réduite à un input. |
Barre de commandes groupée (Formules · Insertion · Vue · Fichier), bouton Enregistrer primaire, état dirty. |
| P2 |
Grille sans affordances : en-têtes = cellules |
Contraste faible entre th et td, pas de zébrage, pas de survol lisible, cellule active peu marquée. |
Tokens de grille + en-têtes plus clairs/interactifs, zébrage, survol, cellule active en bordure accent. |
| P3 |
États avancés traités comme du contenu |
Dashboard inline qui pousse la grille, troncature/lecture seule/formules non recalculées sans emplacement dédié, confirm()/prompt() natifs. |
Couche UI dédiée : bandeaux d'état + inspecteur droit (Lot 3) + dialogues thémés (Lot 2). |
3. Architecture cible de l'écran
- A. Ruban : groupes d'actions avec séparateurs ; actions de style désactivées (styles lus,
pas écrits). Bouton Enregistrer en accent, désactivé si rien de dirty.
- B. Barre de formule : zone nom + champ + badge de session
f(x).
- C. Bandeaux d'état : empilables, non bloquants ; portent lecture seule et
« formules non recalculées ».
- D. Grille : rendue côté serveur (
backend/xlsx_reader.py), habillée et câblée par le front.
- E. Inspecteur : à venir (Lot 3) — Tableau de bord + Assistant IA dans un panneau droit
repliable (réutilise
PaneManager pour le détachement), au lieu du dashboard inline actuel.
- F. Onglets feuilles : permanents (même à une seule feuille) + bouton « + ».
4. Plan par lots (incréments livrables)
Lot 1 — Coquille : ruban groupé, onglets permanents, badges d'état ✅ (2026-09-29)
- A1.1 Barre de commandes groupée (
.xlsx-cmdbar, .xlsx-cmd-group, .xlsx-cmd-sep,
.xlsx-save-primary), IDs existants conservés (compatibilité tests JSDOM/E2E).
- A1.2 Onglets de feuilles toujours rendus (non-CSV) + bouton
+ .xlsx-tab-add
→ sheet_add (même pipeline putStructure).
- A1.3 Badges d'état :
.xlsx-status-pill lecture seule (.xls/.ods) et
formules non recalculées (non-CSV).
- A1.4 Tokens de grille (
--grid-bg, --grid-header-bg, --grid-header-text,
--grid-border, --grid-zebra) déclinés dark/light + affordances (en-têtes clairs,
zébrage, survol, cellule active solide, cellule dirty prioritaire au survol).
Lot 2 — Dialogues thémés & feedback ✅ (2026-09-29)
- A2.1 Helpers génériques
showConfirm() / showPrompt() (frontend/js/ui.js), promise-based,
réutilisant les classes .obsigate-modal-* (fini window.confirm() / window.prompt()).
- A2.2 La visionneuse XLSX utilise ces dialogues pour les actions de structure (ajouter /
renommer / dupliquer / supprimer feuille, insérer / supprimer ligne et colonne) et pour la
confirmation de perte (409
xlsx_lossy_content).
- A2.3 Conflit de sauvegarde (409
conflict) : bandeau non bloquant .xlsx-banner-conflict
avec bouton Réessayer — les modifications sont conservées.
- A2.4 Indicateur dirty sur le bouton Enregistrer et sur l'onglet de la feuille concernée.
Lot 3 — Inspecteur droit ✅ (2026-09-29)
- A3.1 Le Tableau de bord quitte le flux de la grille pour un panneau droit repliable
(
.xlsx-inspector) : la grille reste visible à côté (.xlsx-body = .xlsx-main + inspecteur).
- A3.2 En-tête d'inspecteur : titre, bouton Assistant IA (ouvre le panneau latéral global
existant) et bouton de fermeture.
- A3.3 Responsive : sous 900 px, l'inspecteur passe sous la grille.
Lot 4 — Découpage & finitions (à venir)
- Extraction de
renderXlsxViewer en modules (frontend/js/xlsx/*.js) : toolbar, formula-bar,
grid, sheet-tabs, inspector, cell-editor, api.
- Undo/redo local (pile de commandes), défilement paresseux via
IntersectionObserver,
accessibilité ARIA (role="grid", roving tabindex).
- Lien dashboard → grille (clic sur KPI/plage = scroll + sélection), inspecteur
redimensionnable, détachement en split via
PaneManager.splitRight().
5. Recommandations techniques (contrainte « zéro build »)
| Option Data Grid |
Build |
Licence |
Verdict |
| AG Grid Community |
npm + bundler |
MIT |
❌ viole « zéro build », réécrit le DOM, casse les tests |
| Handsontable |
npm + bundler |
commerciale |
❌ licence non libre |
| TanStack Table |
headless (importable esm.sh) |
MIT |
⚠ possible sans build, mais headless → gain limité |
Grille maison sur <table> |
aucun |
— |
✅ recommandé (conserve DOM, CSP, i18n, tests) |
- Performance : ne pas ré-écrire tout le DOM ; réutiliser le pipeline
appendWindow ;
content-visibility:auto; contain:strict sur les lignes ; garder la pagination serveur
(500 × 40 = 20 000 cellules/feuille) plutôt qu'une virtualisation client complexe.
- CSP :
main.py autorise déjà esm.sh — une lib headless reste possible en Lot 4 si
un vrai besoin de modèle de colonnes apparaît.
6. Critères d'acceptation (par lot)
- Lot 1 : une feuille unique affiche son onglet + « + » ; « + » ajoute une feuille via
PUT …/xlsx/structure et re-rend ; .xls/.ods montrent le badge « lecture seule » (pas de
« + », pas de structure, pas de dashboard) ; un .xlsx montre le badge « formules non
recalculées », un .csv non ; les tests JSDOM/E2E existants restent verts + nouveaux tests.
- Lots suivants : définis à leur ouverture.
7. Historique
| Date |
Événement |
| 2026-09-29 |
Audit UX (3 problèmes) + architecture cible + plan par lots ; Lot 1 livré (ruban groupé, onglets permanents + « + », badges d'état, tokens de grille) |
| 2026-09-29 |
Lot 2 livré : dialogues thémés (showConfirm/showPrompt) pour la structure et la confirmation de perte, bandeau de conflit 409 non bloquant avec réessai, indicateur dirty (bouton + onglet) |
| 2026-09-29 |
Lot 3 livré : le Tableau de bord passe dans un inspecteur droit repliable (grille toujours visible), en-tête d'inspecteur avec entrée Assistant IA et fermeture, responsive < 900 px |