Tabs
Alterna painéis relacionados no mesmo contexto com seleção e teclado previsíveis.
Design
Preview funcional
Executado pelo runtime JavaScript estável ds-tis/tabs.
Anatomia
Panel content goes here.
4.ds-tabs) — container com role="tablist".2 Tab (
.ds-tab) — button individual com role="tab".3 Indicador ativo — borda inferior na tab ativa.
4 Painel da tab — área de conteúdo com
role="tabpanel".
Tabs padrão
Uma tab fica ativa, as demais ficam no estado padrão. Cada tab controla um painel correspondente.
This is the Overview panel content. It provides a summary of your account status and recent activity.
Settings panel for profile, notifications preferences, and account security options.
Activity panel listing recent logins, changes, and audit events.
Com tab desabilitada
Uma tab desabilitada não pode ser interagida e é ignorada durante a navegação por teclado.
General settings for your account: display name, language, and timezone preferences.
Múltiplas tabs
As tabs rolam horizontalmente quando excedem o container.
Dashboard panel showing project metrics, recent commits, and team activity overview.
Mapeamento de tokens
| Propriedade | Token | Variável CSS |
|---|---|---|
| texto (inativo) | component.tabs.label.color.default | --ds-tabs-label-color-default |
| texto (hover) | component.tabs.label.color.hover | --ds-tabs-label-color-hover |
| texto (ativo) | component.tabs.label.color.active | --ds-tabs-label-color-active |
| texto (desabilitado) | component.tabs.label.color.disabled | --ds-tabs-label-color-disabled |
| indicador ativo | component.tabs.indicator.fill.active | --ds-tabs-indicator-fill-active |
| divider | semantic.overlay.default | --ds-overlay-default |
| borda da lista | component.tabs.list.border-width.default | --ds-tabs-list-border-width-default |
| espaçamento do item | component.tabs.item.{padding-x,padding-top}.default | --ds-tabs-item-padding-*-default |
| gap até o indicador | component.tabs.item.indicator-gap.default | --ds-tabs-item-indicator-gap-default |
| altura do indicador | component.tabs.indicator.height.default | --ds-tabs-indicator-height-default |
| tipografia do rótulo | component.tabs.label.{font-size,line-height,font-weight,letter-spacing}.default | --ds-tabs-label-*-default |
| espaçamento do painel | component.tabs.panel.padding-y.default | --ds-tabs-panel-padding-y-default |
| focus ring | component.focus-ring.{color.default,width} | --ds-focus-ring-color-default, --ds-focus-ring-width |
| raio do focus ring | component.tabs.focus-ring.radius.default | --ds-tabs-focus-ring-radius-default |
Uso
Quando usar
Boas práticas
Diretrizes de conteúdo
| Regra | Exemplo |
|---|---|
| Use substantivos como rotulos | "Overview", "Settings", "Activity" — não "View overview" ou "Go to settings" |
| Mesmo nível hierarquico | Todas as tabs devem representar categorias paralelas do mesmo conteúdo |
| Sem ícones sem texto | Sempre inclua um rotulo de texto — ícones sozinhos são ambíguos no contexto de tabs |
| Rotulos curtos (1-2 palavras) | "Pull Requests" — não "View all pull requests in this project" |
Relacionados
Implementação
- Status
- Estável
- Distribuição
- Pacote npm
Instalação
npm install ds-tispnpm add ds-tisyarn add ds-tisbun add ds-tisImportações
import 'ds-tis/css'
import { initTabs } from 'ds-tis/tabs'
initTabs()Markup
<div class="ds-tabs" role="tablist" aria-label="Seções do projeto">
<button class="ds-tab ds-tab--active" role="tab" id="overview-tab" aria-selected="true" aria-controls="overview-panel">Visão geral</button>
<button class="ds-tab" role="tab" id="team-tab" aria-selected="false" aria-controls="team-panel" tabindex="-1">Equipe</button>
</div>
<div class="ds-tab-panel" role="tabpanel" id="overview-panel" aria-labelledby="overview-tab">Resumo do projeto.</div>
<div class="ds-tab-panel" role="tabpanel" id="team-panel" aria-labelledby="team-tab" hidden>Equipe do projeto.</div>Contrato da implementação Web
Classes CSS
| Classe | Descrição |
|---|---|
ds-tabs | Container da lista de tabs |
ds-tab | Button individual de tab |
ds-tab--active | Tab ativa / selecionada |
disabled (atributo HTML) | Tab desabilitada — usar o atributo nativo disabled; não existe classe ds-tab--disabled |
ds-tab-panel | Área de conteúdo do painel |
Runtime obrigatório
O CSS define anatomia e estados visuais, mas seleção, roving tabindex, setas e sync dos painéis dependem do módulo público ds-tis/tabs (initTabs / destroyTabs). Evento: ds-tabs-change. Chame destroyTabs ao desmontar.
Acessibilidade
Interação por teclado
| Tecla | Ação |
|---|---|
Tab | Move o foco para a lista de tabs, parando na tab ativa |
Arrow Left / Arrow Right | Move para a tab anterior / proxima (ativa automaticamente) |
Home | Move para a primeira tab |
End | Move para a ultima tab |
Tab (da lista) | Move o foco para o conteúdo do painel ativo |
Tabs desabilitadas são ignoradas na navegação por setas. Apenas a tab ativa está na sequência Tab (tabindex="0"); todas as outras tem tabindex="-1".
Accessibility
| Critério WCAG | Requisito | Status |
|---|---|---|
| 4.1.2 Name, Role, Value (A) | role="tablist", role="tab", role="tabpanel". aria-selected nas tabs. aria-controls / aria-labelledby vinculando tabs a paineis. | ✓ |
| 2.1.1 Keyboard (A) | Setas navegam entre tabs. Tab entra e sai da lista de tabs. | ✓ |
| 2.4.11 Focus Appearance (AA) | Focus ring visível na tab ativa quando focada. | ✓ |
role="tablist" — no container da lista de tabs.role="tab" — em cada button de tab.role="tabpanel" — em cada painel de conteúdo.aria-selected="true|false" — indica a tab ativa.aria-controls — em cada tab, apontando para o ID do painel correspondente.aria-labelledby — em cada painel, apontando para o ID da tab correspondente.aria-disabled="true" — em tabs desabilitadas.
Responsabilidade da saída
Inicialize o runtime público após o render e destrua-o quando a view responsável for desmontada.
Evidência de validação
Coberta pelo Storybook estável, testes do runtime público quando aplicável, cenários de teclado, responsividade e Axe.