Tabs
Alternância de conteúdo relacionado com tablist, triggers e panels.
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from '@/components/ui/tabs'
export function TabsExample() {
return (
<Tabs defaultValue="overview" className="w-[420px]">
<TabsList>
<TabsTrigger value="overview">Visão geral</TabsTrigger>
<TabsTrigger value="details">Detalhes</TabsTrigger>
<TabsTrigger value="history">Histórico</TabsTrigger>
</TabsList>
<TabsContent value="overview">Conteúdo da visão geral.</TabsContent>
<TabsContent value="details">Conteúdo de detalhes.</TabsContent>
<TabsContent value="history">Histórico do paciente.</TabsContent>
</Tabs>
)
} <script setup lang="ts">
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from '@/components/ui/tabs'
</script>
<template>
<Tabs default-value="overview" class="w-[420px]">
<TabsList>
<TabsTrigger value="overview">Visão geral</TabsTrigger>
<TabsTrigger value="details">Detalhes</TabsTrigger>
<TabsTrigger value="history">Histórico</TabsTrigger>
</TabsList>
<TabsContent value="overview">Conteúdo da visão geral.</TabsContent>
<TabsContent value="details">Conteúdo de detalhes.</TabsContent>
<TabsContent value="history">Histórico do paciente.</TabsContent>
</Tabs>
</template> <div class="itps-tabs" data-itps-tabs>
<div class="itps-tabs__list" role="tablist" aria-label="Dados do paciente">
<button
type="button"
class="itps-tabs__trigger"
id="patient-overview-tab"
role="tab"
aria-controls="patient-overview-panel"
aria-selected="true"
tabindex="0"
>
Visão geral
</button>
<button
type="button"
class="itps-tabs__trigger"
id="patient-details-tab"
role="tab"
aria-controls="patient-details-panel"
aria-selected="false"
tabindex="-1"
>
Detalhes
</button>
<button
type="button"
class="itps-tabs__trigger"
id="patient-history-tab"
role="tab"
aria-controls="patient-history-panel"
aria-selected="false"
tabindex="-1"
>
Histórico
</button>
</div>
<div class="itps-tabs__panel" id="patient-overview-panel" role="tabpanel" aria-labelledby="patient-overview-tab" tabindex="0">
Conteúdo da visão geral.
</div>
<div class="itps-tabs__panel" id="patient-details-panel" role="tabpanel" aria-labelledby="patient-details-tab" tabindex="0" hidden>
Conteúdo de detalhes.
</div>
<div class="itps-tabs__panel" id="patient-history-panel" role="tabpanel" aria-labelledby="patient-history-tab" tabindex="0" hidden>
Histórico do paciente.
</div>
</div> Instalação
Instale o Tabs da sua stack e rode o comando individual ITpS em seguida. O comando itps add tabs é theme-only: ele valida o slug e confirma que o contrato visual vem do tema ITpS, das classes copy-first e dos snippets desta página.
terminal · React/Next
pnpm dlx shadcn@latest add tabs
pnpm dlx github:ITPS/sinapse-ui-cli add tabs terminal · Vue3/Nuxt4
pnpm dlx shadcn-vue@latest add tabs
pnpm dlx github:ITPS/sinapse-ui-cli add tabs O comando individual adapta só este componente; não instala o catálogo inteiro.
Uso
Em React/Next com shadcn/ui e Vue3/Nuxt4 com shadcn-vue, use os compound components Tabs, TabsList, TabsTrigger e TabsContent. Eles carregam estado e navegação por teclado da stack.
Use itps-tabs quando precisar do contrato copy-first em HTML ou wrappers finos. No site, src/scripts/tabs.ts inicializa [data-itps-tabs]; em produto, mantenha o mesmo contrato ou use o componente da sua stack.
Exemplos
Estrutura
| Peça | React/Next e Vue3/Nuxt4 | HTML |
|---|---|---|
| Raiz | Tabs defaultValue="..." | itps-tabs[data-itps-tabs] |
| Lista | TabsList | itps-tabs__list[role="tablist"] |
| Trigger | TabsTrigger value="..." | itps-tabs__trigger[role="tab"] |
| Painel | TabsContent value="..." | itps-tabs__panel[role="tabpanel"] |
Com ícones
Use ícones quando eles ajudam a diferenciar seções com labels curtas. O ícone deve vir antes do texto e permanecer decorativo.
<div class="itps-tabs" data-itps-tabs>
<div class="itps-tabs__list" role="tablist" aria-label="Projeto">
<button
type="button"
class="itps-tabs__trigger"
id="project-summary-tab"
role="tab"
aria-controls="project-summary-panel"
aria-selected="true"
tabindex="0"
>
<i class="ti ti-layout-dashboard" aria-hidden="true"></i>
<span>Resumo</span>
</button>
<button
type="button"
class="itps-tabs__trigger"
id="project-files-tab"
role="tab"
aria-controls="project-files-panel"
aria-selected="false"
tabindex="-1"
>
<i class="ti ti-folder" aria-hidden="true"></i>
<span>Arquivos</span>
</button>
<button
type="button"
class="itps-tabs__trigger"
id="project-team-tab"
role="tab"
aria-controls="project-team-panel"
aria-selected="false"
tabindex="-1"
>
<i class="ti ti-users" aria-hidden="true"></i>
<span>Equipe</span>
</button>
</div>
<div class="itps-tabs__panel" id="project-summary-panel" role="tabpanel" aria-labelledby="project-summary-tab" tabindex="0">
Resumo executivo.
</div>
<div class="itps-tabs__panel" id="project-files-panel" role="tabpanel" aria-labelledby="project-files-tab" tabindex="0" hidden>
Lista de arquivos.
</div>
<div class="itps-tabs__panel" id="project-team-panel" role="tabpanel" aria-labelledby="project-team-tab" tabindex="0" hidden>
Membros do time.
</div>
</div> Estados e teclado
| Estado | React/Next e Vue3/Nuxt4 | HTML |
|---|---|---|
| Ativa inicial | defaultValue | aria-selected="true" + tabindex="0" |
| Inativa | valor diferente do ativo | aria-selected="false" + tabindex="-1" |
| Painel oculto | gerenciado por TabsContent | hidden no painel inativo |
O teclado esperado é ArrowLeft/ArrowRight para navegar, Home/End para extremos e foco no trigger ativo.
API copy-first
| Classe/atributo | Uso |
|---|---|
itps-tabs | Wrapper visual e raiz de comportamento. |
data-itps-tabs | Marca a raiz inicializável pelo script. |
itps-tabs__list | Container com role="tablist". |
itps-tabs__trigger | Botão com role="tab". |
itps-tabs__panel | Painel com role="tabpanel". |
aria-selected | Comunica qual trigger está ativo. |
aria-controls | Liga trigger ao painel. |
aria-labelledby | Liga painel ao trigger. |
tabindex | Mantém foco no trigger ativo e nos painéis focáveis. |
hidden | Oculta painéis inativos. |
ArrowLeft / ArrowRight | Navegam entre triggers. |
Home / End | Levam para o primeiro ou último trigger. |
Acessibilidade
Use role="tablist" no container de tabs, role="tab" nos botões e role="tabpanel" nos painéis. Ligue cada tab ao painel com aria-controls; ligue cada painel à tab com aria-labelledby. Atualize aria-selected, tabindex e hidden quando a tab ativa muda.