Design systems
Design tokens como fonte única: dando a um app de Sudoku uma direção de arte de verdade
Um grid de Sudoku genérico é fácil de lançar e fácil de esquecer. Dar uma direção de arte ao nosso significou mexer primeiro no sistema de tokens, não nas telas.
A maioria dos apps de Sudoku é igual: grid cinza plano, números Roboto, botões Material genéricos, tudo branco e cinza. É seguro e é esquecível. O nosso tinha escorregado exatamente para essa cara, então demos a ele uma direção de arte de verdade. A parte interessante não foi escolher cores. Foi que o app já tinha um sistema de temas e um orçamento de performance duro, e os dois decidiram até onde o “ousado” podia ir.
Esta é a história desse redesign como ele de fato saiu: uma primeira fatia vertical, não um app pronto.
Batize a direção antes de tocar numa tela
Escolhemos uma direção e demos nome a ela: Editorial Ink. Neutros quentes tipo papel no modo claro; um charcoal quente no modo escuro; um foreground que é preto-tinta em vez de preto puro. A única cor de marca continuou o roxo. As quatro skins pagas — fun, ocean, forest, sunset — seguiram funcionando.
Dar nome cedo importou mais do que parece. “Deixa mais bonito” gera cem decisões pequenas e inconsistentes. “Isso pertence ao Editorial Ink?” gera uma. Toda escolha seguinte — peso de borda, tint de seleção, sombra — passou a ter a quem responder.
Cor é papel, não hex
A regra neste repositório é velha e chata: componente nunca cravar hex. Ele consome um token semântico. primary é a marca e a ação principal. accent é um realce sutil, não uma segunda cor de marca. Cores funcionais como danger são um eixo separado, com o próprio par de foreground para o contraste.
O redesign obrigou a cumprir essa regra onde a gente tinha trapaceado. Dois exemplos:
accenttinha virado, sem alarde, uma segunda cor de marca — um ocre que disputava com o roxo. Reclassificamos para um realce neutro sutil e tiramos o ocre.- O tabuleiro em Skia ainda desenhava erro com um
#dc2626cravado. Aquele vermelho ignorava o tema. Promovemosdanger/dangerForegrounda tokens theme-aware de verdade e apagamos o literal.
Também adicionamos os neutros que o novo visual pedia como tokens de primeira classe (secondary, muted) e renomeamos foregroundMuted para mutedForeground, para o app e o site falarem as mesmas palavras. Cada token foi propagado aos seis temas e às CSS variables, e depois mapeado no Tailwind config para que classes NativeWind como bg-danger ou text-cell-highlight resolvam por tema.
O redesign tinha que sobreviver a seis temas
Editorial Ink são dois dos seis temas. O app também traz quatro skins pagas que jogadores já compraram. Um redesign que só ficasse certo no claro e no escuro quebraria justamente aquilo pelo qual alguém pagou.
Como cada token novo foi definido para os seis temas, a tipografia, a grade, a seleção e o enquadramento do tabuleiro renderizam pelo mesmo código em toda skin. A skin muda os valores; os papéis ficam no lugar. Esse é o retorno prático dos tokens semânticos: uma reforma visual vira uma mudança numa tabela de cores, não uma bifurcação no renderer. E significa que a próxima superfície que levarmos para o Editorial Ink herda o suporte a skins de graça, em vez de cada tela re-deduzir “qual é a cor de seleção no ocean?”.
Um vocabulário só para o app e o site
Token só compensa quando existe exatamente um conjunto de nomes. Nossos sites de marketing tinham o próprio dialeto: ink, mist, line e uma escala accent que na verdade era a marca. No mesmo ciclo, renomeamos tudo para os papéis canônicos — accent virou primary, ink virou foreground, mist virou background/surface, line virou border, muted virou muted-foreground. Mesmos valores, vocabulário compartilhado. Agora uma frase como “seleção usa um tint de primary” quer dizer a mesma coisa no jogo e na landing page.
Por isso a cor de seleção do tabuleiro não é uma decisão de enfeite tomada isolada. É um tint de primary em alpha baixo — um roxo discreto que casa com o ::selection do site a 30%. Tentamos um âmbar quente para ecoar o papel, revisamos no aparelho e descartamos: ele brigava com os números em vez de guiar o olho. O token que saiu é o tint roxo, registrado como fonte única para ninguém reinventar mês que vem.
Tokens que pertencem ao tabuleiro
Nem toda necessidade visual é um papel semântico novo. Três tokens são board-derived: existem para a superfície do Sudoku e ficam no app, não no contrato compartilhado.
boardLine: uma variação deborderpara a grade.boardShadow: a sombra de deboss do frame do tabuleiro.cellHighlight: o tint de seleção, célula relacionada e mesmo número descrito acima.
Mantê-los nomeados e derivados, em vez de hex espalhado dentro do renderer, é o que faz o mesmo tabuleiro ler bem no claro, no escuro e nas quatro skins pagas sem um caminho de código por tema.
O tabuleiro é onde a identidade precisa sobreviver à renderização
O tabuleiro carrega a personalidade do jogo, e renderiza de duas formas: um canvas Skia (o padrão em produção) e um fallback React Native, em paridade. Os dois receberam o mesmo tratamento:
- Hierarquia tipográfica entre os fixos (peso maior) e os palpites do jogador.
- Dígitos tabulares, para os números não tremerem quando mudam.
- Grade hairline com separadores 3×3 mais fortes.
- Erro sinalizado por cor e forma (borda arredondada) e um micromovimento, nunca só por cor. Isso mantém o retorno de “você errou” legível para quem tem daltonismo e acima do piso de contraste 4.5:1.
- Um único frame arredondado com deboss em volta do tabuleiro inteiro, no lugar de uma sombra por célula.
Essa última escolha é design e performance ao mesmo tempo. Sombra por célula parece mais rica por um segundo e depois arrasa o orçamento de repaint num aparelho fraco. Um tabuleiro com um frame único e o deboss de boardShadow dá profundidade sem pedir para a GPU compor 81 sombras a cada seleção.
O orçamento de performance foi o teto de verdade
O aparelho de corte é um Redmi Note 7. Selecionar uma célula repinta o tabuleiro, e essa interação não pode regredir. O latency probe vai desligado no envio; a gente liga só para a medição e reverte, então produção nunca paga pela instrumentação.
Seleção de célula com repaint completo do tabuleiro deu mediana de 107ms, P90 de 141ms e máximo de 143ms em quinze amostras. Nenhum input contínuo passou do corte técnico de 180ms. Os únicos picos na faixa de 250–330ms vieram dos fluxos animados de fim de jogo e de erro, não de tocar nas células. É o formato honesto disso: a interação do dia a dia ficou dentro do orçamento, e os momentos de celebração custam mais, mas acontecem uma vez.
Números assim são o motivo de a ambição ser limitada. Um tabuleiro mais bonito que fizesse a seleção parecer mais lenta seria um produto pior, não mais ousado.
O que ainda não fizemos
Chamar isso de “o redesign” seria desonesto. Ele saiu como uma fatia vertical: a fundação de tokens, o tabuleiro e a tela Home — um masthead, um card de retomar jogo, um card de Daily Challenge e um skeleton de carregamento no lugar de spinner cru, com chaves i18n novas adicionadas nos dez idiomas.
O resto está, de propósito, ainda no visual antigo:
- Fim de jogo, o NumberPad e a barra de controles, Perfil, Loja e Configurações ainda não foram para o Editorial Ink. Eles reusam os mesmos tokens, então o que falta é espalhar uma direção, não inventar uma.
- Uma fonte display custom para os dígitos ficou adiada. Ela exige rebuild nativo e mais peso de bundle, então a fatia usa fonte de sistema com peso tabular até essa troca valer a pena.
- Idiomas da direita para a esquerda (árabe, urdu) estão catalogados, e a fatia não introduz layout que quebre em RTL, mas o espelhamento global ainda é tarefa de depois.
A lição
Um redesign ousado num app maduro é, na maior parte, editar o sistema embaixo das telas. Batize a direção para toda decisão seguinte ter a quem responder. Mova cor para tokens semânticos para o app e o site dizerem as mesmas palavras. Deixe o orçamento de performance, não o gosto, definir o teto. Depois entregue uma fatia que você consiga defender, com uma lista honesta do que ainda está no visual antigo.
Isso é menos satisfatório do que anunciar um redesign pronto. Também é a versão que é verdade, e a que deixa a próxima superfície herdar o trabalho em vez de começar do zero.