Pular para o conteúdo
Navegação

Componentes

Navegação

Três níveis, três formas: a sidebar diz em que área você está, o rail diz em que sub-tela, e as abas dizem em que recorte da mesma tela. Todos os três são pílula — menos a aba, que é sublinhado, porque ela comunica LUGAR e não estado.
components/app-shell.tsxui/rail-nav.tsx288px

Rail

O segundo nível: as sub-telas de uma área. Ele vive DENTRO do palco de tela, nunca como coluna própria ao lado do conteúdo.
RailGroups · coluna no lg+, tira horizontal com fade no celular

RailLinks pra uma lista simples; RailGroups quando os destinos têm categorias. No lg+ o grupo vira coluna com rótulo; abaixo disso o rótulo some e os itens voltam a ser uma tira horizontal única (contents derruba o wrapper) — três tiras empilhadas custariam a altura que o palco não tem.

A pista tem mask-image na borda direita no <lg: é a pista de que há mais itens, já que a barra de rolagem fica escondida.

Item ativo por pathname, com aria-current="page". Largura útil no palco: 288 − 40 − 26 = 222px — daí o min-w-0 truncate no rótulo, senão “Custos da clínica” vaza da pista.

Recorte de visão (segmented control)

O terceiro nível: recortes da MESMA tela. No app isso é sempre um segmented control em pílula, com semântica de abas por baixo — Cadastros, Agenda e Atendimento repetem a peça.
Conteúdo de Pacientes 207 registros.
trilho rounded-full bg-ink-100 p-1 · ativo bg-surface shadow-xs · role=tablist + ← → + roving tabIndex
PeçaReceita
Trilhoflex items-center gap-1 rounded-full bg-ink-100 p-1 · overflow-x-auto
Itemh-8 rounded-full px-3.5 text-sm font-medium · pointer-coarse:h-10
Ativobg-surface text-fg shadow-xs — a pílula “sobe” dentro do trilho
Inativotext-fg-muted hover:text-fg (sem fundo)
Contagemtext-xs text-fg-subtle tabular-nums
Processo vivopulso size-1.5 rounded-full bg-info-strong
Semânticarole=tablist/tab + aria-selected + aria-controls + ← →; o painel leva role=tabpanel + aria-labelledby. Nunca aria-pressed: é crachá de toggle, não de aba
Variante moldurarounded-full border border-border (sem o trilho cinza) — a troca de visão da Agenda

Sim

ListaFunil

Um trilho, um selecionado. O conjunto lê como UM controle, e é uma parada só de Tab.

Não

ListaFunil

Dois chips soltos, cada um com sua cor: viram dois filtros independentes aos olhos de quem lê — e o verde da marca sugere “ativo”, não “selecionado entre dois”.

NotaAberto: a aba sublinhada não existe no app

O canon herdado do Prospify previa aba com sublinhado (border-b-2 border-brand) pra navegação entre sub-coleções. Hoje nenhuma tela usa — o produto resolve recorte com o segmented control acima e navegação com rail. Enquanto isso não for decidido, não introduza a aba sublinhada: ela seria a única do app.

Peças de identidade e de linha

Três componentes pequenos que aparecem em toda tela de conta e de ajustes.
RC?
AvatarBubble — 32px, foto redonda ou a inicial em brand-muted
CardIconBadge — selo de 48px no topo de cards de fluxo

Verificação em duas etapas

Um código a mais na hora de entrar.

Códigos de recuperação

Nenhum código restante.

SettingsRow — texto à esquerda, ação à direita; empilha no celular
agrupar SettingsRow
// A linha só cuida do próprio ritmo vertical; quem separa é o pai.
<div className="divide-y divide-border">
  <SettingsRow title="…" description="…"><Button/></SettingsRow>
  <SettingsRow title="…" description="…" tone="negative"><Button/></SettingsRow>
</div>

No celular a SettingsRow empilha (texto em cima, ação embaixo): lado a lado, a descrição ficava espremida em ~114px. É a regra 11 aplicada a um componente pequeno.