Frete Ásia → Santos
US$ por TEU · últimos 12 meses vs. ano anterior
Base única para apps no Lovable, extensões de Chrome, front-ends e blogs. Neutros levemente frios, índigo como cor de marca, um fio de luz como assinatura e brilho que só aparece quando você interage.
shadcn-globals.css + tailwind.config.jsClasses da assinatura: lit, btn-glow, card-glow, nav-active, input-glow. Movimento: motion.ts.
tokens.cssVariáveis --color-*, --space-*, --radius-* e classes .ds-lit, .ds-btn-primary, .ds-card-interactive.
llms.txt + tokens.jsonA IA consulta as páginas pelo llms.txt. O JSON alimenta scripts e Figma (Tokens Studio).
// Regra: componentes usam só tokens semânticos. Nunca hex direto. // Lovable / React + shadcn <html class="dark"> <Card className="lit"> {/* linha de luz: 1 por tela */} <Button className="btn-glow">Criar monitor</Button> </Card> <!-- CSS puro (tokens.css) --> <div class="ds-lit ds-card-interactive"> <button class="ds-btn-primary">Criar monitor</button> </div>
Como ler esta página: Fundamentos definem os tokens; Componentes mostram variantes, estados e regras de uso, cada um com uma nota "Movimento"; Cards e Páginas mostram como compor telas. Clique em cores e escalas para copiar o hex.
Profundidade vem de camadas de superfície e bordas de 1px, sem sombra. Componentes usam só estes tokens; clique em uma cor para copiar o hex do tema atual.
--color-bgPágina inteira e área atrás de cards. Nunca dentro de um card.
--color-surfaceCards, menu lateral, modal, menus suspensos.
--color-surface-raisedDentro da superfície: hover de linha, item ativo, botão secundário, badge neutro.
--color-surface-sunkenCampos, blocos de código, cabeçalho de tabela, rodapé de modal.
--color-border) separa áreas; borda forte contorna controles (campo, botão secundário, menu).Primitivos gerados em OKLCH. Componentes não usam a escala direto: ela serve para criar tokens semânticos, gráficos e ilustrações. Índigo 500 (contornado) é a cor de marca.
| Token | Escuro | Claro |
|---|---|---|
| Fundo · superfície · elevada | neutro 950 · 900 · 800 | neutro 50 · branco · 100 |
| Borda · borda forte | neutro 800 · 700 | neutro 200 · 300 |
| Texto · secundário · apagado | neutro 100 · 300 · 400 | neutro 900 · 700 · 600 |
| Primário · hover | índigo 500 · 600 | índigo 500 · 600 |
| Texto índigo · foco | índigo 300 · 400 | índigo 600 · 500 |
| Status (texto e ícone) | 400 | 700 |
| Destrutivo sólido | vermelho 600 | vermelho 600 |
Regra para criar um token novo: no escuro use passos claros (300–400) para texto; no claro, passos escuros (600–700). Confira o contraste antes de usar.
Razões WCAG sobre o fundo de cada tema. Texto pede 4,5:1 (AA); anel de foco e ícones que transmitem informação pedem 3:1.
| Par | Escuro | Claro | Nível |
|---|---|---|---|
| Texto principal / fundo | 16,8 : 1 | 17,3 : 1 | AAA |
| Texto secundário / fundo | 11,3 : 1 | 11,3 : 1 | AAA |
| Texto apagado / fundo | 7,2 : 1 | 7,5 : 1 | AAA |
| Texto índigo, links / fundo | 9,8 : 1 | 6,5 : 1 | AA |
| Status / fundo | 7,0–7,8 : 1 | 6,8–7,7 : 1 | AA |
| Branco / botão índigo | 5,1 : 1 | 5,1 : 1 | AA |
| Branco / destrutivo sólido | 5,7 : 1 | 5,7 : 1 | AA |
| Anel de foco / fundo | 7,0 : 1 | 4,9 : 1 | 3:1 ok |
| Texto desativado / fundo | 2,5 : 1 | 2,6 : 1 | Isento |
Meça no pior caso: sobre a superfície elevada o texto apagado cai para 5,9:1 (escuro) e o texto índigo para 5,9:1 (claro), ainda AA. Texto desativado é isento pela WCAG, por isso o motivo do bloqueio vai em texto normal ao lado.
Parada, a tela é calma: só um fio de luz no topo do herói e de um card de destaque. O brilho aparece como resposta, ao passar o mouse, focar ou marcar o item ativo.
No máximo um por tela, além do herói.
Passe o mouse: borda índigo e halo suave.
| Elemento | React + shadcn | CSS puro |
|---|---|---|
| Linha de luz | lit | .ds-lit |
| Brilho do primário | btn-glow | .ds-btn-primary |
| Card interativo | card-glow | .ds-card-interactive |
| Foco de campo | input-glow | .ds-input |
| Item ativo do menu | nav-active | .ds-nav-active |
| Marca | brand-mark | .ds-mark |
Geist para interface e títulos, Geist Mono para números, código e rótulos técnicos. Interface em 14px, leitura longa em 16px.
Geist · 400, 500, 600, 700
Geist Mono · 400, 500 · números tabulares
font-variant-numeric: tabular-nums, alinhados à direita em tabelas.Todo espaço é múltiplo de 4px. Quanto mais relacionados dois elementos, menor o espaço entre eles. Profundidade vem de borda e superfície; sombra só no que flutua.
4–8 dentro do componente (ícone e texto) · 12–16 entre campos e padding de card · 24–32 entre grupos · 48–64 entre seções.
Elemento dentro de outro usa raio menor que o do pai.
Camadas (--z-*): menu 50 · fixo 100 · overlay 200 · modal 300 · toast 400.
Traço de 1,75px, cantos arredondados, cor herdada do texto. No Lovable/React use lucide-react, que segue este estilo; não misture com outra biblioteca.
Os nomes são do sprite desta página. No Lucide: okc = CircleCheck, xc = CircleX, warn = TriangleAlert, gear = Settings, more = Ellipsis, tup/tdown = TrendingUp/TrendingDown, down/up = Download/Upload, ext = ExternalLink, out = LogOut, msg = MessageSquare, cal = Calendar, spark = Sparkle.
strokeWidth 1,75 em todos os tamanhos (medido no viewBox de 24).aria-hidden. Ícone sozinho em botão leva aria-label e tooltip.import { Bell } from "lucide-react"; // padrão: 16px, traço 1,75 <Bell size={16} strokeWidth={1.75} aria-hidden />
Movimento é resposta, nunca enfeite: se a animação não ajuda a entender o que mudou, ela sai. Cada componente desta página traz uma nota "Movimento" com o comportamento e os tokens que usa.
| Token | Valor | Uso |
|---|---|---|
--duration-fast | 120ms | cor e fundo no hover, clique, sair, tooltip, menu |
--duration-base | 200ms | brilho e elevação no hover, foco, abrir, abas, toast |
--duration-slow | 320ms | painéis, gaveta, reorganizar lista, switch |
--stagger | 40ms | entre itens de lista; do 7º em diante entram juntos |
--ease-out | .2, 0, 0, 1 | entrar e reposicionar (lista, indicador) |
--ease-in | .4, 0, 1, 1 | sair |
--ease-in-out | .4, 0, .2, 1 | atravessar a tela inteira (varredura) |
--ease-spring | .34, 1.4, .64, 1 | só peças pequenas que confirmam clique: switch, check, radio, ícone, contador |
| Mola (JS) | k 380 · c 30 | o que o dedo arrasta: gaveta, cards; layout no React |
No CSS desta página os mesmos valores se chamam --d-fast, --d-base, --d-slow e --ease-io. Ao copiar CSS daqui, troque pelos nomes de tokens.css.
transform e opacity. Exceções documentadas: altura do acordeão, do alerta ao fechar e do grupo do menu; largura do menu ao recolher.prefers-reduced-motion ativo, deslocamento, escala, mola, varredura e contagem viram troca instantânea.| Projeto | Use | Por quê |
|---|---|---|
| Lovable / React | motion (import de motion/react) | Entrada e saída (AnimatePresence), layout, mola. Sucessor do Framer Motion. |
| Extensão de Chrome, blog, HTML | CSS nativo + View Transitions | 0 KB. @starting-style, popover, animation-timeline. |
| Landing com narrativa de rolagem | GSAP + ScrollTrigger | Só se a página for "contada" pela rolagem. Gratuito. Fora disso, CSS basta. |
| App mobile (React Native) | Reanimated + Moti | Anima na thread nativa, não trava. |
--duration-fast: 120ms; --duration-base: 200ms; --duration-slow: 320ms; --stagger: 40ms; --ease-out: cubic-bezier(.2, 0, 0, 1); --ease-in: cubic-bezier(.4, 0, 1, 1); --ease-in-out: cubic-bezier(.4, 0, .2, 1); --ease-spring: cubic-bezier(.34, 1.4, .64, 1); @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: 0ms !important; animation-duration: 0ms !important; } }
import { motion, AnimatePresence, MotionConfig } from "motion/react"; // presets prontos em motion.ts (modal, menu, toast, list, item…) import { modal, spring } from "@/lib/motion"; // "user" respeita o reduzir movimento do sistema <MotionConfig reducedMotion="user"> <AnimatePresence> {open && <motion.div {...modal} />} </AnimatePresence> <motion.li layout transition={spring} /> </MotionConfig>
Seis técnicas que ajudam a acompanhar o que mudou. Use cada uma só no caso descrito na tabela abaixo das demos. As que dependem do navegador mostram se ele tem suporte nativo ou se está usando a reserva.
Clique num produto: a imagem e o título viajam até a tela de detalhe. Volte para ver o caminho inverso.
Arraste a alça para baixo e solte. Funciona com mouse e dedo.
Filtre e ordene: quem fica desliza para o novo lugar, quem sai some primeiro.
Abre e fecha sem biblioteca: popover nativo + @starting-style. Fundo com vidro fosco.
Role o texto: a barra acompanha e o cabeçalho ganha vidro fosco.
A ação acontece na hora; o servidor confirma depois. Arquive um alerta e use "Desfazer", ou favorite um item.
| Técnica | Use quando | Evite quando | Custo e suporte |
|---|---|---|---|
| View Transitions | Card abre o detalhe e o usuário precisa saber de onde veio. | Muitos elementos com nome na mesma tela; troca de aba simples. | 0 KB. Mesma página: navegadores atuais. Entre páginas: ainda sem Firefox. Reserva: troca direta. |
| Mola | O dedo arrasta: gaveta no celular, card que se descarta. | Modal e menu no desktop; use a curva com duração fixa. | JS a cada quadro. No React, já vem no motion. Funciona em todo navegador. |
| Layout / FLIP | Filtrar ou ordenar uma lista curta em que o usuário segue um item. | Mais de ~50 linhas, tabela virtualizada ou dados que mudam sozinhos. | Mede a posição antes e depois. No React, layout do motion; sem framework, ~30 linhas. |
Popover + @starting-style | Paleta, menu e popover em extensão ou HTML puro. | Diálogo que precisa prender o foco: use <dialog>. No React, use o componente da biblioteca. | 0 KB. Navegadores atuais; no Firefox a saída é instantânea. Reserva: abre sem animar. |
| Scroll-driven | Progresso de leitura e cabeçalho que muda ao rolar. | Parallax, rolagem sequestrada, texto que só aparece ao rolar. | 0 KB. Chrome, Edge e Safari 26; Firefox ainda não. Reserva: ouvinte de rolagem passivo. |
| Interface otimista | Ação reversível que quase nunca falha: arquivar, favoritar, marcar como lida. | Pagamento, exclusão definitiva, envio de e-mail. | Precisa desfazer a mudança e avisar se o servidor falhar. React: useOptimistic ou onMutate do TanStack Query. |
Um botão primário por tela. A hierarquia diz qual ação importa; o texto diz exatamente o que vai acontecer.
scale(.97)). Carregando troca o texto por spinner e depois por check, sem mudar a largura. Alternar dá um pulo no ícone. Desativado e destrutivo não brilham.A ação principal. Um por tela ou por modal.
Ações de apoio ao lado do primário.
Ações neutras em áreas cheias de cards.
Barras de ferramentas, cancelar, ações terciárias.
Dentro de texto ou para navegar. Se leva a outra página, use <a>.
Em listas, cards e configurações. Abre a confirmação ou permite Desfazer.
Aparece apenas no modal que confirma a exclusão. Branco sobre #B1403E: 5,7:1.
No celular, todo alvo de toque tem no mínimo 44px de altura, mesmo que o botão pareça menor.
| Normal | Hover | Foco (teclado) | Pressionado | Carregando | Desativado | |
|---|---|---|---|---|---|---|
| Primário | ||||||
| Secundário | ||||||
| Fantasma | — | |||||
| Destrutivo |
Foco usa anel de 2px com folga de 2px, sempre visível no teclado e nunca no clique do mouse (:focus-visible). Carregando mantém a largura e bloqueia novos cliques.
Ícone à esquerda para ação; seta à direita para avançar.
Sempre com tooltip e aria-label. Passe o mouse.
Ação mais comum à esquerda; alternativas no menu.
Liga/desliga com aria-pressed. Clique em Favoritar.
Contador para pendências; atalho só em ações frequentes.
Clique em Salvar para ver carregando → sucesso.
<button> executa ação; <a> leva a outra página, mesmo que pareça botão.Badge mostra um estado ou atributo e não é clicável. Status sempre com texto; a cor só reforça. Índigo marca novidade e destaque, nunca estado.
Ativo, pago, concluído.
Pede ação em breve, sem bloquear nada.
Falhou ou está bloqueado. O motivo aparece no detalhe.
Em andamento ou aguardando o sistema.
Inativo, arquivado, rascunho. Sem ponto.
Novidade, recurso de IA, plano. Sólido só para o plano pago, no máximo um por tela.
Versão, ID, código. Sempre em Geist Mono.
Só para dado que atualiza sozinho agora. Um por tela.
Pendências não vistas. Acima de 99 mostra "99+"; com zero, some.
Clicável, liga e desliga. Fica em Seleção, acima de listas.
Valor escolhido. Só o X é botão, com aria-label.
Rótulo sempre visível acima, ajuda abaixo. Placeholder só dá exemplo e nunca substitui o rótulo. O erro diz como corrigir.
Marque o opcional, não o obrigatório. Sem asterisco.
Desativado sempre com o motivo ao lado. Somente leitura é para dado que a pessoa vê mas não edita aqui; desativado é para algo que ela poderá editar depois.
Ícone à esquerda. Atalho só no desktop.
Parte fixa fica fora do valor: domínio, moeda, unidade.
Botão de mostrar com aria-pressed. Não bloqueie colar.
Contador só quando há limite.
Colar preenche tudo; o foco avança sozinho.
aria-invalid e aria-describedby. Ao enviar com erro, o foco vai para o primeiro campo errado.type e inputmode certos abrem o teclado certo.Escolha o controle pelo número de opções e pelo momento do efeito. Switch aplica na hora; checkbox e radio esperam o Salvar.
Liga ou desliga com efeito imediato. Sem botão Salvar.
Várias opções independentes, ou um aceite. Vale ao salvar.
Uma entre 2 e 5 opções, todas à vista. Sempre com uma marcada.
Uma entre 6 ou mais, ou quando falta espaço. Acima de 15, select com busca. Até 4 opções que mudam a tela na hora: segmentado (em Abas).
Valor aproximado numa faixa. Mostre o número; para valor exato, use campo.
Filtros que se somam, acima de listas e tabelas. Aplicam na hora.
| Desmarcado | Marcado | Misto | Foco | Erro | Desativado | |
|---|---|---|---|---|---|---|
| Checkbox | ||||||
| Radio | — | |||||
| Switch | — | — |
Misto aparece no "selecionar todos" quando só parte da lista está marcada. Erro de grupo (nenhuma opção escolhida) mostra a mensagem abaixo do grupo, não em cada item. Contorno desmarcado em --muted para ter 3:1 contra o fundo.
fieldset + legend; switch usa role="switch".Abas trocam a visão dentro da mesma página, sem navegar. Segmentado troca o formato do mesmo conteúdo. Breadcrumb e paginação dizem onde a pessoa está.
translate + scaleX, nunca left/width). O painel novo entra com fade e 4px. No segmentado, o fundo da opção desliza.Seções do mesmo objeto, uma de cada vez. De 2 a 6 abas; com mais, use navegação lateral. A aba vai para a URL (?aba=historico) para o link e o voltar funcionarem. No celular, a barra rola na horizontal e nunca quebra linha.
De 2 a 4 opções curtas que mudam o formato ou o período na hora, sem painel novo. Com 5 ou mais, use select.
Breadcrumb a partir de 3 níveis; o último item é a página atual, sem link. No celular, mostre só o nível anterior. Paginação em tabelas com total conhecido: primeira, última e vizinhas. Em feeds, prefira "Carregar mais".
Esconde respostas e detalhes secundários para a página caber numa olhada. Se a pessoa precisa ler tudo, não esconda.
motion com height: "auto".Feito com <details> e <summary>: teclado (Enter e Espaço) e leitor de tela funcionam sem JS. A linha toda é o alvo, com pelo menos 48px. Vários podem ficar abertos ao mesmo tempo.
Perguntas frequentes e opções avançadas que a maioria não abre. O título é a pergunta inteira.
Conteúdos do mesmo nível que a pessoa compara ou alterna. Ver Abas e navegação.
Um texto longo só. Mostre as primeiras linhas e um link para expandir.
Identifica quem fez ou quem participa. Redondo é pessoa, quadrado é empresa ou projeto. Sem foto, iniciais com uma cor fixa por nome.
Ordem de exibição: foto, depois iniciais, depois ícone de pessoa. A cor vem do nome (mesmo nome, mesma cor) e as 6 opções têm texto branco com contraste de 4,9:1 ou mais.
O ponto não basta sozinho: o status vai no aria-label e em texto onde houver espaço.
Até 3 rostos e um contador. Clicar abre a lista completa.
Com o nome ao lado, o avatar é decorativo (aria-hidden ou alt="").
Tooltip nomeia ou completa em poucas palavras e nunca guarda informação essencial. Menu reúne ações sobre um item; cada item começa com verbo.
Nome de botão só de ícone (repete o aria-label) ou o dado completo de algo resumido, como a data exata. Abre no hover e no foco do teclado; em produção, Esc fecha. Só texto, sem link nem botão dentro. No celular não há hover: o que importa fica visível.
Destrutivo por último, depois de uma divisória, em vermelho; ele abre a confirmação. Atalho à direita. Teclado: setas movem, Enter escolhe, Esc fecha e devolve o foco ao botão. No celular, menu com mais de 5 itens vira folha inferior.
Rótulo curto no hover ou foco. Só texto.
Abre no clique e pode ter link, botão ou formulário curto. Fecha com Esc ou clique fora.
Lista de ações sobre um item: "Mais opções", botão dividido.
Escolher um valor de uma lista. Ver Seleção.
Mostra onde a pessoa está num fluxo linear de 3 a 5 passos. Se as partes podem ser visitadas em qualquer ordem, use abas.
scaleX) e o check aparece com impulso. Voltar desfaz na hora. Com movimento reduzido, tudo troca sem animação.Clicável para voltar e revisar. Os dados continuam preenchidos.
Anel índigo. No HTML, aria-current="step".
Apagado e não clicável. Avançar valida só o passo atual.
Passo já visitado que ficou inválido. A descrição diz o que corrigir.
<ol>: a ordem faz parte do significado.Escolha pelo tempo de espera e pelo que se sabe do progresso. Sempre diga o que está carregando.
| Espera | Use |
|---|---|
| Até 300ms | Nada. Mostrar loader nesse tempo só causa uma piscada. |
| 300ms a 3s | Spinner no lugar da ação (botão, linha) ou esqueleto no lugar do conteúdo. |
| Mais de 3s, progresso conhecido | Barra determinada com número: "312 de 480" ou porcentagem. |
| Mais de 3s, sem previsão | Barra indeterminada e um texto do que está acontecendo. Acima de 10s, ofereça Cancelar ou deixe seguir em segundo plano com aviso no fim. |
Brilho só na barra em andamento. Cor por faixa: índigo até 79%, âmbar de 80% a 99%, vermelho ao estourar o limite. Verde só quando um processo termina.
Espera curta num ponto só. Dentro de botão, segue as regras de Botões. Sozinho, leva role="status" e rótulo.
Primeira carga de conteúdo com forma conhecida. Copie o layout real para nada pular quando os dados chegarem.
Mostra proporção em cards de métrica (meta, uso). Não serve para indicar carregamento.
Escolha pelo alcance e pela urgência. Banner fala do produto todo, alerta fala de uma área, toast confirma o que a pessoa acabou de fazer.
Vale para o produto inteiro: novidade, manutenção, pagamento pendente. Fica no topo, um por vez, até a pessoa dispensar ou o problema acabar.
Situação de uma página ou área. Fica perto do que afeta e só sai quando resolvido ou dispensado.
Resultado de uma ação da pessoa. Some sozinho; nada importante pode depender dele.
Decisão obrigatória antes de seguir. É o mais caro: use pouco. Veja Modal.
Erro não tem fechar: fica até ser resolvido e traz o botão que resolve. Os outros podem ser dispensados. Alerta que aparece depois de uma ação usa role="alert" (erro) ou role="status" (demais).
aria-live="polite"; toast de erro usa role="alert".Modal trava a tela. Use só quando a pessoa precisa decidir ou preencher algo curto antes de seguir. Para o resto, prefira Desfazer, painel lateral ou uma página.
@starting-style + allow-discrete). Cresce de 96% com fade e o fundo escurece junto; fecha em 120ms. No celular, vira gaveta que sobe de baixo.Ação destrutiva ou difícil de desfazer. O título pergunta e nomeia o objeto, o corpo diz a consequência, o botão repete o verbo.
Criar ou editar algo com até 4 campos. Com mais campos ou passos, use painel lateral ou página.
Vira gaveta de baixo com botões empilhados em largura total, primário em cima. Veja a gaveta em Técnicas modernas.
Os 128 produtos e todo o histórico de preços serão apagados. Não dá para desfazer.
Pedir para digitar só em perda grande e irreversível (projeto, conta). O botão fica desativado até o texto bater. Nesse caso o foco inicial vai para Cancelar, nunca para o botão destrutivo.
<dialog> com showModal(): o Tab fica preso dentro e o resto da página fica inerte.autofocus). Ao fechar, o foco volta ao botão que abriu.Para trechos que a pessoa vai copiar: comandos, configurações, tokens. Dentro de uma frase, use <code> inline.
<Button className="btn-glow"> <Plus className="h-4 w-4" /> Novo projeto </Button> /* hover: halo índigo */ box-shadow: 0 0 0 1px rgb(99 87 240 / .6), 0 6px 22px rgb(99 87 240 / .35);
npm install lucide-reactO $ vem do CSS (::before) e fica fora da cópia. Cabeçalho diz a linguagem ou o nome do arquivo. Linhas longas rolam na horizontal e nunca quebram no meio. Cores de sintaxe usam só os tokens de texto: índigo, verde, âmbar e apagado.
Para comparar muitos itens pelos mesmos campos. Números em mono e alinhados à direita; texto à esquerda.
| Loja | Status | Ações | ||||
|---|---|---|---|---|---|---|
| Monitor 27" 4K | Loja A | R$ 1.899,00 | −12,0% | Abaixo da meta | ||
| Teclado mecânico | Loja B | R$ 459,90 | 0,0% | Monitorando | ||
| SSD NVMe 2TB | Loja A | R$ 799,00 | +6,5% | Subiu | ||
| Cadeira ergonômica | Loja C | R$ 1.249,00 | — | Link quebrado |
Digite "fone" no filtro para ver a tabela sem resultado: cabeçalho e busca continuam no lugar. Em preço, queda é boa notícia: verde para queda, vermelho para alta, sempre com o sinal.
<button> dentro do <th>, com aria-sort. Uma coluna ordena por vez; o primeiro clique ordena do menor para o maior.aria-label que nomeia o item. Tabela vazia de verdade usa o estado vazio de primeiro uso.Todo lugar que pode ficar vazio precisa de um. Diga por que está vazio e qual é o próximo passo, com um botão só.
Cole o link de um produto para começar a monitorar o preço.
Nenhum resultado para "teclado sem fio". Tente outro termo ou limpe os filtros.
A conexão caiu durante a busca. Seus dados estão salvos.
Primeiro uso convida: ícone índigo e botão primário. Sem resultado repete o termo buscado e oferece limpar. Erro diz o que houve, tranquiliza sobre os dados e oferece tentar de novo; nunca mostre código técnico.
Escolha o tipo pela pergunta que o gráfico responde, use a paleta de dados na ordem fixa e deixe o número exato a um passar de mouse.
Séries diferentes, sempre nesta ordem. Máx. 6; o resto vira "Outros" em cinza.
Intensidade de um valor: mapa de calor, mapa. Mais claro = mais.
Desvio em torno de um centro: variação %, meta vs. real.
Só quando a série É um status (no prazo, atrasado, crítico). Nunca como cor de categoria.
Todas as cores têm 3:1 ou mais sobre a superfície nos dois temas. A série principal é sempre a índigo (--chart-1); comparações e períodos anteriores ficam em cinza ou tracejado.
2 a 6 séries. Fica acima do gráfico, na ordem das cores. Clique liga/desliga a série; a última não pode ser desligada.
Até 3 linhas: o nome vai na ponta da linha, na cor dela. Dispensa a legenda e o olho não vai e volta.
Rosca e composição: a legenda vira a tabela de valores ao lado do gráfico.
Mapa de calor e mapas: mostra o que cada tom significa, com o intervalo real ("0–30 navios").
Linhas de média, limite e alvo entram na legenda com o mesmo traço usado no gráfico.
Uma série só não leva legenda: o título e o subtítulo já dizem o que é.
| Pergunta | Use | Evite |
|---|---|---|
| Como mudou ao longo do tempo? | Linha · área (volume) | Barras com mais de ~20 períodos |
| Qual é maior? Qual o ranking? | Barras horizontais ordenadas | Pizza, radar |
| Como se compara com o período anterior? | Barras agrupadas · linha com tracejado | Duas pizzas lado a lado |
| Do que é feito o total? | Rosca (até 5 partes) · barra empilhada 100% | Pizza com 6+ fatias |
| Uma coisa influencia a outra? | Dispersão | Duas linhas com eixos diferentes |
| Volume e taxa juntos? | Combinado (barras + linha) | Dois gráficos separados sem eixo comum |
| Quando acontece mais? | Mapa de calor (dia × hora) | Linha com 168 pontos |
| Onde as pessoas desistem? | Funil | Rosca |
| Estamos perto da meta? | Bullet (barra com alvo) | Velocímetro |
Os gráficos que cobrem quase todo painel. Passe o mouse para ver o tooltip; clique na legenda para ligar e desligar séries.
US$ por TEU · últimos 12 meses vs. ano anterior
Mil toneladas por mês · últimos 12 meses
Alertas disparados · outubro
Mil embarques · 2024 vs. 2025
Top 6 · US$ bilhões · 2025
% do total · outubro
% das toneladas · 2025
Barras: mil embarques · linha: % atrasados · 12 meses
Dias × US$ mil · por canal de parametrização
Navios atracados · faixas de 2h · últimos 90 dias
Pessoas por etapa · outubro
Valor atual, faixas ruim/ok/bom e alvo
Todo gráfico precisa de três estados além do normal, e de uma biblioteca que respeite os tokens de cor.
Nenhum alerta entre 1 e 13 de outubro.
A fonte de dados não respondeu. O resto do painel continua funcionando.
role="img" e um aria-label com a conclusão; para dados críticos, ofereça "Ver como tabela".| Projeto | Use | Por quê |
|---|---|---|
| Lovable / React + shadcn | shadcn/ui chart (Recharts v3) | Padrão de mercado para dashboards; cores via var(--chart-1…6), tema claro/escuro automático. Bom até ~5 mil pontos. |
| Muitos dados, tempo real, mapas | Apache ECharts | Renderiza em canvas; aguenta dezenas de milhares de pontos e tem Sankey, treemap, mapas. Aplique os tokens no tema. |
| Extensão de Chrome, HTML puro | SVG próprio ou uPlot | Sparkline e barra simples em SVG (como nesta página); uPlot para séries temporais grandes com poucos KB. |
| App mobile | Victory Native ou ECharts | Mesmos tokens; tooltip por toque. |
:root { /* claro */ --chart-1: #5246cd; --chart-2: #098585; --chart-3: #be7204; --chart-4: #c4334f; --chart-5: #2382ba; --chart-6: #61911c; } .dark { /* escuro */ --chart-1: #8d92f9; --chart-2: #49c7c0; --chart-3: #eeb154; --chart-4: #f2798f; --chart-5: #7ac8f5; --chart-6: #afd46a; }
const config = { atual: { label: "2025", color: "var(--chart-1)" }, anterior: { label: "2024", color: "var(--chart-other)" }, } satisfies ChartConfig; <ChartContainer config={config} className="h-56 w-full"> <LineChart data={data}> <CartesianGrid vertical={false} /> <XAxis dataKey="mes" tickLine={false} axisLine={false} /> <ChartTooltip content={<ChartTooltipContent />} /> <Line dataKey="anterior" stroke="var(--color-anterior)" strokeDasharray="5 4" dot={false} /> <Line dataKey="atual" stroke="var(--color-atual)" strokeWidth={2.25} dot={false} /> </LineChart> </ChartContainer>
Para painéis e dashboards. O número é o protagonista, em Geist Mono; a variação vem com seta e cor de status. As regras de anatomia abaixo valem para todas as seções de cards.
.card.pad (20px, gap 12) para card simples sem divisórias. .card-h/.card-b/.card-f quando há título com ação, lista ou rodapé. Card em linha (arquivo, opção, integração): 14/16px.<a> inteiro com .hov. Card com várias ações fica parado e cada ação é um botão. Sem .hov em card que não abre nada.No frete, a seta desce e a cor é verde porque cair é bom. No tempo de liberação, a seta sobe e a cor é vermelha.
Para blogs, catálogos, projetos e pessoas. Se o card leva a um lugar só, ele inteiro é o link e acende no hover. Se tem várias ações, ele fica parado e cada ação é um botão.
Tokens, tipografia e uma assinatura visual que funciona do Lovable à extensão de Chrome.
Acompanha cotações de frete marítimo e avisa quando a rota fica abaixo da meta.
Notificação no navegador em segundos quando o preço cruza a sua meta.
Ver como funcionaArquivo tem ação interna (baixar): card parado. Link leva a um lugar só: card inteiro clicável.
<a> do título cobre o card com ::after e o botão fica por cima (z-index).<a> é HTML inválido e o leitor de tela lê tudo como um link só.Cards que pedem uma decisão: plano, opção, integração ou próximo passo. Cada card tem uma ação clara; o plano recomendado leva a linha de luz.
Para testar e uso pessoal.
Para quem vende ou monitora muito.
Para times e empresas.
Um primário só, no plano recomendado. Os outros usam secundário e contorno. No celular, o recomendado vem primeiro.
O card inteiro é o <label> do rádio: clique e setas do teclado funcionam sem JS.
Já conectada: switch liga e desliga. Ainda não conectada: botão Conectar.
Para feeds curtos dentro de um painel. As linhas vão de borda a borda, sem .card-b; título à esquerda e ação em texto à direita no cabeçalho. Mostre até 5 itens e leve o resto para "Ver todas".
Linha que abre algo é um <a> e acende no hover (Notificações). Linha que só informa não reage ao mouse (Equipe). Não lidas: texto em --text e ponto índigo; lidas: texto em --text-2.
Status de serviço, configuração e perigo, mais os estados que todo card de dados precisa ter: carregando, erro, vazio e bloqueado. Cada estado ocupa o mesmo tamanho do card pronto, para a tela não pular.
Excluir o projeto apaga os 128 produtos e todo o histórico. Não dá para desfazer.
O badge do cabeçalho mostra o pior status da lista. Zona de perigo fica no fim da página de configurações e abre a confirmação (veja Modal).
A coleta de preços não respondeu. Os outros cards continuam funcionando.
Erro fica dentro do card que falhou, nunca derruba a tela. Espaço vazio que adiciona algo é um <button> tracejado.
Duas colunas: formulário à esquerda, mensagem do produto à direita com a linha de luz. O formulário é a tela inteira; a coluna da marca é opcional e some no celular.
Duas colunas iguais. Na do formulário, marca no topo, formulário no meio e rodapé legal embaixo. Formulário com até 340px.
A coluna da marca some. O formulário ocupa a largura com margem de 16px, botões em btn-lg (44px).
Uma mensagem só, acima de Entrar: "E-mail ou senha incorretos." Use <form>, type="email" e autocomplete para Enter e gerenciador de senhas funcionarem.
Um passo por tela, stepper no topo, opções como cards selecionáveis. Voltar e Continuar ficam no mesmo lugar em todos os passos.
Dá para mudar depois em Configurações.
Coluna única centralizada de até 620px, sem menu lateral. Topo só com marca e Pular. Ações num rodapé com divisória: Voltar à esquerda, Continuar à direita.
Stepper vira texto "Passo 3 de 4" com barra de progresso. Cards empilham. Rodapé de ações fica preso no fim da tela, com Continuar em largura total.
No máximo 4 passos, cada um com uma pergunta. Ao avançar, o foco vai para o título do passo. Pular sempre visível; nada aqui deve ser obrigatório para usar o produto.
Menu lateral na variante app de Navegação lateral, barra superior com busca, cabeçalho da página com o único primário, KPIs (um com linha de luz), gráfico e lista.
Menu de 260px (64px recolhido) + conteúdo fluido. Barra superior de 56px. Corpo com 24px de margem: KPIs em 4 colunas, gráfico 1,6fr ao lado da lista 1fr. Acima de 1440px o conteúdo para de crescer e centraliza.
O menu vira gaveta, aberta por um botão na barra superior. KPIs em 2×2; gráfico e lista empilham. No cabeçalho fica só o primário; o filtro de período vai para um menu.
Um primário, no cabeçalho da página. Linha de luz só no KPI principal; KPIs não são clicáveis, então não têm hover. Perfil e plano ficam no rodapé do menu, como em Navegação lateral.
Herói com linha de luz, prova em números, recursos em cards e chamada final. A ação principal repete com o mesmo texto; só o herói e a chamada final a mostram como primário.
A Órbita monitora preços em qualquer loja e avisa no segundo em que cai abaixo da sua meta.
Sem cartão · 50 produtos grátisFunciona com as principais lojas do Brasil.
Escolha o preço que vale a compra.
No navegador, por e-mail ou WhatsApp.
Contêiner de até 1120px. Herói centralizado: título com até 13ch, texto com até 46ch. Blocos separados por 48–72px; números em faixa de 3 colunas, recursos em 3 cards.
Links do topo viram menu; ficam a marca e Entrar. Título de 54 para 36px. Botões do herói empilham em largura total. Números e recursos em 1 coluna.
Linha de luz só no herói e na chamada final. No topo, a mesma ação fica secundária para não competir com o herói. Tudo que leva a outra página é <a>, mesmo com cara de botão. Cards informativos não têm hover.
Abas no topo, cada grupo com título à esquerda e card à direita, zona de perigo no fim. Campos de texto salvam pelo rodapé do card; switch e segmentado salvam na hora.
Como você aparece para a equipe.
Aparência e e-mails. Salva na hora e avisa com um toast.
Ações que não dá para desfazer.
Apaga todos os projetos e dados.
Conteúdo de até 960px. Grade de 240px (título e explicação) + card. Dentro do app, ocupa a área de conteúdo do Dashboard com Configurações ativo no menu; aqui aparece sem o menu.
Abas rolam na horizontal. O título de cada grupo sobe para cima do card. Campos em 1 coluna; no rodapé, Salvar ocupa a largura e o status fica acima.
Rodapé do card: status à esquerda, Descartar e Salvar à direita, ativos só com alteração pendente. Excluir conta é destrutivo suave; o sólido aparece só no modal que confirma.
Coluna de leitura com cerca de 65 caracteres, corpo em 17px, sumário lateral fixo e código no mesmo estilo do sistema. O texto é o produto: nada de primário na página.
animation-timeline, demo em Técnicas modernas) e cabeçalho com vidro fosco ao rolar. O sumário destaca a seção atual. O texto não anima.Cada projeto novo começava do zero. Uma base fixa resolve isso e deixa o tempo para o problema que o produto resolve.
Num tema escuro, quase tudo na tela é cinza. Escolha um fundo, duas superfícies e duas bordas com um leve tom frio, e a interface já parece intencional antes de qualquer cor de marca.
--bg: #0e0e14; --surface: #16161d; --primary: #6357f0;
Se tudo brilha, nada se destaca.
Contêiner de 960px: artigo de até 640px (cerca de 65 caracteres em 17px) + sumário de 200px preso ao rolar. Corpo 17/1,7; título de seção 22px com respiro extra acima.
O sumário sai da lateral e vira "Nesta página" recolhível acima do texto. Título de 40 para 30px, margens de 16px. Código rola dentro do bloco, nunca a página.
Um h1 por artigo e níveis sem pular. Links no corpo sublinhados. Assinar é secundário; a única chamada forte, se houver, vai no fim do artigo.
360px de largura, cabeçalho compacto, ação principal visível sem rolar. Ao lado, o estado vazio do mesmo popup.
Abra a página de um produto em uma loja para monitorar o preço.
Ver lojas compatíveisLargura fixa de 360px (o Chrome aceita até 800×600). Cabeçalho de 48px; corpo com 14px de margem e 12px entre blocos. Tudo em uma coluna.
Produto atual, meta e Monitorar ficam sempre visíveis. Se a lista passar do limite de 600px, só ela rola. Itens que abrem a página do produto são <a>.
Produto encontrado, vazio (ao lado), carregando (esqueleto do card, não spinner) e sem acesso à página, com o botão que pede a permissão.
Diz o que aconteceu em uma frase, sem culpar a pessoa, e oferece o caminho de volta. Dentro do app, mantenha o menu lateral para ninguém ficar perdido.
O produto pode ter sido removido ou o link está incompleto.
Uma coluna centralizada na altura da tela, texto com até 42ch. No app, ocupa só a área de conteúdo, com menu e barra superior no lugar.
Número de 88 para 64px. Botões empilham em largura total (btn-lg), primário em cima.
Responda com status HTTP 404 de verdade, sem redirecionar. Mantenha a URL errada na barra. Ir para o início é o único primário; Buscar é secundário.
Ferramentas de IA não precisam de um prompt colado: elas leem as páginas do design system direto da web. Aponte a IA para o índice e ela busca só o que a tarefa pede. Os arquivos de tokens continuam sendo a fonte da verdade.
https://design.mypersonalhub.com.br/llms.txt lista as páginas da camada IA (fundamentos, movimento, tokens, componentes) com um resumo de cada uma.
https://design.mypersonalhub.com.br/llms-full.txt reúne todas as páginas em um só texto, para ferramentas que não navegam por links.
Para o código, use tokens.css, shadcn-globals.css, tailwind.config.js e motion.ts. As páginas explicam o porquê; os arquivos trazem os valores.
Na primeira mensagem ou no conhecimento do projeto (Knowledge), peça para seguir o design system em llms.txt. Depois peça para aplicar shadcn-globals.css e tailwind.config.js.
Adicione uma linha ao arquivo de regras (.cursor/rules ou CLAUDE.md) apontando para o llms.txt, ao lado dos arquivos de tokens.
Envie o link do llms.txt (ou do llms-full.txt) e peça para consultá-lo antes de montar a tela.
Siga o design system "Índigo + Linha de luz". Antes de montar qualquer tela, consulte https://design.mypersonalhub.com.br/llms.txt e leia as páginas relevantes (use llms-full.txt se não conseguir navegar pelos links). No código use SEMPRE os tokens/classes (bg-primary, var(--color-primary)…), nunca hex solto.