Sur cette page

Accessibilité

#Lien direct vers cette section

Pris en charge automatiquement

#Lien direct vers cette section
  • Le tablist reçoit role="tablist", chaque onglet role="tab" et chaque panneau role="tabpanel".
  • Les associations aria-controls (onglet → panneau) et aria-labelledby (panneau → onglet) sont calculées et posées automatiquement sur les hôtes en light DOM — les IDREF restent dans le même arbre et sont lisibles par les technologies d’assistance.
  • WCAG 2.1.1 (ouvre dans un nouvel onglet)Keyboard : toutes les fonctionnalités doivent être accessibles au clavier. : navigation ←/→ entre les onglets, Home/End pour le premier/dernier, Tab pour atteindre le panneau actif.
  • L’onglet actif a tabindex="0", les inactifs tabindex="-1" (roving tabindex).
  • Les panneaux inactifs ont l’attribut hidden natif — exclus du flux de tabulation et invisibles aux lecteurs d’écran.

Scroll horizontal et overflow

#Lien direct vers cette section
WCAG 1.4.10 (ouvre dans un nouvel onglet)Reflow : le contenu doit être accessible à 320px de large sans scroll horizontal.

Le tablist utilise un scroll horizontal natif (overflow-x: auto). Les onglets restent toujours accessibles au clavier via les flèches (l’onglet actif est automatiquement ramené dans le viewport). Cette approche s’appuie sur l’exception WCAG 1.4.10 pour les éléments de navigation à mise en page bidimensionnelle.

Recommandations pour votre design system :

  • Les techniques de signalement d’overflow (mask-image, boutons de scroll via scrollNav()) sont démontrées dans les variantes Scroll hints et Boutons de scroll.
  • Si une scrollbar visible est souhaitée, stylez ar-tab-group::part(nav)::-webkit-scrollbar et scrollbar-width.

À votre charge

#Lien direct vers cette section
  • Nommer le tablist : si la page contient plusieurs ar-tab-group, ajoutez l’attribut label sur chacun — il devient l’aria-label du tablist, permettant aux lecteurs d’écran de les distinguer.
  • Libellés des onglets : le texte visible de l’onglet est son nom accessible. Évitez les onglets avec des icônes seules sans texte alternatif (aria-label sur ar-tab).

Utilisation

#Lien direct vers cette section

Écouter le changement d’onglet

#Lien direct vers cette section

ar-tab-group émet ar-tab-group-change à chaque changement d’onglet actif, avec le nom du panel dans detail :

document.querySelector('ar-tab-group').addEventListener('ar-tab-group-change', (e) => {
    console.log('Onglet actif :', e.detail.active);
});

L’événement se déclenche aussi automatiquement quand l’onglet actif est retiré du DOM : un autre onglet est réélu et ar-tab-group-change est émis avec son nom, sans action de votre part.

Activation manuelle vs automatique

#Lien direct vers cette section

Par défaut (manual-activation absent), les flèches déplacent le focus et activent immédiatement l’onglet ciblé — ar-tab-group-change se déclenche à chaque flèche. Voir la variante Activation manuelle pour le comportement avec manual-activation.

Exemples

#Lien direct vers cette section

Les exemples de cette page sont affichés avec le thème neutre du starter-kit.

Par défaut

#Lien direct vers cette section

Déclarer les onglets avec `<ar-tab panel="nom">` et les panneaux avec `<ar-tab-panel name="nom">`. L'association se fait par correspondance du nom.

Introduction Utilisation API Contenu de l'onglet Introduction. Contenu de l'onglet Utilisation. Contenu de l'onglet API.
Voir le code
<ar-tab-group>
    <ar-tab panel="intro">Introduction</ar-tab>
    <ar-tab panel="usage">Utilisation</ar-tab>
    <ar-tab panel="api">API</ar-tab>
    <ar-tab-panel name="intro" style="padding: 0.75rem 1rem">Contenu de l'onglet Introduction.</ar-tab-panel>
    <ar-tab-panel name="usage" style="padding: 0.75rem 1rem">Contenu de l'onglet Utilisation.</ar-tab-panel>
    <ar-tab-panel name="api" style="padding: 0.75rem 1rem">Contenu de l'onglet API.</ar-tab-panel>
</ar-tab-group>

Onglet initial

#Lien direct vers cette section

Utilisez l'attribut `active` pour définir l'onglet ouvert par défaut.

