Um só acento
Halor Blue é a única cor de ação. Verde, âmbar e coral aparecem só para dizer o estado de algo.
O design system da PharmaLab reúne tokens, componentes e padrões para uma operação farmacêutica com muitos públicos: o representante no celular, a operação de olho no prazo, o gestor que aprova desconto e a diretoria que fecha o mês. Tudo nesta página é o código real do protótipo, com os dados da Nexa Saúde.
Halor Blue é a única cor de ação. Verde, âmbar e coral aparecem só para dizer o estado de algo.
Todo valor sai da plataforma e aparece por extenso: R$ 1.214.951, nunca “1,2 mi”. A IA escreve o texto, não o número.
A tela começa pelo que precisa de você agora e termina num botão. Análise vem depois, para quem quiser.
Modo essencial para o dia a dia, completo para quem configura. Glossário e atalhos para quem quer ir além.
A PharmaLab atende do representante que vende pelo celular ao financeiro que fecha a DRE. Quando houver dúvida no desenho de uma tela, estes oito princípios decidem. Cada cartão tem um exemplo para você testar.
Mostre primeiro o número que decide. O contexto vem no gráfico e o detalhe na ficha, sempre um clique depois.
Quem está começando vê só o que usa no dia. Colunas técnicas, regras e logs ficam no modo completo, a um clique.
Escreva como a equipe fala. “Rep ativo”, não “RA”. O botão diz o que acontece: verbo e objeto.
Toda fila, alerta ou insight termina numa ação de um clique. Tela vazia ensina o primeiro passo em vez de só dizer que não há nada.
Ações leves acontecem na hora e oferecem Desfazer por 5 segundos. Confirmação fica para o que não tem volta.
⌘K busca e pergunta, ? mostra os atalhos, G e P leva a Pedidos. Nenhum atalho dispara enquanto você digita.
Todo indicador com definição tem um ? ao lado. A mesma frase vale em todas as telas e no assistente de IA.
Foco visível, contraste AA, rótulo em todo botão de ícone, tabela com cabeçalho e movimento reduzido respeitado.
Seis públicos com pressa, contexto e vocabulário diferentes. A mesma tela precisa servir a todos, por isso o que aparece primeiro muda com o papel.
Quatro degraus de profundidade. Cada um responde uma pergunta e leva ao próximo sem trocar de contexto.
Quanto? Um número, a comparação e um ? com a definição.
Está melhor ou pior? Série no tempo e o período anterior tracejado.
Quais? Tabela com filtros, visões salvas e ação em lote.
Por quê? A ficha mostra a linha do tempo, quem mexeu e quando.
O símbolo é um P molecular: um anel hexagonal como bojo, a haste como ligação e um átomo no pé. Ele vive num ladrilho Halor Blue, lê bem a partir de 16 px e muda de tom para dizer em que ambiente você está.
Grade de 48 unidades. O ladrilho tem raio de 13,5 e o traço do glifo tem 4,4, com pontas e junções arredondadas, igual aos ícones.
Símbolo mais “PharmaLab” em Plus Jakarta Sans 800, com o ponto azul no fim. O ponto clareia no escuro e fica branco sobre o azul.
Deixe livre, em volta da assinatura, metade da altura do símbolo. Abaixo de 24 px use só o símbolo; o favicon usa o traço um pouco mais grosso.
O símbolo tem uma forma só. Estes ajustes parecem pequenos, mas desfazem o reconhecimento.
Ladrilho azul em qualquer tema do navegador. O título da aba segue “Tela · PharmaLab”.
A cor da sidebar diz onde você está antes de qualquer texto. Quem atende vários ambientes nunca confunde o painel do tenant com o portal do fornecedor.
Uma paleta curta: Halor Blue como único acento, Ink para superfícies escuras e uma escada de cinzas frios. Componentes nunca usam a paleta direto; eles usam os tokens semânticos, que mudam no tema escuro. Clique em qualquer amostra para copiar o hex.
Do Halor Brand Guidelines. Os nomes começam com --pl- e não mudam com o tema.
São estes que os componentes usam. O escuro não é o claro invertido: o azul fica mais luminoso para manter contraste e as sombras viram contorno.
| Token | Claro | Escuro | Uso |
|---|
Os mesmos componentes, lado a lado. O escuro vem de data-theme="dark", que pode ser aplicado num trecho da página, como aqui.
Dessaturadas e sempre sobre um fundo suave. Servem para estado: chip, ponto, alerta e prazo.
Queda de faturamento não é erro: o delta negativo usa cinza, como em
Seis tons, na ordem em que entram. Azul para a série principal, Ink para a comparação.
Faturamento por canal, de pedido do rep (46%) a cobrança avulsa.
Destaque de dado: barra ativa, projeção, etapa final do funil.
Plus Jakarta Sans em cinco pesos. Títulos em 600 com tracking negativo, corpo em 500 e números sempre tabulares, para que colunas de valores fiquem alinhadas.
Dez estilos cobrem o produto inteiro. Se um texto não cabe em nenhum, o problema costuma ser a hierarquia, não a escala.
Cada dígito com a mesma largura. Em tabelas, KPIs e gráficos, use .num ou .t-num.
.numQuando os centavos importam, eles aparecem em .cents, mais claros que o valor inteiro.
Regra da proposta, sem exceção: valor sempre por extenso. Vale para KPI, tabela, tooltip, eixo de gráfico, exportação e texto da IA.
Nunca “mil”, “k” ou “mi”. A pessoa compara valores de cabeça, e abreviação esconde a ordem de grandeza.
Eixos de moeda usam PL.fmt.axisBrl. Se não couber, use menos marcas, não abrevie.
Vírgula decimal, ponto de milhar e espaço fixo depois do R$, para o símbolo nunca quebrar de linha (PL.nbsp).
Digite um valor. Todas as telas usam estas funções, então o que você vê aqui é o que aparece no produto.
Relógio do protótipo: segunda-feira, 26 de outubro de 2026, 09:42. Prazos de etapa contam horas úteis; tempos de feed contam minutos corridos.
| Chamada | Resultado | Onde usar |
|---|
Base de 4 px, cantos generosos e sombras quase invisíveis. A hierarquia vem do espaço e do contraste, não de bordas e sombras pesadas.
Oito degraus. Entre cards, sempre --gap (14 px; 12 px no modo compacto).
Botão, campo e aba dividem a mesma altura, então tudo alinha numa linha.
No modo compacto as três alturas viram 32, 38 e 46.
Do chip ao card, sempre arredondado. Botões, abas, busca e filtros de barra são pílulas; campos de texto de formulário usam --r-ctl (14 px).
Três níveis e um anel. No escuro, a sombra vira um contorno de 1 px, porque sombra preta some no preto.
Sidebar flutuante, coluna de conteúdo até 1.680 px e grids que se reorganizam sozinhos. Nada rola na horizontal entre 360 e 1.920 px; tabelas largas rolam dentro do próprio card.
KPIs em 4 colunas, grids em 3 ou 4, sidebar expandida.
KPIs e grids caem para 2 colunas; a topbar esconde textos.
Sidebar vira gaveta com hambúrguer, overlay e Esc.
KPIs e categorias em rolagem horizontal, botão + flutuante.
Um sprite SVG em grade de 24, traço de 1,8 com pontas redondas e currentColor, então o ícone herda a cor do texto. Clique em um ícone para copiar a chamada.
Pílulas de 44 px, peso 600, ícone opcional à esquerda. O rótulo é sempre um verbo com objeto, para a pessoa saber o que vai acontecer antes de clicar.
Uma variante por intenção. Passe o mouse e use Tab para ver hover e foco.
| Variante | Pequeno | Padrão | Grande | Ícone | Desabilitado | Carregando |
|---|
Altura do controle, raio de pílula e ícone de 18 px. O ícone encosta 4 px na borda para o conjunto parecer centrado.
Botão de ícone sempre com rótulo acessível. O grupo junta ações irmãs.
.fab). Quando usar: só no celular, para a única ação principal da tela. Com ele, o primário da barra de ferramentas some abaixo de 640 px; sem ele, o primário vira um círculo “+”.Rótulo em cima, ajuda embaixo e erro que diz como resolver. Todos os controles têm a mesma altura e o mesmo foco azul, e todos funcionam no teclado.
.switch · role="switch".check.radio.segmented.qty · data-min · data-max.segmented[data-multi]disabled · aria-disabled.rangeTrês controles especiais do produto. A dropzone aceita arrastar ou clicar; o código aceita colar os 6 dígitos de uma vez.
Enviamos para helena@nexasaude.com.br. Para testar, digite 482913; outro código mostra o erro.
Título e descrição à esquerda, controle à direita. Estas linhas funcionam de verdade nesta página.
Cartão de comunicação abaixo das configurações.
Na madrugada de 30 de outubro, das 02:00 às 04:00, os eventos de pagamento podem chegar com atraso. A plataforma reprocessa tudo sozinha; nenhum pedido se perde.
Pequenos, mas carregam a maior parte do estado da operação. O chip diz o status, o delta diz a direção, a tag marca uma exceção e o avatar diz quem.
Fundo suave e texto na cor do estado. O tom vem do dicionário de dados, então “Aprovado” é verde em qualquer tela.
Comparação com o período anterior. Azul quando sobe, cinza quando cai.
.delta.up.delta.down.delta.good.delta.bad.delta.flat0,0%Quadradas e menores que o chip. Marcam exceção ou origem, nunca etapa.
.chip-btnIniciais sobre seis tons da marca. Sem foto, o tom vem do nome, então a mesma pessoa tem sempre a mesma cor.
.av-1 a .av-6Cards brancos de 26 px de raio sobre o Cloud. Na linha de KPIs, o primeiro cartão é escuro e carrega o número mais importante da tela.
Ícone num quadrado, delta, menu, número grande com contagem animada e uma comparação. O ? abre a definição do glossário.
O pé padrão é uma linha flexível: rótulo curto e um valor em negrito. Quando o pé vira uma frase com negrito ou link no meio, use .kpi-foot.is-text: ele corre como texto e quebra entre palavras.
Quatro fundos de card. O escuro e o azul são para destaque e aparecem no máximo uma vez por linha.
Branco, raio de 26 e --sh-1. Base de quase tudo.
.cardCloud, sem sombra. Sempre dentro de outro card: sobre o fundo da página ele some.
.card > .card-softHalor Blue com listras suaves. Para meta batida ou chamada da Lab IA.
.card-blueInk com brilho azul no canto. Primeiro KPI da linha.
.card-heroSelecionar um card filtra a tabela abaixo dele. O ativo vira Ink. Clique para testar.
As linhas da Halor: fundo Cloud, ícone redondo, valor à direita com barra de participação.
Sem fundo, com divisórias. Para rankings e listas longas dentro de um card.
Cabeçalho em pílula Cloud, linhas de 56 px, nome com a dose em cinza na mesma linha e chips suaves. Busca, filtros, visões salvas, seleção em lote e paginação vêm juntos.
Tudo funciona: busque, troque a visão, remova um filtro, selecione linhas para ver a barra de ações em lote e abra a ficha pelo olho.
| Pedido | Cliente | Produto | Rep | Valor | Pagamento | Etapa | Ações |
|---|
Tente outro termo ou limpe os filtros para ver todos os pedidos de hoje.
O modo compacto reduz linhas de 56 para 44 px e controles de 44 para 38 px. Para quem trabalha numa fila longa o dia todo.
| Receita | Paciente | Canal | Confiança | Status | Espera |
|---|
Tudo que flutua sobre a tela. Drawers e modais empilham, prendem o foco, fecham com Esc e devolvem o foco para quem os abriu. Abra cada um.
PL.drawer()Ficha, formulário longo ou detalhe, sem perder a lista. Abre à direita com 560 px.
PL.modal()Uma decisão curta e focada, com no máximo dois botões e um campo.
PL.confirm()Só para o que não volta, como excluir uma regra. Devolve uma promessa.
PL.toast()Confirma uma ação leve e oferece Desfazer por 5 segundos. Pausa no hover.
PL.menu()Ações de um item, com ícone, atalho, item marcado e ação perigosa separada.
PL.popover()Explicação curta presa a um elemento. Fecha ao clicar fora.
data-tipRótulo de botão de ícone ou atalho. Aparece no hover e no foco do teclado.
.hint · data-hint-keyA definição de um indicador, igual em todas as telas e no assistente.
PL.cmdk.open()Busca telas, pedidos e clientes, executa ações e responde perguntas com números.
PL.ai.open()Assistente em drawer, com sugestões, resposta com número calculado e link para a tela.
PL.notify.open()Agrupadas em Hoje e Antes. O estado de lida fica salvo e o ponto do sino atualiza.
PL.tour()Holofote com explicação passo a passo. Aparece uma vez por tela, e volta pela Ajuda.
Alerta para o que pede atenção, vazio que ensina, esqueleto enquanto carrega e progresso para metas. Todo feedback diz o que aconteceu e o que fazer em seguida.
Ícone, título que resume, texto que explica e até duas ações. O tom segue as cores funcionais.
Contextuais: explicam por que está vazio e oferecem o primeiro passo. Nunca só “Nenhum dado”.
Quando um rep pedir desconto acima de 5%, o pedido aparece aqui com o prazo de 2 horas úteis.
Cadastre o primeiro cliente ou importe a planilha que você já usa. Levamos menos de 2 minutos.
O catálogo tem Minoxidil 5%. Confira a dose ou busque pelo SKU.
Reproduzem a forma do conteúdo. O brilho para com movimento reduzido.
Preenchido por --v. Listrado para meta, Ink para comparação, cores funcionais para prazo.
O pedido anda em três trilhas independentes: pagamento, operação e comissão. O kanban mostra a etapa calculada a partir delas, com o prazo de cada etapa contado em horas úteis.
Ana Paula Ribeiro, para Lúcia Ribeiro · Camila Rocha · Laboratório Aurora · cartão em 3x ·
Dez etapas configuráveis em Configurações › Operação. As internas andam pelo kanban; as da Yampi andam sozinhas pelos eventos. Números de hoje.
Cada evento com horário, trilha e origem. Nada se apaga; correção vira um novo evento.
O tempo do cartão muda de cor a 80% do prazo e fica coral quando passa. Cartão atrasado ganha uma barra à esquerda. Tempo e prazo são contados em horas úteis (seg–sex, 08h–18h; 1 dia útil = 600 min): formate todo campo *Min com PL.fmt.durBiz. PL.fmt.dur é só para tempo corrido.
Pedidos reais de hoje. Arraste um cartão entre as colunas com o mouse, ou foque o cartão e aperte Enter (no celular, toque e segure) para escolher a etapa em Mover para….
Peças que várias telas faziam cada uma do seu jeito e agora saem da fundação: quem controla cada etapa, o chip da etapa, a abertura da aba, colunas fixas, resumo de valores (também sobre Ink), pé de KPI em frase, destaque da busca, barra com projeção, arte do produto, marca do tenant e QR code.
São dois trechos da Yampi com a Conferência, interna, no meio: a plataforma leva o pedido até a receita, a Yampi cuida do pagamento, a plataforma confere e a Yampi volta a mandar na separação e no envio. Toda tela desenha este mesmo modelo a partir de PL.data.pipelineRuns; nunca escreva “daqui em diante a Yampi controla” como se fosse uma passagem só.
PL.stageChip(order) escreve onde o pedido está: chip neutro com o ponto da cor da etapa. Exceção vence a etapa (Retido em âmbar, Falha na entrega em coral); Entregue fica verde. { origin: true } mostra a etiqueta Interna ou Yampi.
Uma linha de contexto logo abaixo das abas. Título só quando ele diz mais do que o nome da aba (o mês, o recorte, um bom-dia); senão, só o texto. Ação principal fica sempre à direita da subnav, nunca aqui.
Comissão nasce apurada quando o pagamento é aprovado, fica liberada 7 dias depois da entrega e é paga no lote do mês seguinte.
Pedidos que pediram uma condição fora da alçada do rep. Aprove com um toque, faça uma contraproposta ou negue com motivo.
Em linha ou painel --surface-2, use .btn-raised: superfície com borda suave, legível nos dois temas. .btn-white fica só para cards Ink, azuis ou foto.
Número clicável dentro de um texto: a pontuação que vem depois vai num .punct logo depois da .text-pill: a pílula fecha o respiro e a frase lê “chegaram.”, nunca “chegaram .”.
Desde ontem às 18h, 38 pedidos foram pagos e 12 receitas chegaram. 2 aprovações passaram do prazo.
Em tabela larga, .sticky-start prende a primeira coluna (e a seguinte, quando a primeira é a seleção) e .sticky-end prende as ações. A sombra só aparece quando há conteúdo passando por baixo. Tabelas com mais de 12 linhas ganham cabeçalho fixo e um esmaecer no pé enquanto houver linhas abaixo.
Subtotal, descontos, frete e total, alinhados à direita. Cada linha é um <div> com dt e dd; .is-neg marca desconto e .is-total fecha a conta. Sobre Ink, como o painel de total do pedido, acrescente .on-ink.
.sum-list.card-hero .sum-list.on-inkSobre Ink, o desconto fica branco como os outros valores: o verde perde contraste no fundo escuro e o sinal de menos já diz que é desconto. Em área recuada dentro de um card, use .is-soft.
Sólido é o realizado, listrado é a projeção e o traço é a meta. Cabe numa linha de tabela.
A mesma arte de embalagem em toda tela; a marca do tenant nas páginas públicas; QR que o celular lê de verdade.
Em lista filtrada, o trecho que bateu com a busca aparece marcado. Ignora acento e maiúscula: “acido” acha Ácido azelaico, “omega” acha Ômega 3. Digite para testar.
Tente parte do nome ou do SKU, como “colag” ou “AUR”.
Devolve HTML pronto para innerHTML: o texto já sai escapado e só o primeiro trecho encontrado ganha o <mark class="hl">. Busca vazia devolve só o texto escapado.
Prazos em minutos úteis viram horário de vencimento com PL.fmt.due; PL.time soma e conta minutos úteis (seg–sex, 08h–18h).
| Chamada | Resultado | Para quê |
|---|
A IA escreve o texto e sugere a ação. O número sempre sai do cálculo da plataforma, e toda resposta diz de onde veio e respeita o papel de quem pergunta.
Assim um insight nunca inventa um valor, e o mesmo número aparece no KPI, no gráfico e na frase.
Pedidos, receitas, eventos da Yampi e comissões na base gerencial.
Consultas fixas com a definição do glossário. Saída: R$ 1.448.596.
“A projeção é de R$ 1.448.596, 3,5% acima da meta.” O texto cita o número, nunca o cria.
Insight, ação sugerida e tarefas marcáveis. A barra à esquerda diz a prioridade. Gerados às 07:02 pelos agentes de cada área.
O padrão que aparece na paleta e no assistente: valor, rótulo, série curta, uma frase e o link para a tela de origem.
Dezenove tipos em SVG, sem bibliotecas externas. Todos leem as cores dos tokens, refazem o desenho na troca de tema, entram com animação, respeitam movimento reduzido e navegam pelo teclado. Os dados abaixo são da Nexa Saúde, até 26/10 às 09:42.
Cada gráfico tem role="img" e um resumo em aria-label. Com o foco nele, as setas percorrem os pontos, Enter seleciona e Esc limpa; o valor é lido em voz por uma região aria-live.
Combinações de componentes que se repetem em todo o produto. Usar o mesmo padrão em todo lugar é o que faz a pessoa aprender uma vez e saber usar todas as telas.
Busca à esquerda, ações à direita, visões salvas e chips removíveis logo abaixo. O filtro ativo sempre aparece como chip.
A ação acontece na hora. O toast avisa e oferece Desfazer, que devolve o item para o mesmo lugar.
O essencial mostra o que a pessoa usa no dia. O completo revela colunas, regras e logs. Ligue na página toda: o modo essencial esconde os trechos de código desta documentação.
ar3 · pedido acima de R$ 10.000nível gerentepiso de 10%27,4%prazo de 2 horas úteissobe para diretoria às 11:42A tela vazia explica o benefício e tem um botão que resolve. Depois da primeira ação, mostra o resultado e o próximo passo.
O admin confere a tela com os olhos de outro papel. Menu e dados seguem o recorte, uma faixa Ink avisa e o acesso fica no log. Este exemplo não muda o seu papel nas outras telas.
Selecionar linhas faz surgir a barra Ink na base da tela, com a contagem e as ações que valem para todas.
A barra aparece só com seleção, fica fixa na base da tela e some com o ✕. Ações destrutivas em lote pedem confirmação; as outras oferecem Desfazer.
Português do Brasil, frase com só a primeira letra maiúscula, palavras que a equipe usa no balcão. Escrevemos para quem está com pressa e com o celular numa mão.
Primeiro o que importa. “17 pedidos fora do prazo”, não “Atenção: há itens que requerem sua avaliação”.
Número, nome e prazo. “Aprovar até 11:42” diz mais que “aprovar em breve”.
Fale com a pessoa, sem culpar. “Não encontramos o cliente”, não “Erro 404: entidade inexistente”.
Saúde já é sensível. Nada de exclamação, caixa alta ou alarme vermelho para coisa que tem solução.
Exemplos reais de cada tipo de texto.
Verbo no infinitivo mais objeto. A pessoa lê só o botão e sabe o que vai acontecer.
Três partes, nesta ordem. A terceira é a mais importante.
Uma definição por indicador, usada em todas as telas, nos hints e pelo assistente. Vem de PL.data.glossary.
Movimento curto, com desaceleração forte no fim, só para explicar o que mudou. Com movimento reduzido ligado no sistema, tudo aparece no estado final, sem animação.
Três durações e uma curva para tudo.
Hover, cor, foco, tooltip.
Troca de aba, drawer, menu, sidebar.
Barra de progresso e entrada de gráfico.
Sai rápido e chega devagar. A pessoa vê a resposta na hora e o fim suave deixa claro onde o elemento parou. Não usamos quique, elástico ou rotação.
Quatro movimentos, todos com propósito.
PL.countUpNúmero que chega contando, uma vez, ao carregar. Em atributo, use número de JavaScript: data-countup="509.63" data-fmt="brl" mostra R$ 509,63.
PL.revealCards entram com 40 ms de diferença.
.liftPasse o mouse: o card sobe 2 px e ganha --sh-2. Diz que dá para clicar.
O mínimo de toda tela antes de ir para revisão.
Calculado agora, no tema em uso.
| Par | Amostra | Razão | Nível |
|---|
Funcionam em todas as telas com shell e nesta página. Nenhum dispara enquanto você digita.
Referência completa das variáveis CSS de pharmalab.css, com o valor claro e o escuro. Clique no nome para copiar var(--token).
| Token | Claro | Escuro | Uso |
|---|