Pular para o conteúdo
Card

Componentes

Card

A superfície padrão do produto: rounded-xl, borda de 1px e um fio de sombra. Quase plano em repouso — e é justamente por ser plano que ele consegue acender no foco enquanto os irmãos apagam.
src/components/ui/card.tsxdata-slot="card"42 usos em 28 arquivos

Anatomia

Cinco peças, e o ritmo vertical já vem pronto: py-6 no card, px-6 nas partes, gap-6 entre elas.
Ocupação da agenda
Esta semana, de segunda a sábado.

agendados 124 · capacidade 200

Card > CardHeader (CardTitle + CardDescription) > CardContent
ui/card.tsx — a classe do Card
flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-xs
[transition:border-color_150ms,box-shadow_150ms,opacity_300ms]
focus-within:border-brand focus-within:ring-[3px] focus-within:ring-brand-muted
motion-reduce:[transition:none]
PropTipoPadrãoO que faz
CardTitle as"div" | "h1" | "h2""div"Existe por acessibilidade, não por estilo. Na maioria dos usos o card é um bloco DENTRO de uma tela que já tem seu h1; promover todos criaria vários títulos de nível 1. Mas nas telas de acesso o card É a tela — ali, as="h1", senão a página fica sem heading nenhum e quem navega por títulos não encontra a tela de login.
classNamestringComposto por cn() — a classe do chamador vence. Use pra largura e col-span, não pra trocar raio ou sombra.

Não existem CardFooter nem CardAction: o rodapé é uma linha dentro do CardContent, e a ação do cabeçalho entra no CardHeader com justify-between. Menos peças, menos jeitos de divergir.

Vivo ao toque

A regra que dá nome à assinatura do produto — e ela mora no CSS global, não no componente. Toque no campo abaixo.
Dados da clínica
O cabeçalho é data-dim-keep: fura o véu e continua legível enquanto se edita.
focus-within acende a borda e o anel da marca; o foco em camadas cuida do resto da tela
MomentoO que o card faz
Repousoborder-border + shadow-xs. Quase plano.
Controle interno em focoborder-brand + ring-[3px] ring-brand-muted, em 150ms.
Um bloco data-dim em edição na páginaO card RECUA: ganha uma película de 40% e devolve a borda neutra — o único destaque em cena passa a ser o bloco elevado.
Cabeçalho durante a ediçãodata-dim-keep fura a película e fica aceso.

NotaPor que a regra é global e não uma prop

[data-slot="card"] em globals.css alcança todo card do app sem que nenhum card saiba disso. Regra solta fora de @layer vence qualquer utility do Tailwind v4 — é o que permite o card devolver a borda sem !important, e o que exige cuidado: position: relative ali sobrescreveria um sticky de classe, se algum card usasse.

Cartão de número

O molde que o app usa pra mostrar um número que importa: ícone + título, o valor grande em tabular, e um rodapé que dá o contexto (ou o alerta).

Cadastros

207

12 novos esta semana

Comparecimento

84%

vs. 79% no mês passado

Sem responder

8

há mais de 24h

panorama-view · rounded-xl border px-4 py-3 sm:px-5 · valor text-2xl font-bold tabular-nums
PeçaReceita
Moldurarounded-xl border border-border bg-surface px-4 py-3 sm:px-5
Títulotext-sm font-semibold, com o ícone do domínio à esquerda
Valortext-2xl font-bold tracking-tight tabular-nums
Rodapétext-xs text-fg-subtle — ou text-warning-strong quando é alerta
Valor menor dentro de um bloco (a “cifra”)text-xl font-semibold tabular-nums + rótulo text-xs text-fg-subtle

NotaNúmero não é filtro

Estes cartões INFORMAM. Quem filtra a lista é o chip de recorte da toolbar — outra peça, outra forma (ver Anatomia de uma tela). Misturar os dois faz a pessoa clicar num número esperando que a lista mude.

Card clicável

Se o card inteiro é um alvo, ele precisa dizer isso antes do clique. E o hover é sempre por COR, nunca por sombra.
navega ou abre detalhe · hover:bg-ink-50 — o mesmo hover da linha de tabela
é uma ESCOLHA que vai ficar selecionada · hover:bg-ink-50 hover:border-brand
O card faz o quêHoverPor quê
Abre, navega, mostra o detalhehover:bg-ink-50Mesmo hover da linha de tabela: o app inteiro passa a dizer “isto é clicável” de um jeito só.
É uma escolha que fica selecionadahover:bg-ink-50 hover:border-brandA borda verde ANTECIPA a seleção. Fora desse caso ela mente: promete um estado que não vai existir.

NuncaSombra não é hover

hover:shadow e hover:shadow-md saíram do vocabulário: sombra preta não desenha sobre fundo escuro — nos três temas escuros o hover por elevação simplesmente não acontecia, e metade das pessoas não via retorno nenhum ao passar o mouse. No escuro, elevação é TOM; e tom no hover brigaria com a cor da superfície. Por isso: cor, sempre.

O resto da regra: o alvo é <button> ou <a> de verdade (nunca div com onClick), leva focus-ring, e a transição é transition-colors — não transition-all, que arrastaria junto qualquer transform.

NotaA bolha de chat fica de fora

Mensagem não é card: a bolha já carrega cor própria (brand-muted na saída, surface na entrada), e um hover:bg-ink-50 apagaria justamente o sinal de quem falou. Ela mantém o hover de sombra como exceção declarada — e é a única.

Cabeçalho em card próprio (split)

Quando o que EXPLICA o conceito e o que OPERA a lista disputam o mesmo retângulo, eles se separam.
Insumos
O que se gasta por procedimento. Cada insumo entra no custo da ficha e no preço sugerido.
Luva de procedimentoR$ 0,24/un
Agulha 30GR$ 0,31/un
CrudCard com split — a descrição ganha medida de leitura e o CTA vira o verde da tela

Sim

Equipe
Quem entra na clínica.
Conteúdo do card.

Título e descrição à esquerda, ação à direita, gap-3, e o conteúdo respirando no CardContent.

Não

Equipe

Quem entra na clínica.

Conteúdo do card.

Card montado à mão: respiro de 12px, sombra pesada, sem data-slot (o foco em camadas não alcança) e sem as peças semânticas.