Introduction Utilisation API Introduction. Cet onglet est actif par défaut. API.
Voir le code
<ar-tab-group active="usage">
    <ar-tab panel="intro">Introduction</ar-tab>
    <ar-tab panel="usage">Utilisation</ar-tab>
    <ar-tab panel="api">API</ar-tab>
    <ar-tab-panel name="intro" style="padding: 0.75rem 1rem">Introduction.</ar-tab-panel>
    <ar-tab-panel name="usage" style="padding: 0.75rem 1rem">Cet onglet est actif par défaut.</ar-tab-panel>
    <ar-tab-panel name="api" style="padding: 0.75rem 1rem">API.</ar-tab-panel>
</ar-tab-group>

Onglet désactivé

#Lien direct vers cette section

L'attribut `disabled` sur un `<ar-tab>` rend l'onglet non sélectionnable et l'exclut de la navigation clavier.

Actif Désactivé Actif aussi Panel A. Panel B (inaccessible). Panel C.
Voir le code
<ar-tab-group>
    <ar-tab panel="a">Actif</ar-tab>
    <ar-tab panel="b" disabled>Désactivé</ar-tab>
    <ar-tab panel="c">Actif aussi</ar-tab>
    <ar-tab-panel name="a" style="padding: 0.75rem 1rem">Panel A.</ar-tab-panel>
    <ar-tab-panel name="b" style="padding: 0.75rem 1rem">Panel B (inaccessible).</ar-tab-panel>
    <ar-tab-panel name="c" style="padding: 0.75rem 1rem">Panel C.</ar-tab-panel>
</ar-tab-group>

Activation manuelle

#Lien direct vers cette section

Avec `manual-activation`, les flèches déplacent le focus sans changer l'onglet actif — il faut appuyer sur Entrée ou Espace pour confirmer. Utile quand le contenu du panel est coûteux à charger.

Tab A Tab B Tab C Panel A. Panel B. Panel C.
Voir le code
<ar-tab-group manual-activation>
    <ar-tab panel="a">Tab A</ar-tab>
    <ar-tab panel="b">Tab B</ar-tab>
    <ar-tab panel="c">Tab C</ar-tab>
    <ar-tab-panel name="a" style="padding: 0.75rem 1rem">Panel A.</ar-tab-panel>
    <ar-tab-panel name="b" style="padding: 0.75rem 1rem">Panel B.</ar-tab-panel>
    <ar-tab-panel name="c" style="padding: 0.75rem 1rem">Panel C.</ar-tab-panel>
</ar-tab-group>

Boutons de scroll

#Lien direct vers cette section

La méthode publique `scrollNav(direction, amount?)` permet de piloter facilement le défilement de la tablist sans accéder au shadow DOM. Dans l'exemple suivante, les boutons sont affichés/masqués via CSS `:has()` en fonction des classes `has-overflow-start` / `has-overflow-end`.

Premier onglet Deuxième onglet Troisième onglet Quatrième onglet Panel A. Panel B. Panel C. Panel D.
Voir le code
<style>
  .demo-scroll-nav {
      max-width: 350px;
      position: relative;
  }
  .demo-scroll-nav button {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 2rem;
      height: 2rem;
      border: none;
      border-radius: 0.375rem;
      background: var(--doc-bg);
      color: var(--ar-color-interactive);
      cursor: pointer;
      font-size: 1rem;
      transition: opacity 0.15s;
      position: absolute;
      top: .5rem;

      &:hover {
          background-color: var(--ar-color-bg-subtle);
      }
  }

  .demo-scroll-nav .btn-start {
      left: -1rem;
  }

  .demo-scroll-nav .btn-end {
      right: -2.3rem;
  }

  .demo-scroll-nav:not(:has(ar-tab-group.has-overflow-start)) .btn-start,
  .demo-scroll-nav:not(:has(ar-tab-group.has-overflow-end)) .btn-end {
      opacity: 0.3;
      pointer-events: none;
  }
