Tabs
Painéis de content irmãos que compartilham um context. Variant pill ou line, horizontal ou vertical, com navegação por teclado completa.
Visão geral
Tabs é o switcher canônico de content irmão: um container, várias views mutuamente exclusivas dentro dele. Construído sobre o Radix Tabs, ele oferece duas aparências de list via a prop variant em TabsList - um pill default (background arredondado) e um line minimalista (único underline no trigger ativo).
Use as Tabs quando as views vivem no mesmo escopo - Profile / Billing / API keys, ou Code / Preview para um único exemplo. Para navegação entre seções (páginas diferentes, áreas diferentes de um app), use NavigationMenu ou Sidebar. Para filtros que combinam, use ToggleGroup.
Preview
Install: npx gremorie add rx-tabs
'use client';import { Tabs, TabsContent, TabsList, TabsTrigger,} from '@gremorie/rx-navigation';export function TabsPreview() { return ( <Tabs defaultValue="react" className="w-full max-w-md"> <TabsList> <TabsTrigger value="react">React</TabsTrigger> <TabsTrigger value="angular">Angular</TabsTrigger> <TabsTrigger value="tokens">Tokens</TabsTrigger> </TabsList> <TabsContent value="react"> <p className="mt-4 text-sm text-muted-foreground"> Install: <code>npx gremorie add rx-tabs</code> </p> </TabsContent> <TabsContent value="angular"> <p className="mt-4 text-sm text-muted-foreground"> Install: <code>npx gremorie add ng-tabs</code> </p> </TabsContent> <TabsContent value="tokens"> <p className="mt-4 text-sm text-muted-foreground"> Tokens are framework-agnostic - see the Tokens tab. </p> </TabsContent> </Tabs> );}Anatomia
Tabs the Radix root; carries value / orientation
├─ TabsList the trigger track; variant default (pill) or line
│ └─ TabsTrigger one selectable tab
└─ TabsContent the panel shown for the active tabInstalação
bash npx gremorie@latest add rx-tabs bash pnpm dlx gremorie@latest add rx-tabs bash yarn dlx gremorie@latest add rx-tabs bash bunx --bun gremorie@latest add rx-tabs Uso
import {
Tabs,
TabsList,
TabsTrigger,
TabsContent,
} from "@gremorie/rx-navigation";
export function AccountTabs() {
return (
<Tabs defaultValue="profile">
<TabsList>
<TabsTrigger value="profile">Profile</TabsTrigger>
<TabsTrigger value="billing">Billing</TabsTrigger>
<TabsTrigger value="api">API keys</TabsTrigger>
</TabsList>
<TabsContent value="profile">Profile fields...</TabsContent>
<TabsContent value="billing">Billing details...</TabsContent>
<TabsContent value="api">API keys list...</TabsContent>
</Tabs>
);
}A edição Angular deste componente hoje é distribuída a partir do source (veja o side-by-side no workbench); sua entrada no registry vem a seguir.
API
<Tabs>
Container raiz. Envolve o Tabs.Root do Radix.
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | string | - | Tab ativa inicial, não controlada. |
value | string | - | Tab ativa controlada. |
onValueChange | (value: string) => void | - | Dispara quando a tab ativa muda. |
orientation | "horizontal" | "vertical" | "horizontal" | Afeta a navegação por teclado e o layout. Vertical dispõe a list e o painel lado a lado. |
dir | "ltr" | "rtl" | "ltr" | Direção de leitura para navegação por setas. |
activationMode | "automatic" | "manual" | "automatic" | "automatic" ativa uma tab no focus; "manual" exige Enter ou Space. |
<TabsList>
Container para os triggers. Envolve o Tabs.List do Radix.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "line" | "default" | "default" é uma list pill com background muted arredondado. "line" é transparente com um único underline embaixo no trigger ativo. |
loop | boolean | true | Se o foco do teclado dá a volta nas pontas. |
<TabsTrigger>
A tab clicável. Envolve o Tabs.Trigger do Radix.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | Obrigatório. Corresponde ao value do <TabsContent> correspondente. |
disabled | boolean | false | Desabilita este trigger. |
<TabsContent>
O painel revelado quando seu trigger está ativo. Envolve o Tabs.Content do Radix.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | Obrigatório. Corresponde ao value de um <TabsTrigger>. |
forceMount | boolean | false | Força o painel no DOM mesmo quando inativo (útil para animações). |
Composição
<Tabs>é dono do value ativo (controlado ou não controlado).<TabsList>envolve os triggers. A propvariantvive aqui, não no Root.- Um ou mais
<TabsTrigger>com propsvalueúnicos vão dentro da list. - Painéis
<TabsContent>são irmãos da list (não dentro dela), cada um com umvalueque corresponde a um trigger.
Renderize os triggers dentro de <TabsList> apenas - colocá-los fora quebra o contrato de navegação por teclado.
Variações
List pill (default)
Profile fields...
<Tabs defaultValue="profile">
<TabsList>
<TabsTrigger value="profile">Profile</TabsTrigger>
<TabsTrigger value="billing">Billing</TabsTrigger>
<TabsTrigger value="api">API keys</TabsTrigger>
</TabsList>
<TabsContent value="profile">Profile fields...</TabsContent>
<TabsContent value="billing">Billing details...</TabsContent>
<TabsContent value="api">API keys list...</TabsContent>
</Tabs>Use quando as tabs ficam dentro de um card ou painel e precisam de uma aparência clara e contida.
List line
High-level summary.
<Tabs defaultValue="overview">
<TabsList variant="line">
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="usage">Usage</TabsTrigger>
<TabsTrigger value="api">API</TabsTrigger>
</TabsList>
<TabsContent value="overview">High-level summary.</TabsContent>
<TabsContent value="usage">Code patterns.</TabsContent>
<TabsContent value="api">Prop tables.</TabsContent>
</Tabs>Use para tabs a nível de página onde o chrome ao redor já é pesado e um pill competiria visualmente.
Orientação vertical
'use client';import { Tabs, TabsContent, TabsList, TabsTrigger,} from '@gremorie/rx-navigation';export function TabsVerticalPreview() { return ( <Tabs defaultValue="account" orientation="vertical" className="w-full max-w-md flex-row" > <TabsList> <TabsTrigger value="account">Account</TabsTrigger> <TabsTrigger value="security">Security</TabsTrigger> <TabsTrigger value="notifications">Notifications</TabsTrigger> </TabsList> <TabsContent value="account" className="text-sm text-muted-foreground"> Update your name, email, and avatar. </TabsContent> <TabsContent value="security" className="text-sm text-muted-foreground"> Manage password and two-factor authentication. </TabsContent> <TabsContent value="notifications" className="text-sm text-muted-foreground" > Choose which emails and alerts you receive. </TabsContent> </Tabs> );}Defina orientation="vertical" e disponha a list e o painel lado a lado com flex-row. Use para menus de configuração dentro de painel. Arrow Up / Down navegam entre triggers quando vertical.
Com ícones
'use client';import { Tabs, TabsContent, TabsList, TabsTrigger,} from '@gremorie/rx-navigation';import { BellIcon, CreditCardIcon, UserIcon } from 'lucide-react';export function TabsWithIconsPreview() { return ( <Tabs defaultValue="profile" className="w-full max-w-md"> <TabsList> <TabsTrigger value="profile"> <UserIcon /> Profile </TabsTrigger> <TabsTrigger value="billing"> <CreditCardIcon /> Billing </TabsTrigger> <TabsTrigger value="alerts"> <BellIcon /> Alerts </TabsTrigger> </TabsList> <TabsContent value="profile" className="mt-4 text-sm text-muted-foreground" > Your public profile details. </TabsContent> <TabsContent value="billing" className="mt-4 text-sm text-muted-foreground" > Plan, invoices, and payment method. </TabsContent> <TabsContent value="alerts" className="mt-4 text-sm text-muted-foreground" > Notification preferences. </TabsContent> </Tabs> );}Coloque um ícone lucide-react antes do label dentro de cada trigger. Os estilos do trigger dimensionam e espaçam o ícone automaticamente.
Tab desabilitada
'use client';import { Tabs, TabsContent, TabsList, TabsTrigger,} from '@gremorie/rx-navigation';export function TabsDisabledPreview() { return ( <Tabs defaultValue="overview" className="w-full max-w-md"> <TabsList> <TabsTrigger value="overview">Overview</TabsTrigger> <TabsTrigger value="analytics" disabled> Analytics </TabsTrigger> <TabsTrigger value="reports">Reports</TabsTrigger> </TabsList> <TabsContent value="overview" className="mt-4 text-sm text-muted-foreground" > High-level summary of the workspace. </TabsContent> <TabsContent value="reports" className="mt-4 text-sm text-muted-foreground" > Scheduled and saved reports. </TabsContent> </Tabs> );}Passe disabled num <TabsTrigger> para renderizá-lo inerte. Triggers desabilitados são pulados na navegação por setas e ficam esmaecidos.
Valor controlado
const [tab, setTab] = useState('profile');
<Tabs value={tab} onValueChange={setTab}>
<TabsList>
<TabsTrigger value="profile">Profile</TabsTrigger>
<TabsTrigger value="billing">Billing</TabsTrigger>
</TabsList>
<TabsContent value="profile">...</TabsContent>
<TabsContent value="billing">...</TabsContent>
</Tabs>;Use quando a tab ativa deve sincronizar com estado da URL, um router ou um wizard de formulário.
Acessibilidade
- Padrão WAI-ARIA Tabs: a list renderiza como
role="tablist", cada trigger comorole="tab"comaria-selectedearia-controls, cada painel comorole="tabpanel"comaria-labelledby. - Teclado:
Tabentra na list e pousa no trigger ativo;ArrowLeft/ArrowRight(ouArrowUp/ArrowDownquando vertical) navegam entre triggers;Home/Endpulam para o primeiro / último;Tabde novo sai da list e pousa no painel ativo. - Modo de ativação: com
activationMode="automatic"(default), focar um trigger ativa seu painel. DefinaactivationMode="manual"quando os painéis carregam content pesado e você quer que os usuários apertemEnterouSpacepara confirmar. - Triggers desabilitados: renderizam com
aria-disabled="true"e são pulados na navegação por setas. - Focus visible: o trigger ativo mantém um focus ring visível; o painel em si usa
outline-nonee depende dos seus filhos para gerenciar o focus.
Relacionados
- NavigationMenu - navegação entre seções com painéis ricos, não content irmão.
- Sidebar - navegação de app-shell por muitas áreas.
- ToggleGroup - escolhas mutuamente exclusivas que não são containers de view.