ADR-056 ActifActive contract

Implementing `agtc-tabs`

DateDate
2026-06-12
DécideursDecision makers
Human (approval) · Design System Lead

Context

Phase D3 of the site redesign: the doc-chrome needs a tabs component to structure component pages (e.g. Overview | Tokens | Best practices). No agtc-tabs existed.


Decisions

1. Tab type — in-page + optional href

Decision: in-page by default (panel change within the DOM), with an optional href attribute per tab for external navigation links.

Why: Most doc-chrome uses are in-page. The optional href allows mixed tabs (e.g. Overview | Storybook ↗) without creating two separate components.

Source: NN/g — Tabs: Used Right


2. Automatic activation on focus

Decision: activation="auto" by default — navigating with the arrow keys activates the tab immediately. activation="manual" available as opt-in (requires Enter/Space).

Why: The APG recommends automatic activation when content is preloaded (our case — all panel content is in the DOM). Reduces the number of keystrokes.

Source: W3C APG — Tabs Pattern


3. Closable tabs — deferred

Decision: Not implemented in D3. No use case identified in the doc-chrome. To be reconsidered for a future multi-doc editor.


4. Orientation — horizontal only

Decision: Horizontal tablist (inline list). No vertical orientation in D3.

Why: All current uses are horizontal. Vertical orientation will be added if a specific use case emerges.


5. ARIA pattern — tablist / tab / tabpanel

Decision: ARIA structure strictly conformant with the W3C APG:

  • role="tablist" + aria-label on the container
  • role="tab" + aria-selected + aria-controls on each tab
  • role="tabpanel" + aria-labelledby on each panel
  • Roving tabindex: active tab tabindex="0", others -1
  • Keyboard navigation: ArrowLeft/Right (circular) · Home/End · Tab exits the group

6. no-visited-nav rule — ADR-047

Decision: :visited neutralized on .tab (color = same as :link).

Why: Tabs are navigation elements — the system-wide ADR-047 rule applies.


Component tokens

TokenSemantic value
tabs.default.tab-textsemantic.color.text.secondary
tabs.default.tab-text-hoversemantic.color.text.primary
tabs.default.tab-text-activesemantic.color.action.primary
tabs.default.indicatorsemantic.color.action.primary
tabs.default.bordersemantic.color.border.default
tabs.default.border-focussemantic.color.border.focus
tabs.default.padding-xsemantic.space.control.padding-x
tabs.default.padding-ysemantic.space.control.padding-y

Reference UX patterns applied

PatternSourceApplied
Tablist above the panelNN/g
In-page tabs (instant change)NN/g
Automatic activation on focusW3C APG
Arrow keys + Home/End + roving tabindexW3C APG
Full tablist/tab/tabpanel ARIAW3C APG
Labels in natural case (never ALL-CAPS)NN/g
:visited neutralized (navigation)ADR-047
Optional href (navigation tabs)NN/g

Rejected alternatives

AlternativeReason for rejection
role="group" + aria-current (like agtc-segmented)Tabs change a panel — tablist is the correct ARIA pattern
Manual activation by defaultThe APG recommends auto when content is preloaded
Closable tabs from D3No use case in the current doc-chrome

Consequences

  • agtc-segmented remains the pattern for immediate-effect settings (≤5 options, no panel).
  • agtc-tabs is the pattern for in-page navigation with a content panel.
  • The distinction is documented in both components' guidelines.

Contexte

Phase D3 du redesign site : le doc-chrome nécessite un composant d'onglets pour structurer les pages composant (ex. Aperçu | Tokens | Bonnes pratiques). Aucun agtc-tabs n'existait.


Décisions

1. Type de tabs — in-page + href optionnel

Décision : in-page par défaut (changement de panneau dans le DOM), avec attribut href optionnel par tab pour les liens de navigation externe.

Pourquoi : La majorité des usages doc-chrome sont in-page. Le href optionnel permet des tabs mixtes (ex. Aperçu | Storybook ↗) sans créer deux composants distincts.

Source : NN/g — Tabs: Used Right


2. Activation automatique au focus

Décision : activation="auto" par défaut — naviguer avec les flèches active le tab immédiatement. activation="manual" disponible en opt-in (nécessite Entrée/Espace).

Pourquoi : L'APG recommande l'activation automatique quand le contenu est préchargé (notre cas — tout le contenu de panel est dans le DOM). Réduit le nombre de frappes.

Source : W3C APG — Tabs Pattern


3. Tabs fermables — différé

Décision : Non implémenté en D3. Aucun cas d'usage identifié dans le doc-chrome. À reconsidérer lors d'un futur éditeur multi-doc.


4. Orientation — horizontal uniquement

Décision : Tablist horizontal (liste en ligne). Pas d'orientation verticale en D3.

Pourquoi : Tous les usages actuels sont horizontaux. L'orientation verticale sera ajoutée si un cas d'usage précis émerge.


5. Pattern ARIA — tablist / tab / tabpanel

Décision : Structure ARIA strictement conforme au W3C APG :

  • role="tablist" + aria-label sur le conteneur
  • role="tab" + aria-selected + aria-controls sur chaque onglet
  • role="tabpanel" + aria-labelledby sur chaque panneau
  • Roving tabindex : tab actif tabindex="0", les autres -1
  • Navigation clavier : ArrowLeft/Right (circulaire) · Home/End · Tab sort du groupe

6. Règle no-visited-nav — ADR-047

Décision : :visited neutralisé sur .tab (color = même que :link).

Pourquoi : Les tabs sont des éléments de navigation — la règle système ADR-047 s'applique.


Tokens de composant

TokenValeur sémantique
tabs.default.tab-textsemantic.color.text.secondary
tabs.default.tab-text-hoversemantic.color.text.primary
tabs.default.tab-text-activesemantic.color.action.primary
tabs.default.indicatorsemantic.color.action.primary
tabs.default.bordersemantic.color.border.default
tabs.default.border-focussemantic.color.border.focus
tabs.default.padding-xsemantic.space.control.padding-x
tabs.default.padding-ysemantic.space.control.padding-y

Patterns UX de référence appliqués

PatternSourceAppliqué
Tablist au-dessus du panelNN/g
In-page tabs (changement instantané)NN/g
Activation automatique au focusW3C APG
Flèches + Home/End + roving tabindexW3C APG
ARIA tablist/tab/tabpanel completW3C APG
Labels en casse naturelle (jamais ALL-CAPS)NN/g
:visited neutralisé (navigation)ADR-047
href optionnel (navigation tabs)NN/g

Alternatives rejetées

AlternativeRaison du rejet
role="group" + aria-current (comme agtc-segmented)Les tabs changent un panneau — tablist est le pattern ARIA correct
Activation manuelle par défautAPG recommande l'auto quand contenu préchargé
Tabs fermables dès D3Pas de cas d'usage dans le doc-chrome actuel

Conséquences

  • agtc-segmented reste le pattern pour les réglages à effet immédiat (≤ 5 options, sans panneau).
  • agtc-tabs est le pattern pour la navigation in-page avec panneau de contenu.
  • La distinction est documentée dans les guidelines des deux composants.
← ADR-055 ADR-057 →