</style>
<div class="demo-scroll-nav">
  <button class="btn-start" onclick="this.parentElement.querySelector('ar-tab-group').scrollNav('start')" aria-label="Défiler vers le début">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5"><path fill-rule="evenodd" d="M11.78 5.22a.75.75 0 0 1 0 1.06L8.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06l-4.25-4.25a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" /></svg>
  </button>
  <ar-tab-group>
      <ar-tab panel="a">Premier onglet</ar-tab>
      <ar-tab panel="b">Deuxième onglet</ar-tab>
      <ar-tab panel="c">Troisième onglet</ar-tab>
      <ar-tab panel="d">Quatrième onglet</ar-tab>
      <ar-tab-panel name="a" style="padding: 0.75rem 1rem">Panel A.</ar-tab-panel>
      <ar-tab-panel name="b" style="padding: 0.75rem 1rem">Panel B.</ar-tab-panel>
      <ar-tab-panel name="c" style="padding: 0.75rem 1rem">Panel C.</ar-tab-panel>
      <ar-tab-panel name="d" style="padding: 0.75rem 1rem">Panel D.</ar-tab-panel>
  </ar-tab-group>
  <button class="btn-end" onclick="this.parentElement.querySelector('ar-tab-group').scrollNav('end')" aria-label="Défiler vers la fin">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5"><path fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /></svg>
  </button>
</div>

Scroll hints

#Lien direct vers cette section

Les classes `has-overflow-start` et `has-overflow-end` sont posées automatiquement sur l'hôte. Cette démo branche un `mask-image` CSS sur ces classes pour signaler l'overflow en temps réel — aucun attribut requis.

Premier onglet Deuxième onglet Troisième onglet Quatrième onglet Panel A. Panel B. Panel C. Panel D.
Voir le code
<style>
    .demo-scroll ar-tab-group.has-overflow-start:not(.has-overflow-end)::part(nav) {
        mask-image: linear-gradient(to right, transparent, black 3rem);
    }
    .demo-scroll ar-tab-group.has-overflow-end:not(.has-overflow-start)::part(nav) {
        mask-image: linear-gradient(to left, transparent, black 3rem);
    }
    .demo-scroll ar-tab-group.has-overflow-start.has-overflow-end::part(nav) {
        mask-image: linear-gradient(
            to right,
            transparent,
            black 3rem,
            black calc(100% - 3rem),
            transparent
        );
    }
</style>
<div class="demo-scroll" style="max-width: 300px;">
    <ar-tab-group>
        <ar-tab panel="a">Premier onglet</ar-tab>
        <ar-tab panel="b">Deuxième onglet</ar-tab>
        <ar-tab panel="c">Troisième onglet</ar-tab>
        <ar-tab panel="d">Quatrième onglet</ar-tab>
        <ar-tab-panel name="a" style="padding: 0.75rem 1rem">Panel A.</ar-tab-panel>
        <ar-tab-panel name="b" style="padding: 0.75rem 1rem">Panel B.</ar-tab-panel>
        <ar-tab-panel name="c" style="padding: 0.75rem 1rem">Panel C.</ar-tab-panel>
        <ar-tab-panel name="d" style="padding: 0.75rem 1rem">Panel D.</ar-tab-panel>
    </ar-tab-group>
</div>

Avec thème personnalisé

#Lien direct vers cette section

Les tokens `--ar-tab-*` permettent de changer le style de l'indicateur actif sans modifier le composant. Exemple — indicateur en haut (top border) et style pill.

Top border

Premier Deuxième Troisième Panel A. Panel B. Panel C.

Pill

Premier Deuxième Troisième Panel A. Panel B. Panel C.
Voir le code
<style>
    .demo-top ar-tab-group {
        --ar-tab-group-border-top-width: 1px;
        --ar-tab-group-border-bottom-width: 0;
    }
    .demo-top ar-tab {
        --ar-tab-active-shadow: inset 0 3px 0 var(--ar-color-interactive);
    }

    .demo-pill ar-tab-group {
      --ar-tab-group-border-top-width: 0;
      --ar-tab-group-border-bottom-width: 0;
    }
    .demo-pill ar-tab {
        --ar-tab-active-shadow: none;
        border-radius: 9999px;
    }
    .demo-pill ar-tab::part(tab--selected) {
        background: var(--ar-color-interactive-subtle);
    }
