ADR-040 ActifActive contract

Implémentation de `agtc-table`

DateDate
2026-06-03
DécideursDecision makers
Design System Lead

English summary: Implements agtc-table — the site's most-used pattern (692 token-table occurrences) — as a "mix" architecture: a data-driven Lit component for apps/Storybook, plus a .agtc-table CSS class for the site's static HTML (so displaying a table never depends on JS). Read-only in v1; sorting/filtering/pagination are deferred but designed for via an extensible columns/rows API.

>

*The original French version follows below — preserved unaltered as the historical record.*


Patterns UX de référence appliqués

Ajouté le 2026-06-03 via le workflow ux-pattern-review (ADR-036). Décision : T1–T10 tous approuvés. Détail et liens : guidelines/components/table.md § PATTERNS UX DE RÉFÉRENCE.

#PatternSource
T1HTML sémantique + scope="col"Smashing — Table Patterns
T2<caption> (masquable)Smashing
T3Alignement texte/gauche, numérique/droiteNN/g — Data Tables
T4Séparateurs de lignes (zébrage en option)NN/g
T5Survol de ligneNN/g
T6En-tête figé (optionnel)NN/g · Smashing
T7Scroll horizontal + indicateur d'overflowSmashing
T81ʳᵉ colonne = identifiant lisibleNN/g
T9Densité compact par défautDashboard Design Patterns
T10Tri/filtre/pagination — porte ouverte, hors v1NN/g

Contexte

agtc-table est le composant le plus utilisé du site généré : 692 occurrences de token-row/token-table (tables de tokens : token CSS → référence → valeur → intention), plus les tables de comparaison et les tables DOs/DON'Ts. La gap-analysis du 2026-06-03 l'a identifié comme premier composant à construire à partir des besoins réels du site.

Constat à la création : le HTML d'origine du site n'a ni scope sur les <th> ni <caption> — un trou d'accessibilité que ce composant comble.

La table est en lecture seule : les tables documentaires n'ont pas besoin d'édition, de tri ni de pagination. On évite la conception spéculative tout en gardant la porte ouverte.


Décisions

Décision 1 — Architecture « mix » : composant piloté par données + classe light DOM

Deux formes consommant les mêmes tokens component.table.* :

1. <agtc-table> (Lit, shadow DOM) — piloté par .columns/.rows. Pour les apps, les contextes JS et Storybook. Cohérent avec les autres composants (shadow DOM + static styles). 2. .agtc-table (classe CSS) — appliquée à un <table> réel écrit à la main. Pour le site statique, qui doit rester résilient : afficher une table ne doit pas dépendre de JS.

Pourquoi pas un seul mécanisme ?

  • Tout-shadow-DOM piloté par données rendrait le site JS-dépendant pour afficher ses tables —

régression de résilience (le site est aujourd'hui du HTML statique pur).

  • Le *slotting* d'un <table> complet dans un shadow DOM ne permet pas de styler th/td

(::slotted n'atteint pas les descendants). La classe light DOM contourne cette limite et gère le contenu riche des cellules (ex. <code>), que l'API par données (texte échappé) ne couvre pas.

Décision 2 — Lecture seule ; tri/filtre/pagination hors périmètre, mais API extensible

La v1 n'implémente ni tri, ni filtrage, ni pagination (T10). Besoin réel du site = tables statiques. Mais l'utilisateur a confirmé un besoin futur : l'API columns/rows est choisie précisément pour les accueillir sans rupture (futur column.sortable, événement @sort, slot de barre d'outils). Aucune propriété morte n'est livrée en v1 pour éviter une API trompeuse.

Décision 3 — Tokens table dans component.json, structure default.* + paddings

Les couleurs et le rayon vivent sous table.default.* ; les paddings (horizontal, vertical compact/confortable) sont au niveau table.*. Cette séparation permet de changer la densité sans toucher aux couleurs. Conforme aux trois niveaux (ADR-001) : tous les tokens pointent vers des tokens sémantiques (background.subtle, border.default, background.hover…), aucune valeur brute.

Décision 4 — Accessibilité par défaut : scope, <caption>, alignement numérique

<th scope="col"> systématique ; <caption> recommandé (avertissement console si absent), masquable visuellement via caption-hidden ; colonnes numériques alignées à droite (align="end") pour le scan vertical. Comble les trous du HTML d'origine.

Décision 5 — Séparateurs par défaut, zébrage en option (T4)

Décision utilisateur : séparateurs de lignes par défaut (sobre, adapté aux tables de tokens denses), zébrage disponible via l'attribut striped.

Décision 6 — Densité compact par défaut (T9)

Les tables de tokens sont denses ; compact est le défaut, comfortable disponible via density.


Périmètre v1

InclusExclu (porte ouverte)
Composant piloté par données (columns/rows)Tri / filtrage / pagination
Classe .agtc-table (light DOM, contenu riche)Édition de cellule en ligne
caption + caption-hidden, scope="col"Sélection de lignes / actions de masse
Alignement par colonne (start/end/center)Colonnes redimensionnables / réordonnables
striped, sticky-header, densityEn-tête multi-niveaux / colspan
Scroll horizontal + indicateur d'overflowCellules HTML riches via l'API par données (→ classe)

Alternatives rejetées

  • Tout-shadow-DOM piloté par données seul : rend le site JS-dépendant pour ses tables (régression).
  • Tout-classe CSS seul : pas d'API par données pour les apps ; pas de story Storybook propre.
  • Slotting d'un <table> dans le shadow DOM : impossible de styler th/td slottés.
  • Livrer un sortable no-op pour « marquer » T10 : API trompeuse ; préféré documenter l'extensibilité.

Conséquences

  • Le site pourra migrer ses token-table/token-row vers .agtc-table lors de l'étape de

*dogfooding* (catégorie A de la gap-analysis), sans dépendance JS.

  • Tout ajout de tri/filtre/pagination devra créer un nouvel ADR (gouvernance).

Tokens ajoutés dans component.json

TokenRéférence sémantique
--agtc-table-default-header-backgroundsemantic.color.background.subtle
--agtc-table-default-header-textsemantic.color.text.secondary
--agtc-table-default-cell-textsemantic.color.text.primary
--agtc-table-default-bordersemantic.color.border.default
--agtc-table-default-row-hoversemantic.color.background.hover
--agtc-table-default-stripesemantic.color.background.subtle
--agtc-table-default-caption-textsemantic.color.text.secondary
--agtc-table-default-radiussemantic.radius.card
--agtc-table-default-font-sizesemantic.typography.label.size
--agtc-table-padding-xprimitive.space.3
--agtc-table-padding-y-compactprimitive.space.2
--agtc-table-padding-y-comfortableprimitive.space.3