ADR-056
Implementing `agtc-tabs`
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-labelon the containerrole="tab"+aria-selected+aria-controlson each tabrole="tabpanel"+aria-labelledbyon each panel- Roving tabindex: active tab
tabindex="0", others-1 - Keyboard navigation:
ArrowLeft/Right(circular) ·Home/End·Tabexits 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
| Token | Semantic value |
|---|---|
tabs.default.tab-text | semantic.color.text.secondary |
tabs.default.tab-text-hover | semantic.color.text.primary |
tabs.default.tab-text-active | semantic.color.action.primary |
tabs.default.indicator | semantic.color.action.primary |
tabs.default.border | semantic.color.border.default |
tabs.default.border-focus | semantic.color.border.focus |
tabs.default.padding-x | semantic.space.control.padding-x |
tabs.default.padding-y | semantic.space.control.padding-y |
Reference UX patterns applied
| Pattern | Source | Applied |
|---|---|---|
| Tablist above the panel | NN/g | ✅ |
| In-page tabs (instant change) | NN/g | ✅ |
| Automatic activation on focus | W3C APG | ✅ |
| Arrow keys + Home/End + roving tabindex | W3C APG | ✅ |
| Full tablist/tab/tabpanel ARIA | W3C APG | ✅ |
| Labels in natural case (never ALL-CAPS) | NN/g | ✅ |
:visited neutralized (navigation) | ADR-047 | ✅ |
Optional href (navigation tabs) | NN/g | ✅ |
Rejected alternatives
| Alternative | Reason for rejection |
|---|---|
role="group" + aria-current (like agtc-segmented) | Tabs change a panel — tablist is the correct ARIA pattern |
| Manual activation by default | The APG recommends auto when content is preloaded |
| Closable tabs from D3 | No use case in the current doc-chrome |
Consequences
agtc-segmentedremains the pattern for immediate-effect settings (≤5 options, no panel).agtc-tabsis 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-labelsur le conteneurrole="tab"+aria-selected+aria-controlssur chaque ongletrole="tabpanel"+aria-labelledbysur chaque panneau- Roving tabindex : tab actif
tabindex="0", les autres-1 - Navigation clavier :
ArrowLeft/Right(circulaire) ·Home/End·Tabsort 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
| Token | Valeur sémantique |
|---|---|
tabs.default.tab-text | semantic.color.text.secondary |
tabs.default.tab-text-hover | semantic.color.text.primary |
tabs.default.tab-text-active | semantic.color.action.primary |
tabs.default.indicator | semantic.color.action.primary |
tabs.default.border | semantic.color.border.default |
tabs.default.border-focus | semantic.color.border.focus |
tabs.default.padding-x | semantic.space.control.padding-x |
tabs.default.padding-y | semantic.space.control.padding-y |
Patterns UX de référence appliqués
| Pattern | Source | Appliqué |
|---|---|---|
| Tablist au-dessus du panel | NN/g | ✅ |
| In-page tabs (changement instantané) | NN/g | ✅ |
| Activation automatique au focus | W3C APG | ✅ |
| Flèches + Home/End + roving tabindex | W3C APG | ✅ |
| ARIA tablist/tab/tabpanel complet | W3C APG | ✅ |
| Labels en casse naturelle (jamais ALL-CAPS) | NN/g | ✅ |
:visited neutralisé (navigation) | ADR-047 | ✅ |
href optionnel (navigation tabs) | NN/g | ✅ |
Alternatives rejetées
| Alternative | Raison du rejet |
|---|---|
role="group" + aria-current (comme agtc-segmented) | Les tabs changent un panneau — tablist est le pattern ARIA correct |
| Activation manuelle par défaut | APG recommande l'auto quand contenu préchargé |
| Tabs fermables dès D3 | Pas de cas d'usage dans le doc-chrome actuel |
Conséquences
agtc-segmentedreste le pattern pour les réglages à effet immédiat (≤ 5 options, sans panneau).agtc-tabsest le pattern pour la navigation in-page avec panneau de contenu.- La distinction est documentée dans les guidelines des deux composants.