{"id":765,"date":"2026-10-07T18:33:48","date_gmt":"2026-10-07T21:33:48","guid":{"rendered":"https:\/\/yellowkode.com\/blog\/como-nomear-design-tokens-taxonomia-niveis\/"},"modified":"2026-10-07T18:33:48","modified_gmt":"2026-10-07T21:33:48","slug":"como-nomear-design-tokens-taxonomia-niveis","status":"publish","type":"post","link":"https:\/\/yellowkode.com\/blog\/como-nomear-design-tokens-taxonomia-niveis\/","title":{"rendered":"Como nomear design tokens: a taxonomia de n\u00edveis que impede o sistema de virar bagun\u00e7a"},"content":{"rendered":"<p>Em 6 de outubro de 2026, Vitaly Friedman publicou na Smashing Magazine um guia pr\u00e1tico chamado <em>A Practical Guide To Naming Things<\/em>, reunindo recursos para nomear classes CSS, cores, tokens, vari\u00e1veis, features e componentes de UI. O artigo \u00e9 essencialmente uma curadoria, apontando para trabalhos como o de Nathan Curtis (EightShapes) sobre taxonomia de tokens e o estudo de caso de Nate Baldwin sobre o Intuit Design System.<\/p>\n<p>Em vez de resumir a curadoria, vou pegar a parte mais densa dela, a nomenclatura de design tokens, e explicar o mecanismo que est\u00e1 por tr\u00e1s. Nomear token n\u00e3o \u00e9 escolha est\u00e9tica. \u00c9 escolha de API. Quando voc\u00ea escreve <code>color.text.default<\/code>, voc\u00ea est\u00e1 publicando um contrato que outro time vai consumir e que vai aparecer dentro do Figma truncado na metade. O nome \u00e9 o \u00fanico lugar onde a sem\u00e2ntica mora.<\/p>\n<h2>O mecanismo: por que um token precisa de n\u00edveis<\/h2>\n<p>Um design token \u00e9 um apelido para um valor. Em vez de usar HEX ou valores em px diretamente, voc\u00ea se refere a um token cujo nome descreve como e onde o valor \u00e9 usado, o que torna muito mais simples atualizar o design mudando um valor em um lugar sem quebrar o resto. Isso \u00e9 a parte f\u00e1cil. A parte dif\u00edcil \u00e9 que <code>#B90000<\/code> pode ser, ao mesmo tempo, a cor de borda de um input inv\u00e1lido, o fundo de um toast de erro e o \u00edcone de alerta no header. Tr\u00eas inten\u00e7\u00f5es, um valor. Se voc\u00ea der um nome s\u00f3, perde a inten\u00e7\u00e3o. Se der tr\u00eas nomes totalmente desconexos, perde o fato de que compartilham o valor.<\/p>\n<p>Pensa num endere\u00e7o postal. &#8220;Rua das Flores, 123&#8221; sozinho n\u00e3o serve para nada: existem mil Ruas das Flores no Brasil. Voc\u00ea precisa de bairro, cidade, estado, CEP. Cada n\u00edvel reduz a ambiguidade do anterior. E a ordem importa: voc\u00ea escreve do mais espec\u00edfico ao mais gen\u00e9rico (ou o contr\u00e1rio, como no padr\u00e3o japon\u00eas), mas nunca embaralhado. Taxonomia de token \u00e9 exatamente isso. Cada n\u00edvel \u00e9 uma pergunta que o nome responde, e a ordem dos n\u00edveis \u00e9 parte da gram\u00e1tica. A analogia quebra num ponto: endere\u00e7o s\u00f3 precisa levar voc\u00ea a um lugar. Token precisa tamb\u00e9m permitir que voc\u00ea troque o lugar sem reescrever o nome.<\/p>\n<h3>Os n\u00edveis de Nathan Curtis<\/h3>\n<p>Curtis, da EightShapes, prop\u00f4s um modelo que virou refer\u00eancia. Ele separa o nome do token em quatro fam\u00edlias de n\u00edveis. Os n\u00edveis base s\u00e3o o esqueleto do token e combinam categoria (por exemplo, color), concept (action) e property (size). Os n\u00edveis modifier se referem a variant (primary), state (hover), scale (100) e mode (on-dark). Os n\u00edveis object se referem a um component (button), element dentro de um componente (left-icon) ou component group (forms). Acima disso tudo pode existir um namespace, que identifica o sistema ou a marca.<\/p>\n<p>Na pr\u00e1tica isso resulta em nomes de comprimento vari\u00e1vel. O token $esds-color-neutral-42 combina quatro n\u00edveis, namespace (esds, de EightShapes Design System), category, variant e scale, para mapear para #6B6B6B. E quando a decis\u00e3o \u00e9 mais espec\u00edfica, mais n\u00edveis entram: $esds-color-feedback-background-error representa #B90000 propositalmente, e $esds-marquee-space-inset-2-x-media-query-s incorpora um nome de componente e inclui dois pares de category\/scale.<\/p>\n<p>Repare na ordem. Curtis escreve do mais gen\u00e9rico ao mais espec\u00edfico. Isso \u00e9 importante porque o nome ordenado dessa forma agrupa automaticamente quando voc\u00ea lista alfabeticamente. Todos os <code>color-feedback-*<\/code> ficam juntos. Todos os <code>color-neutral-*<\/code> ficam juntos. O autocompletar do seu editor passa a funcionar como um menu de navega\u00e7\u00e3o, e n\u00e3o como uma loteria.<\/p>\n<h3>As tr\u00eas camadas: primitive, semantic, component<\/h3>\n<p>Em cima dos n\u00edveis existe outra decis\u00e3o, independente: em que camada esse token vive. A conven\u00e7\u00e3o que foi se consolidando separa tr\u00eas. Primitive (ou global, ou base) \u00e9 o valor cru sem contexto: blue-500 diz que um azul existe e qual \u00e9 o valor dele, mas n\u00e3o diz onde usar. Semantic (ou alias) \u00e9 a inten\u00e7\u00e3o: color-text-default aponta para um primitive e diz para que serve o valor. Component \u00e9 ligado a um componente s\u00f3: button-background-hover aponta para um semantic e existe para que um componente possa divergir por conta pr\u00f3pria.<\/p>\n<p>A regra pr\u00e1tica que caiu bem no meu dia a dia: nunca referencie primitive direto no componente. Sempre passe por semantic. Isso \u00e9 o que permite trocar o tema inteiro sem tocar nos componentes. E \u00e9 tamb\u00e9m o que o time da Intuit descobriu, da forma dura, que faltava. O conjunto antigo de tokens era composto principalmente de primitives e tokens espec\u00edficos de componente, com poucos tokens sem\u00e2nticos. Um set sem\u00e2ntico fraco significava que primitives acabavam mapeados direto para tokens de componente sem contexto sistem\u00e1tico claro por tr\u00e1s da escolha de cor.<\/p>\n<h2>O que isso significa na pr\u00e1tica<\/h2>\n<p>Vou mostrar como as tr\u00eas camadas se combinam em CSS Custom Properties, que \u00e9 o jeito mais direto de implementar hoje:<\/p>\n<pre><code>:root {\n \/* Camada 1: primitives. Valor cru, sem inten\u00e7\u00e3o. *\/\n --yk-color-red-500: #b90000;\n --yk-color-red-600: #8f0000;\n --yk-color-neutral-0: #ffffff;\n --yk-color-neutral-900: #111111;\n\n \/* Camada 2: semantic. Inten\u00e7\u00e3o, aponta para primitive. *\/\n --yk-color-feedback-error: var(--yk-color-red-500);\n --yk-color-feedback-error-strong: var(--yk-color-red-600);\n --yk-color-text-default: var(--yk-color-neutral-900);\n --yk-color-surface-default: var(--yk-color-neutral-0);\n}\n\n[data-theme=\"dark\"] {\n \/* Trocar tema \u00e9 reescrever semantic, nunca primitive. *\/\n --yk-color-text-default: var(--yk-color-neutral-0);\n --yk-color-surface-default: var(--yk-color-neutral-900);\n}\n\n.yk-input--invalid {\n \/* Camada 3: component usa semantic, nunca primitive. *\/\n border-color: var(--yk-color-feedback-error);\n}<\/code><\/pre>\n<p>O que esse c\u00f3digo imp\u00f5e: quando o modo escuro muda <code>--yk-color-text-default<\/code>, nenhum componente precisa ser reescrito. Quando o rebranding muda o vermelho da marca de <code>#b90000<\/code> para outro vermelho, voc\u00ea edita o primitive e todos os semantics se ajustam. Se um componente precisa de uma cor que nenhum semantic descreve, isso \u00e9 um sinal: ou falta um semantic no sistema, ou a decis\u00e3o \u00e9 genuinamente local e merece um token de component dedicado. Dificilmente \u00e9 &#8220;vou puxar o primitive direto, s\u00f3 dessa vez&#8221;.<\/p>\n<p>Em projetos onde publiquei design system e style guide de interface, o que mais fez diferen\u00e7a n\u00e3o foi o conjunto de componentes, foi essa disciplina de camadas. \u00c9 quase nenhum engenheiro de IA que tem isso montado, e \u00e9 por isso que quase toda interface de produto com agente hoje \u00e9 feia: n\u00e3o tem onde ancorar as decis\u00f5es, cada tela \u00e9 uma decis\u00e3o nova.<\/p>\n<h3>A ordem dos n\u00edveis dentro do nome<\/h3>\n<p>Curtis defende do mais gen\u00e9rico ao mais espec\u00edfico. A Intuit tamb\u00e9m. A conven\u00e7\u00e3o de nomenclatura derivada da taxonomia \u00e9 ordenada da categoria mais gen\u00e9rica para a mais espec\u00edfica, uma forma intencional de ordenar cada categoria para construir uma sobre a outra, resultando em tokens que t\u00eam nomes naturais e humanos. O ponto de ter uma regra, qualquer regra, \u00e9 que o pr\u00f3ximo token a ser criado tem um lugar \u00f3bvio. Sem regra, cada pessoa escolhe uma ordem, e no fim do trimestre voc\u00ea tem <code>button-hover-background<\/code> e <code>background-primary-button<\/code> apontando para a mesma inten\u00e7\u00e3o.<\/p>\n<h2>Onde quebra<\/h2>\n<p>A taxonomia tem custo. O primeiro \u00e9 cognitivo: um nome como <code>yk-color-feedback-background-error-hover<\/code> \u00e9 longo. Nos problemas levantados pela Intuit: os nomes de token de componente eram dif\u00edceis de entender, eram longos e ficavam truncados na UI do Figma, havia tokens demais para escolher, e os times tinham dificuldade de identificar o racional por tr\u00e1s do uso. O Figma trunca. O autocompletar do VS Code mostra os primeiros caracteres, e se dez tokens come\u00e7am igual, voc\u00ea passa a comparar sufixos. Isso \u00e9 real e precisa ser desenhado contra.<\/p>\n<p>O segundo custo \u00e9 pol\u00edtico. Design system s\u00f3 se paga quando tem mais de um time consumindo. Em time \u00fanico, uma planilha com dez cores resolve. A taxonomia de quatro n\u00edveis \u00e9 overkill. O investimento de nomear direito s\u00f3 retorna quando aparecem o segundo e o terceiro consumidor, e quando aparece o rebranding, o dark mode, o white label. A\u00ed a economia aparece de uma vez.<\/p>\n<p>O terceiro custo \u00e9 que a disciplina s\u00f3 se mant\u00e9m se o pr\u00f3prio tooling imp\u00f5e. Num construtor de landing page que montei para tirar a cria\u00e7\u00e3o de p\u00e1gina da fila da engenharia, a redu\u00e7\u00e3o de esfor\u00e7o de desenvolvimento por p\u00e1gina passou de 70%, mas o pre\u00e7o foi aceitar que o marketing conseguisse montar p\u00e1gina fora do design system, a menos que o pr\u00f3prio builder impusesse o limite. A li\u00e7\u00e3o vale aqui: se o pipeline de tokens n\u00e3o valida nomes contra a taxonomia (via linter, via schema JSON, via check de CI), a taxonomia vai erodir em tr\u00eas sprints. Documento n\u00e3o segura, c\u00f3digo segura.<\/p>\n<p>O quarto ponto \u00e9 que taxonomia n\u00e3o resolve naming de feature voltada ao usu\u00e1rio. O artigo de Curtis expande como pensar em naming de token com uma base s\u00f3lida estendida por modifiers, objects e namespaces, e aprofunda em princ\u00edpios como completude, ordem e polihierarquia. Nada disso ajuda a decidir se o bot\u00e3o da sua ferramenta de IA se chama &#8220;Resumir&#8221;, &#8220;Sintetizar&#8221; ou &#8220;Gerar sum\u00e1rio&#8221;. Essa decis\u00e3o vem de pesquisa com usu\u00e1rio, n\u00e3o de taxonomia.<\/p>\n<h2>O que n\u00e3o d\u00e1 para afirmar ainda<\/h2>\n<p>A curadoria da Smashing junta trabalhos de contextos muito diferentes, EightShapes, Intuit, Vodafone UK, sem comparar resultados mensur\u00e1veis. N\u00e3o h\u00e1 no material n\u00famero de ado\u00e7\u00e3o, tempo at\u00e9 primeiro token \u00fatil, taxa de erro de uso. Ent\u00e3o quando o artigo sugere que taxonomia melhora a vida do time, isso \u00e9 consenso da pr\u00e1tica, n\u00e3o resultado controlado. \u00c9 poss\u00edvel que, em contextos de time pequeno e \u00fanico produto, a camada semantic adicione fric\u00e7\u00e3o sem retorno proporcional. Eu n\u00e3o testei abaixo de dois consumidores.<\/p>\n<p>Tamb\u00e9m n\u00e3o est\u00e1 claro no material como esses sistemas lidam com conflitos entre a conven\u00e7\u00e3o global e necessidades espec\u00edficas de plataforma (iOS, Android, web t\u00eam restri\u00e7\u00f5es diferentes de nome, caracteres, tamanho). O artigo de Curtis trata disso em profundidade, mas \u00e9 um t\u00f3pico \u00e0 parte.<\/p>\n<h2>Como testar isso voc\u00ea mesmo<\/h2>\n<p>Pega um projeto pequeno que voc\u00ea j\u00e1 tem e faz o seguinte, em uma hora:<\/p>\n<ol>\n<li>Lista todas as cores que aparecem no CSS. Se forem mais de dez repeti\u00e7\u00f5es do mesmo HEX, voc\u00ea j\u00e1 tem primitive impl\u00edcito.<\/li>\n<li>Para cada HEX, escreve ao lado qual \u00e9 a inten\u00e7\u00e3o. Se o mesmo HEX serve a duas inten\u00e7\u00f5es, anota as duas.<\/li>\n<li>Cria um arquivo <code>tokens.css<\/code> com tr\u00eas blocos comentados: primitives, semantics, components. Preenche s\u00f3 os primitives (<code>--brand-blue-500<\/code>) e os semantics que voc\u00ea consegue nomear sem hesitar (<code>--color-text-default<\/code>, <code>--color-surface-default<\/code>, <code>--color-feedback-error<\/code>).<\/li>\n<li>Substitui no CSS existente, come\u00e7ando pelos componentes mais est\u00e1veis, as refer\u00eancias diretas por <code>var(--...)<\/code>. Nunca referencia primitive dentro do componente.<\/li>\n<li>Adiciona um bloco <code>[data-theme=\"dark\"]<\/code> e redefine s\u00f3 os semantics. Toggle no HTML e v\u00ea se a interface vira sem voc\u00ea tocar em nenhum componente.<\/li>\n<\/ol>\n<p>Se o passo 5 funcionar sem reescrever componente, a camada semantic est\u00e1 fazendo o trabalho dela. Se n\u00e3o funcionar, provavelmente algum componente ainda est\u00e1 puxando primitive direto, e esse \u00e9 exatamente o tipo de d\u00edvida que a taxonomia existe para evitar.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Guia t\u00e9cnico de nomenclatura de design tokens: taxonomia em n\u00edveis (base, modificador, objeto, namespace), tr\u00eas camadas e exemplos de c\u00f3digo.<\/p>\n","protected":false},"author":2,"featured_media":764,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-765","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts\/765","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/comments?post=765"}],"version-history":[{"count":0,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts\/765\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/media\/764"}],"wp:attachment":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/media?parent=765"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/categories?post=765"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/tags?post=765"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}