</style>
<div style="display: flex; flex-direction: column; width: 100%;">
    <p style="margin: 0 0 1.25rem; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--doc-text-muted, #6b7280);">Top border</p>
    <div class="demo-top">
        <ar-tab-group>
            <ar-tab panel="a">Premier</ar-tab>
            <ar-tab panel="b">Deuxième</ar-tab>
            <ar-tab panel="c">Troisième</ar-tab>
            <ar-tab-panel name="a" style="padding: 0.75rem 1rem">Panel A.</ar-tab-panel>
            <ar-tab-panel name="b" style="padding: 0.75rem 1rem">Panel B.</ar-tab-panel>
            <ar-tab-panel name="c" style="padding: 0.75rem 1rem">Panel C.</ar-tab-panel>
        </ar-tab-group>
    </div>
    <hr style="margin: 1.5rem 0; border: none; border-top: 1px solid var(--doc-border, #e5e7eb);" />
    <p style="margin: 0 0 1.25rem; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--doc-text-muted, #6b7280);">Pill</p>
    <div class="demo-pill">
        <ar-tab-group>
            <ar-tab panel="a">Premier</ar-tab>
            <ar-tab panel="b">Deuxième</ar-tab>
            <ar-tab panel="c">Troisième</ar-tab>
            <ar-tab-panel name="a" style="padding: 0.75rem 1rem">Panel A.</ar-tab-panel>
            <ar-tab-panel name="b" style="padding: 0.75rem 1rem">Panel B.</ar-tab-panel>
            <ar-tab-panel name="c" style="padding: 0.75rem 1rem">Panel C.</ar-tab-panel>
        </ar-tab-group>
    </div>
</div>

Démo interactive

#Lien direct vers cette section

Manipulez les attributs pour voir le code et la preview se mettre à jour.

Introduction Utilisation API Contenu de l'onglet Introduction. Contenu de l'onglet Utilisation. Contenu de l'onglet API.
<ar-tab-group>
    <ar-tab panel="intro">Introduction</ar-tab>
    <ar-tab panel="usage">Utilisation</ar-tab>
    <ar-tab panel="api">API</ar-tab>
    <ar-tab-panel name="intro" style="padding: 0.75rem 1rem">Contenu de l'onglet Introduction.</ar-tab-panel>
    <ar-tab-panel name="usage" style="padding: 0.75rem 1rem">Contenu de l'onglet Utilisation.</ar-tab-panel>
    <ar-tab-panel name="api" style="padding: 0.75rem 1rem">Contenu de l'onglet API.</ar-tab-panel>
</ar-tab-group>

Référence API

#Lien direct vers cette section

Import

#Lien direct vers cette section

Si vous utilisez l'autoloader, les composants détectés dans la pages sont chargés automatiquement, donc pas besoin de les importer individuellement.
Pour un import manuel, voici comment vous y prendre.

CDNnpm

Importez ce composant depuis le CDN.

<script type="module" src="https://unpkg.com/@ariane-ui/core/dist/components/tab-group/index.js"></script>

Après avoir installé le paquet via npm, vous pouvez importer le composant ainsi :

import '@ariane-ui/core/dist/components/tab-group/index.js';

Configuration

#Lien direct vers cette section
Attributs et propriétés 3Slots 1Événements 1Méthodes 1

Attributs et propriétés

1 sur 3
activereflète

Nom de l'onglet actif. Si absent, le premier onglet non-disabled s'active.

Type stringDéfaut ''

2 sur 3
labelreflète

aria-label sur le tablist — recommandé si plusieurs ar-tab-group sur la page.

Type stringDéfaut ''

3 sur 3
manualActivationreflètemanual-activation

Active le mode manuel : les flèches déplacent le focus sans activer l'onglet.

Type booleanDéfaut false

Slots

1 sur 1(default)

ar-tab et ar-tab-panel enfants.

Événements

1 sur 1
ar-tab-group-changedetail : { id: string | undefined, active: string }

Émis quand l'onglet actif change.

Méthodes

1 sur 1
scrollNav()direction: 'start' | 'end', amount = 200retour : void

Scrolle la zone de navigation d'un certain nombre de pixels vers `'start'` ou `'end'`.

Personnalisation

#Lien direct vers cette section
CSS Parts 3CSS Custom Properties 3

CSS Parts

Utilisez ::part(name) pour styler ces éléments depuis l'extérieur.
Certaines parts indiquent un rôle transverse, partagé avec d'autres composants — voir Personnalisation avancée.

1 sur 3tab-group

Racine du composant.

2 sur 3nav

Zone scrollable (overflow-x: auto).

3 sur 3tabs

div[role="tablist"]. Les classes `has-overflow-start` et `has-overflow-end` sont ajoutées automatiquement sur l'hôte quand le contenu de la tablist déborde à gauche ou à droite.

CSS Custom Properties

1 sur 3--ar-tab-group-border-top-width

Épaisseur du trait séparateur en haut de la la tablist. Mettre à 1px pour l'activer.

2 sur 3--ar-tab-group-border-bottom-width

Épaisseur du trait séparateur sous la tablist. Mettre à 1px pour l'activer.

3 sur 3--ar-tab-group-border-color

Couleur du trait séparateur sous la tablist.