SPB Git forge

spb/qc-election

Public
20commits 1branches 0releases
4.9 MBsize
maindefault branch
20 days agolast push
Python 66.6% HTML 24.8% CSS 4.9% JavaScript 3.6%
5.5 KB

# UI Audit — refonte « QC Signal » (2026-08-30)

État des lieux avant la refonte du frontend (design v3 « sharp ») et dettes retirées par la migration vers le design system QC Signal (voir docs/DESIGN_SYSTEM.md). Refonte UI/UX pure : aucun changement statistique, aucun contrat d'API modifié, backend intact.

# État avant

  • Design v3 « sharp » : bon socle (thème dark/light, palette partis validée CVD, drawer mobile correct), mais tokens incomplets (pas d'échelle de radius/spacing formalisée, ombres composites lourdes --shadow-lift), deux polices (Inter + JetBrains Mono), logo = carré dégradé bleu/violet avec ⚜ emoji et ombre portée.
  • Accueil : liste de cartes partis chargées (gros portraits + logos), baromètre « meter » comme seul visuel de sièges, aucun hemicycle, aucune hiérarchie éditoriale (pas de verdict principal), intervalles [a–b] en texte brut partout.
  • « Le point du jour » : deltas verts/rouges (delta-up/delta-down) — une hausse du PQ affichée « positive » universellement, en contradiction avec la neutralité de la plateforme.
  • Intelligence / simulateur : momentum et « vs référence » également en vert (--good) / rouge (--plq!) — le rouge d'un parti utilisé comme sémantique négative.
  • Pas d'indicateur global du forecast hors de l'accueil (aucun « strip »).
  • Tables longues (127 circonscriptions, ~2000 sondages) sans en-tête sticky ni hauteur bornée.
  • /carte : carte à ~66 % de largeur, hauteur fixe 560 px, panneau 340 px figé.
  • Emojis décoratifs dans les cartes de couches (🗳️✅🏛️📰📈) et libellés d'état.
  • Bascule de thème = emoji ☀️/🌙.
  • États vides hétérogènes (<span style="color:var(--muted)">, .loading partout).

# Dettes retirées

Dette Correction
Deltas vert/rouge (aujourdhui, intelligence, simulateur) helper unique deltaHTML : flèche + valeur, couleur du parti ou neutre — jamais de valence universelle
var(--plq) (rouge PLQ) utilisé comme couleur d'erreur (admin, intelligence, simulateur) --danger sémantique (admin) ou couleur du parti (données)
Intervalles texte [24–86] sans lecture visuelle composant rangeHTML (barre lo─●─hi avec repère majorité) sur accueil + cartes partis
Aucune vue de composition des sièges hemicycleSVG réutilisable (127 sièges, marqueur majorité 64, hover parti/sièges/IC)
Pas de résumé du forecast inter-pages forecast strip sticky sous la nav sur les 11 pages (via initShell, /api/today + repli)
Logo pastille dégradée + emoji ⚜ fleur-de-lys SVG nette monochrome accent, wordmark simple
Emoji ☀️/🌙 et emojis de couches icônes SVG soleil/lune; couches numérotées 1-5
2 webfonts Inter seul (code → pile monospace système)
Ombres/gradients lourds sur cartes surfaces planes + --shadow-sm/--shadow-md discrets, bordures rgba faibles
Tables longues illisibles .table-scroll (max-height 70 vh) + th sticky (circonscriptions, sondages)
/carte : carte à l'étroit .map-layout ~75/25, hauteur min(72vh, 700px)
Débordement horizontal mobile (390 px) : tiroir hors-écran comptait dans scrollWidth; canvas ECharts verrouillait la colonne de grille (/intelligence à 824 px); table marchés sans conteneur html,body{overflow-x:clip}, .grid>*{min-width:0}, overflow-wrap:anywhere sur les verbatims, conteneur défilant sur la table marchés — scrollWidth = 390 sur les 11 pages
Étiquette « majorité 64 » de l'hémicycle coupée hors viewBox marge haute du SVG (+52 px)
Nav qui tronquait « Méthodologie » à 1440 px paliers 1560/1250/1120 px (densité, masquage MAJ, masquage « Forecast »)
États vides ad hoc / risque de undefined emptyStateHTML(...) uniforme; audit Playwright vérifie l'absence de undefined/NaN/[object Object] dans le texte rendu
Animations non bornées ≤220 ms, prefers-reduced-motion respecté aussi par ECharts (baseChart)

# Langage uniformisé

« Chance d'arriver premier » · « Sièges attendus » · « Vote projeté » · « Majorité » — appliqué à l'accueil, au point du jour, au strip et aux cartes partis.

# Validation

~/ka-screenshots/qcsignal-audit.mjs : 11 pages × {1440, 1024, 768, 390} px, collecte pageerror + console.error, détection de texte undefined/NaN, captures /tmp/qcsignal_*.png (accueil aussi en clair 1440 + 390). Résultat final : zéro erreur JS, zéro débordement horizontal, aucun texte cassé sur les 44 combinaisons.

# Contrats préservés (fragiles — ne pas renommer)

  • IDs DOM consommés par les scripts de page (inchangés partout) : notamment hdr-updated, drawer-updated, nav-burger, fstrip (coquille); party-cards, trend-chart, seat-hist, prob-hist, nowfc, events, latest-polls, beyond-* (accueil); tous les IDs de carte/circonscriptions/ sondages/signaux/simulateur/intelligence/backtest/admin inchangés.
  • Helpers globaux d'app.js réutilisés par toutes les pages : initShell, getJSON, API, partyColor/partyName/partyLeader, avatarHTML, initialsAvatar, partyLogo, fmtPct/fmtDate/sortParties, baseChart, AXIS_STYLE/TOOLTIP/LEGEND, areaGrad/lineGlow/hexA, DARKMODE/GRID_COLOR/SPLIT_COLOR/MUTED/INK2/CHART_FONT — signatures intactes.
  • La probabilité « premier » affichée reste la valeur publiée (seats.ensemble.blended avec repli prob_most) — aucune probabilité recalculée côté client; l'outcome bar n'utilise que prob_majority, prob_minority_win et leur complément.