ADR-060 ActifActive component

Implémentation de `agtc-top-nav`

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

English summary: The site's main navigation was hand-rolled HTML/CSS that had accumulated repeated bugs: unstyled :visited/:active, a filled "active" state that looked like a toggled button, missing :focus-visible and aria-current, and no component-token layer. This ADR formalizes agtc-top-nav as a Lit Web Component using <nav> + aria-current="page" (not role="tablist", since it links between pages rather than switching in-page panels), a full-height tab visual pattern with a bottom-border active indicator, a separate CTA link style, and 18 new component tokens — making the component, not the site's CSS, the source of truth for the nav's design.

>

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


Contexte

Le site Agentica est le laboratoire vivant du design system — chaque fonctionnalité du site est l'occasion de construire et valider un composant réel avant de le formaliser.

La navigation principale du site (site/build.js) était implémentée en HTML statique généré par JavaScript, avec des styles CSS définis directement en termes de tokens sémantiques (sans passer par un niveau composant). Plusieurs problèmes accumulés au fil des sessions :

La décision de formaliser agtc-top-nav comme composant du DS découle du principe fondateur : le site consomme le design system, pas l'inverse.


Décision

Créer le composant agtc-top-nav (Web Component Lit) qui encapsule la navigation principale horizontale avec un pattern visuel tabs full-height, et le formaliser dans le design system avant de l'appliquer au site.

Décisions techniques clés

<nav> et non role="tablist"

Malgré l'apparence visuelle similaire aux tabs, agtc-top-nav utilise des liens inter-pages. Le pattern ARIA correct est <nav aria-label="..."> + <a aria-current="page">, pas role="tablist" qui impliquerait des panneaux de contenu in-page et une navigation aux flèches.

Pattern tabs full-height

Chaque lien occupe toute la hauteur du header (64px) via align-self:stretch. L'état actif est indiqué par border-bottom:2px solid action-primary positionné au bas du header — pas par un fond rempli (qui imiterait un bouton togglé).

Bouton CTA séparé

Le lien "Démarrer" (cta:true) sort du pattern tab : height:auto; align-self:center; border-radius:control; margin-left:8px. C'est une action d'adoption, visuellement un bouton.

18 tokens composant

Toutes les décisions visuelles sont capturées dans tokens/component.json sous top-nav.* : 11 tokens pour les tabs, 7 tokens pour le CTA. Le CSS du composant et du site ne référencent que --agtc-component-top-nav-*.


Patterns UX de référence appliqués

PatternSourceDécision
Landmark <nav aria-label>W3C WAI APGnav-label obligatoire, prop exposée
aria-current="page"WCAG 2.4.4 / 4.1.2Calculé automatiquement depuis current (pathname)
Indicateur border-bottomNN/g — nav horizontale2px en bas du tab pleine hauteur
Pas de role="tablist"W3C APG Tabs PatternNav inter-pages ≠ tabs in-page
CTA distinct (bouton pill)IxDF — clear primary actioncta:true → border-radius + fond rempli
:visited neutraliséADR-047Dans shadow DOM via a:visited { color: var(…) }
Mobile hamburgerNN/g — Mobile navGéré par le site (hors composant v1.0)

Alternatives rejetées

AlternativeRaison du rejet
Garder le HTML statiquePas de réutilisabilité, décisions de design éparpillées dans le CSS du site
Utiliser agtc-tabs avec hrefagtc-tabs a role="tablist" — sémantique ARIA incorrecte pour une nav inter-pages
Fond rempli pour le lien actifRessemble à un bouton togglé (pill) — NN/g recommande l'indicateur de ligne pour les navs horizontales
Navigation aux flèchesRéservée aux tablist ARIA — trompeuse pour des liens
Intégrer le bilinguisme dans le composantLe composant est language-agnostic — la langue est gérée côté consommateur (site)

Conséquences

Pour le site : La CSS du site référence désormais --agtc-component-top-nav-* au lieu de tokens sémantiques directs. Le composant Lit peut être utilisé pour remplacer le HTML généré en phase 2 d'intégration.

Pour le design system : 18 nouveaux tokens composant dans tokens/component.json. Build : 792 tokens définis (+18), 0 fantôme.

Pour les agents : Toute modification visuelle de la top-nav passe par tokens/component.json (et un TCR). Le composant est le contrat — pas le CSS du site.


Incidents ou déclencheurs

Navigation corrigée 6 fois en une journée (2026-06-15) avant la décision de formaliser le composant : :visited Safari (×3), :active absent, .active bouton-like, :focus-visible absent, aria-current absent. La récurrence des corrections a déclenché la formalisation.

← ADR-059 ADR-061 →