Field
A unidade fundamental de formulário: Label + Input + Hint/Error.
Como aparece no seu documento oficial.
Insira um e-mail válido, ex: nome@empresa.com
Aparece no seu perfil.
0 / 160
<!-- Obrigatório --> <div class="flex flex-col gap-1"> <label for="campo" class="text-sm font-medium text-zinc-700"> Rótulo <span class="text-red-500" aria-hidden="true">*</span> </label> <input id="campo" type="text" required class="w-full px-3 py-2 text-sm text-zinc-900 bg-white border border-zinc-300 placeholder:text-zinc-400 hover:border-zinc-400 focus:outline-none focus:ring-2 focus:ring-zinc-900 focus:border-transparent transition-colors" /> <p class="text-xs text-zinc-500">Hint.</p> </div> <!-- Campo com erro --> <input aria-invalid="true" aria-describedby="msg" class="... border-red-500 focus:ring-red-500"/> <p id="msg" role="alert" class="text-xs text-red-600 flex items-center gap-1.5"> Mensagem de erro. </p> <!-- Textarea com contador --> <textarea maxlength="160" ...></textarea> <div class="flex justify-between"> <p class="text-xs text-zinc-500">Hint.</p> <p class="mono text-xs text-zinc-400">0 / 160</p> </div>
Search Bar
Input + ícone + botão. Use role="search" no wrapper e type="search" no input.
Inline (input + botão)
Standalone com atalho
<!-- Inline --> <div role="search" class="flex"> <div class="relative flex-1"> <!-- ícone esquerda --> <input type="search" aria-label="Buscar" class="w-full pl-9 pr-3 py-2 text-sm border border-zinc-300 border-r-0 focus:ring-2 focus:ring-zinc-900 focus:outline-none focus:z-10 focus:border-transparent transition-colors"/> </div> <button type="submit" class="px-4 py-2 bg-zinc-900 text-white text-sm hover:bg-zinc-700"> Buscar </button> </div>
Alert / Banner
Ícone + Título + Mensagem. Use role="alert" para urgentes, role="status" para informativos.
Salvo com sucesso
Suas alterações foram aplicadas e estão visíveis.
Atenção necessária
Verifique os campos marcados antes de prosseguir.
Erro ao salvar
Não foi possível conectar ao servidor.
Manutenção programada
O sistema ficará indisponível no dia 25/03 das 02h às 04h.
<!-- Sucesso --> <div role="alert" class="flex gap-3 p-4 bg-green-50 border border-green-200"> <!-- SVG ícone --> <div> <p class="text-sm font-semibold text-green-800">Título</p> <p class="text-xs text-green-700 mt-0.5">Mensagem.</p> </div> </div> <!-- Mapa de cores: sucesso → green-50 / green-200 / green-800 warning → yellow-50 / yellow-200 / yellow-800 erro → red-50 / red-200 / red-800 info → blue-50 / blue-200 / blue-800 neutro → zinc-50 / zinc-200 / zinc-800 role="alert" → urgente (lido imediatamente) role="status" → informativo (lido quando possível) -->
Card
Container semântico de agrupamento. Variações de estrutura interna para diferentes densidades de informação.
Card simples
Agrupa informações relacionadas numa unidade visual coesa.
Com cabeçalho
Use o cabeçalho para título e ações contextuais.
Com rodapé
O rodapé abriga as ações primárias relacionadas.
Card clicável
Todo o card é interativo. Ideal para listagens navegáveis.
<!-- Simples --> <div class="border border-zinc-200 bg-white p-5"> <p class="text-sm font-semibold text-zinc-900 mb-1">Título</p> <p class="text-xs text-zinc-500 leading-relaxed">Conteúdo.</p> </div> <!-- Com header + footer --> <div class="border border-zinc-200 bg-white overflow-hidden"> <div class="px-5 py-3 border-b border-zinc-100 flex items-center justify-between"> <p class="text-sm font-semibold">Título</p> </div> <div class="p-5"></div> <div class="px-5 py-3 border-t border-zinc-100 bg-zinc-50 flex items-center gap-2"> </div> </div> <!-- Card clicável --> <a href="#" class="block border border-zinc-200 bg-white p-5 hover:border-zinc-400 hover:bg-zinc-50 focus:outline-none focus:ring-2 focus:ring-zinc-900 focus:ring-offset-2 transition-colors group"> </a>
Stat Card
Label + Valor + Tendência. Para dashboards e resumos de métricas.
Receita total
R$ 48.200
+12,4% vs. mês anterior
Novos usuários
1.284
-3,2% vs. mês anterior
Taxa de conversão
3,6%
Sem variação
Tickets abertos
47
12 urgentes<div class="border border-zinc-200 bg-white p-5"> <p class="text-xs font-medium text-zinc-500 mb-2"> Label </p> <p class="text-2xl font-bold text-zinc-900 mb-1"> Valor </p> <!-- Tendência positiva --> <p class="text-xs flex items-center gap-1 text-green-600"> <!-- SVG trend-up 14×14 --> +12,4% </p> <!-- Negativa → text-red-600 --> <!-- Ícone decorativo (opcional): bg-blue-50 + SVG text-blue-600 --> </div>
Dropdown Menu
Estrutura visual do menu suspenso. Adicione aria-expanded e toggle via JS da sua stack.
<button aria-expanded="false" aria-haspopup="menu" class="...">Opções</button> <div role="menu" class="absolute top-full left-0 mt-1 w-48 bg-white border border-zinc-200 shadow-lg z-10"> <div class="py-1"> <a role="menuitem" class="flex items-center gap-2.5 px-4 py-2 text-sm text-zinc-700 hover:bg-zinc-100 hover:text-zinc-900 transition-colors"> Item </a> <hr class="my-1 border-zinc-100" /> <!-- Item destrutivo --> <a role="menuitem" class="... text-red-600 hover:bg-red-50"> Excluir </a> </div> </div>
Pagination
Prev + Páginas + Next. Use <nav aria-label="Paginação"> e aria-current="page" na página atual.
Padrão
Simples (prev/next)
<nav aria-label="Paginação" class="flex items-center gap-1"> <!-- Página normal --> <a href="#" class="inline-flex items-center justify-center w-9 h-9 text-sm text-zinc-500 border border-zinc-200 hover:border-zinc-400 hover:text-zinc-900 transition-colors">1</a> <!-- Página atual --> <a aria-current="page" class="inline-flex items-center justify-center w-9 h-9 text-sm font-semibold bg-zinc-900 text-white border border-zinc-900">3</a> <!-- Elipse --> <span aria-hidden="true" class="w-9 h-9 inline-flex items-center justify-center text-sm text-zinc-400"> … </span> </nav>
Tabs
Navegação entre painéis de conteúdo relacionado. Use role="tablist/tab/tabpanel".
Underline
Conteúdo da aba ativa.
Pill / Filled
<!-- Underline --> <div role="tablist" class="flex border-b border-zinc-200"> <!-- Ativa --> <button role="tab" aria-selected="true" aria-controls="panel-1" class="px-4 py-2.5 text-sm font-medium text-zinc-900 border-b-2 border-zinc-900 -mb-px"> Tab </button> <!-- Inativa --> <button role="tab" aria-selected="false" class="... text-zinc-500 border-b-2 border-transparent -mb-px hover:text-zinc-700 hover:border-zinc-300 transition-colors"> Tab </button> </div> <div id="panel-1" role="tabpanel" aria-labelledby="tab-1" class="pt-4"> </div>
Empty State
Ícone + Título + Descrição + CTA. Use para listas vazias, resultados nulos e estados de onboarding.
Nenhum projeto ainda
Crie seu primeiro projeto para começar a organizar seu trabalho.
Sem resultados
Nenhum item corresponde à sua busca.
<div class="border border-dashed border-zinc-300 py-12 px-8 text-center"> <div class="w-12 h-12 bg-zinc-100 flex items-center justify-center mx-auto mb-4"> <!-- SVG 24×24 text-zinc-400 --> </div> <h3 class="text-sm font-semibold text-zinc-900 mb-1"> Nenhum item ainda </h3> <p class="text-xs text-zinc-500 mb-5 max-w-xs mx-auto"> Crie o primeiro para começar. </p> <button type="button" class="inline-flex items-center gap-2 px-4 py-2 bg-zinc-900 text-white text-sm font-medium hover:bg-zinc-700 focus:outline-none focus:ring-2 focus:ring-zinc-900 focus:ring-offset-2 transition-colors"> Criar novo </button> </div>
Accordion
CSS-only via <details>/<summary> nativos. Acessível sem JS.
O que está incluído no plano Pro?
O plano Pro inclui acesso ilimitado, suporte prioritário, exportação em PDF e histórico de 12 meses.
Posso cancelar a qualquer momento?
Sim. Cancele a qualquer momento sem multa. O acesso permanece ativo até o fim do período pago.
Item desabilitado
<div class="border border-zinc-200 divide-y divide-zinc-200"> <details class="group"> <summary class="flex items-center justify-between px-5 py-4 cursor-pointer list-none hover:bg-zinc-50 transition-colors select-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-zinc-900"> <span class="text-sm font-medium text-zinc-900"> Pergunta </span> <!-- Chevron: group-open:rotate-180 --> </summary> <div class="px-5 pb-4 pt-1"> <p class="text-sm text-zinc-600 leading-relaxed"> Resposta. </p> </div> </details> </div>
Collapse
Painel único retrátil. Mesma base <details>, estética diferente do Accordion.
Filtros avançados 3 ativos
Ver detalhes técnicos
POST /api/v2/users
Content-Type: application/json
Authorization: Bearer {token}
<details class="group border border-zinc-200 bg-white" open> <summary class="flex items-center gap-3 px-4 py-3 cursor-pointer list-none hover:bg-zinc-50 transition-colors select-none"> <!-- Chevron: group-open:rotate-90 --> <span class="text-sm font-semibold text-zinc-900"> Título </span> <!-- Badge opcional: ml-auto --> </summary> <div class="border-t border-zinc-200 px-4 py-4"> <!-- qualquer conteúdo --> </div> </details> <!-- Accordion = múltiplos itens em lista Collapse = painel único retrátil Base técnica: idêntica (<details>) -->
List
Lista de itens estruturados. Use <ul>/<li> para listas e <ol> para ordenadas.
Simples com ícone
-
ABAtivo
Ana Barros
ana@empresa.com
-
CSPendente
Carlos Silva
carlos@empresa.com
-
MFInativo
Maria Ferreira
maria@empresa.com
<ul class="divide-y divide-zinc-100 border border-zinc-200"> <li class="flex items-center gap-3 px-4 py-3 hover:bg-zinc-50 transition-colors"> <!-- Avatar/ícone --> <div class="w-8 h-8 bg-zinc-800 flex items-center justify-center flex-shrink-0"> <span class="text-xs font-semibold text-white">AB</span> </div> <!-- Texto principal --> <div class="flex-1 min-w-0"> <p class="text-sm font-medium text-zinc-900 truncate">Nome</p> <p class="text-xs text-zinc-500 truncate"> secundário </p> </div> <!-- Badge/ação (flex-shrink-0) --> </li> </ul>
File Upload
Zona de drop com fallback para botão. CSS-only com peer trick no input.
Drag zone
Arquivo selecionado
relatorio-q3-2025.pdf
2,4 MB
Botão simples
<!-- Drag zone --> <label for="upload" class="flex flex-col items-center justify-center gap-3 border-2 border-dashed border-zinc-300 bg-zinc-50 p-10 text-center cursor-pointer hover:border-zinc-500 hover:bg-zinc-100 focus-within:border-zinc-900 focus-within:bg-zinc-100 transition-colors group"> <!-- Input real, invisível --> <input id="upload" type="file" accept=".pdf,.png,.jpg" multiple class="sr-only" /> <!-- Ícone --> <div class="w-10 h-10 bg-white border border-zinc-200 flex items-center justify-center group-hover:border-zinc-400 transition-colors"> <!-- SVG upload 20×20 --> </div> <!-- Texto --> <div> <p class="text-sm font-medium text-zinc-900"> Arraste arquivos aqui </p> <p class="text-xs text-zinc-500 mt-0.5"> ou <span class="text-zinc-900 font-medium underline underline-offset-2"> clique para selecionar </span> </p> </div> <p class="mono text-[10px] text-zinc-400"> PDF, PNG, JPG · máx. 10 MB </p> </label> <!-- Arquivo selecionado --> <div class="border border-zinc-200 bg-white p-3 flex items-center gap-3"> <!-- ícone de tipo --> <div class="flex-1 min-w-0"> <p class="text-sm font-medium text-zinc-900 truncate"> nome-do-arquivo.pdf </p> <p class="text-xs text-zinc-500">2,4 MB</p> </div> <!-- Botão remover --> <button type="button" aria-label="Remover arquivo" class="p-1 text-zinc-400 hover:text-red-600 hover:bg-red-50 transition-colors"> <!-- SVG X 16×16 --> </button> </div>
Toast / Snackbar
Notificação transiente. Posicione via fixed bottom-4 right-4 na produção. Use role="alert" para urgentes, role="status" para informativos.
Salvo com sucesso
Alterações aplicadas.
Erro ao enviar
Verifique sua conexão.
Item excluído.
<!-- Toast escuro (padrão) --> <div role="alert" class="flex items-start gap-3 px-4 py-3 bg-zinc-900 text-white shadow-lg fixed bottom-4 right-4 max-w-sm w-full z-50"> <!-- SVG ícone --> <div class="flex-1 min-w-0"> <p class="text-sm font-medium">Título</p> <p class="text-xs text-zinc-400 mt-0.5">Detalhe.</p> </div> <button aria-label="Fechar" class="text-zinc-400 hover:text-white transition-colors"> <!-- SVG X 16×16 --> </button> </div> <!-- Toast claro (variante erro) --> <div class="... bg-white border border-red-200"></div> <!-- Com ação inline --> <button class="text-xs font-semibold text-zinc-300 hover:text-white underline underline-offset-2"> Desfazer </button> <!-- Posição: fixed bottom-4 right-4 z-50 Stack múltiplos: flex flex-col gap-2 -->
Combobox / Select Custom
Versão visual enriquecida do Select. Estrutura estática — conecte aria-expanded e toggle via JS da sua stack.
Preview aberto
- 🇧🇷 Brasil
- 🇦🇷 Argentina
- 🇵🇹 Portugal
- 🇺🇸 Estados Unidos
Com avatar
<!-- Trigger --> <button type="button" aria-haspopup="listbox" aria-expanded="false" class="w-full flex items-center justify-between px-3 py-2 bg-white border border-zinc-300 hover:border-zinc-400 text-sm focus:outline-none focus:ring-2 focus:ring-zinc-900 transition-colors"> <span class="flex items-center gap-2"> <!-- ícone/avatar opcional --> Opção selecionada </span> <!-- SVG chevron --> </button> <!-- Dropdown --> <ul role="listbox" class="absolute top-full left-0 right-0 mt-1 bg-white border border-zinc-200 shadow-lg z-10 py-1 max-h-48 overflow-y-auto"> <!-- Selecionado --> <li role="option" aria-selected="true" class="flex items-center gap-2.5 px-3 py-2 text-sm text-zinc-900 bg-zinc-100 cursor-pointer"> Opção A <!-- SVG check ml-auto --> </li> <!-- Normal: text-zinc-700 hover:bg-zinc-100 --> </ul>
Rating
Avaliação por estrelas. Versão interativa via radio + peer CSS-only — sem JS.
Exibição (read-only)
Tamanhos
<!-- Exibição read-only --> <div class="flex gap-1" aria-label="Avaliação: 4 de 5 estrelas"> <!-- Estrela preenchida --> <svg class="w-5 h-5 text-yellow-400" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true"> <path d="M9.049 2.927..."/> </svg> <!-- Estrela vazia: text-zinc-200 --> </div> <!-- Tamanhos: sm → w-3.5 h-3.5 gap-0.5 md → w-5 h-5 gap-1 lg → w-6 h-6 gap-1 -->
Command Palette
Paleta de comandos tipo ⌘K. Estrutura estática: search + grupos + itens com atalhos. Conecte abertura/busca via JS.
Recentes
Navegação
<div class="border border-zinc-200 bg-white shadow-xl overflow-hidden fixed top-24 left-1/2 -translate-x-1/2 w-full max-w-md z-50" role="dialog" aria-modal="true" aria-label="Paleta de comandos"> <!-- Search --> <div class="flex items-center border-b border-zinc-200 px-4"> <!-- SVG search --> <input type="search" class="flex-1 px-3 py-3.5 text-sm bg-white focus:outline-none" /> <kbd class="mono text-[10px] border border-zinc-200 bg-zinc-100 text-zinc-400 px-1.5 py-0.5">Esc</kbd> </div> <!-- Lista: max-h-72 overflow-y-auto py-2 --> <!-- Grupo: p mono text-[10px] uppercase --> <!-- Item ativo: bg-zinc-100 --> <button class="w-full flex items-center gap-3 px-4 py-2.5 text-sm text-zinc-700 hover:bg-zinc-100 transition-colors"> <!-- Ícone 24×24 bg-zinc-100 --> <span class="flex-1 text-left">Label</span> <kbd class="mono text-[10px] border border-zinc-200 bg-white text-zinc-400 px-1.5 py-0.5">⌘K</kbd> </button> <!-- Footer hints --> <div class="border-t border-zinc-100 px-4 py-2 flex gap-3 mono text-[10px] text-zinc-400"></div> </div>
Inline Editable
Campo editável in-place. Texto vira input ao clicar. Use focus-within para controlar exibição dos controles.
Leitura (hover revela edição)
Estado de edição
Ghost input (borda no hover/focus)
Borda surge no hover/focus.
<!-- Texto + botão lápis (hover reveal) --> <div class="group flex items-center gap-2"> <span class="text-sm font-semibold text-zinc-900"> Texto editável </span> <button aria-label="Editar" class="opacity-0 group-hover:opacity-100 focus:opacity-100 p-1 text-zinc-400 hover:text-zinc-700 transition-all"> <!-- SVG pencil 14×14 --> </button> </div> <!-- Estado de edição --> <div class="flex items-center gap-2"> <input type="text" class="flex-1 px-2 py-1 text-sm font-semibold border border-zinc-900 focus:outline-none focus:ring-2 focus:ring-zinc-900 focus:border-transparent" /> <!-- btn confirmar: bg-zinc-900 --> <!-- btn cancelar: hover:bg-zinc-100 --> </div> <!-- Ghost input --> <div class="border border-transparent hover:border-zinc-300 focus-within:border-zinc-900 focus-within:ring-2 focus-within:ring-zinc-900 px-2 py-1 transition-all"> <input type="text" class="w-full text-sm bg-transparent focus:outline-none" /> </div>
Timeline
Sequência cronológica de eventos. Linha vertical + dot + conteúdo. Variantes com ícone e estado.
Deploy concluído
SucessoVersão 2.4.1 publicada em produção sem erros.
hoje, 14:32
Code review aprovado
PR #142 aprovado por Carlos Silva.
hoje, 11:15
Em revisão
PendenteAguardando aprovação de QA.
ontem, 16:00
Branch criada
feature/payment-refactor criada por Ana Barros.
25 mar 2026
<!-- Wrapper com linha vertical --> <div class="relative pl-6"> <div class="absolute left-[7px] top-2 bottom-2 w-px bg-zinc-200"></div> <div class="space-y-6"> <div class="relative flex gap-4"> <!-- Concluído: bg-zinc-900 + check --> <div class="absolute -left-6 top-1 w-3.5 h-3.5 bg-zinc-900 flex items-center justify-center"> <!-- SVG check 8×8 text-white --> </div> <!-- Atual (ativo): -left-[23px] bg-white border-2 border-zinc-900 ring-2 ring-offset-2 --> <!-- Futuro: bg-zinc-200 (sem ícone) --> <div class="flex-1 min-w-0"> <p class="text-sm font-semibold text-zinc-900">Evento</p> <p class="text-xs text-zinc-500 leading-relaxed">Desc.</p> <p class="mono text-[10px] text-zinc-400 mt-1">hoje</p> </div> </div> </div> </div>