Componentes
Card
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.Anatomia
agendados 124 · capacidade 200
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]
| Prop | Tipo | Padrão | O 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. |
| className | string | — | Composto 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
data-dim-keep: fura o véu e continua legível enquanto se edita.| Momento | O que o card faz |
|---|---|
| Repouso | border-border + shadow-xs. Quase plano. |
| Controle interno em foco | border-brand + ring-[3px] ring-brand-muted, em 150ms. |
| Um bloco data-dim em edição na página | O 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ção | data-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
Cadastros
207
12 novos esta semana
Comparecimento
84%
vs. 79% no mês passado
Sem responder
8
há mais de 24h
| Peça | Receita |
|---|---|
| Moldura | rounded-xl border border-border bg-surface px-4 py-3 sm:px-5 |
| Título | text-sm font-semibold, com o ícone do domínio à esquerda |
| Valor | text-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
Card clicável
| O card faz o quê | Hover | Por quê |
|---|---|---|
| Abre, navega, mostra o detalhe | hover:bg-ink-50 | Mesmo hover da linha de tabela: o app inteiro passa a dizer “isto é clicável” de um jeito só. |
| É uma escolha que fica selecionada | hover:bg-ink-50 hover:border-brand | A 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
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)
Sim
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.
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.