Design system aberto · v1.0

Violet Ink

O sistema por trás deste site. Um único arquivo de tokens alimenta todas as páginas, os dois temas e os dois idiomas, e tudo está aberto para leitura.

120tokens em um arquivo
3camadas: primitiva, semântica, componente
2temas a partir de uma camada semântica
AAde contraste em todo par de texto

Por que existe

O problema

O site antigo cresceu página por página. As cores variavam entre seções, e cada seção nova exigia escolher valores de novo. Ter tema claro e escuro dobrava esse trabalho.

As decisões

Componentes só leem tokens semânticos, nunca hex direto. O violeta fica reservado para ação, foco e rótulos, então ele sempre tem um significado. Uma família tipográfica, Geist, com escala fixa. Movimento também tem tokens, e tudo desliga com movimento reduzido.

Como escala

Uma página nova é montada com componentes que já existem. Um tema novo é um remapeamento de uns vinte tokens semânticos. O build exporta o tokens.json, então os mesmos valores podem ir para variáveis do Figma ou para outro código.

Cor

As primitivas são a paleta bruta. Nada na interface usa esses valores diretamente.

--ink-950#07060b
--ink-900#0d0b13
--ink-850#13101b
--ink-800#1a1624
--ink-700#262133
--ink-500#5b546d
--ink-300#8d87a0
--ink-200#b5afc6
--ink-100#e4e0ee
--ink-50#f5f3fa
--paper-0#ffffff
--paper-50#faf9fd
--paper-100#f2eff9
--paper-200#e7e2f2
--violet-200#d9cfff
--violet-300#c2b3ff
--violet-400#a68dff
--violet-500#8a6cff
--violet-600#6c4cf5
--violet-700#5535d9
--violet-800#3d24a8
--violet-900#241566
--magenta-400#ff7ab6
--magenta-600#c2185b
--green-400#48e3a0
--green-600#0e7448

Tokens semânticos

Para que cada valor serve. Cada tema liga os mesmos nomes a primitivas diferentes. O contraste é calculado com os valores reais no build da página.

TokenUsoEscuroClaro
--bgFundo da página#07060b#faf9fd
--surfaceCards e painéis#0d0b13#ffffff
--surface-raisedElementos elevados, campos#13101b#f2eff9
--surface-sunkenÁreas rebaixadas#050408#f2eff9
--fgTexto principal#f5f3fa18.4:1 · AAA#120f1a18.1:1 · AAA
--fg-mutedTexto corrido, secundário#b5afc69.5:1 · AAA#4f49628.1:1 · AAA
--fg-subtleLegendas, metadados#8d87a05.9:1 · AA#6a64805.3:1 · AA
--lineDivisores, bordas de cardrgba(255, 255, 255, .08)rgba(18, 15, 26, .09)
--line-strongBordas de controlesrgba(255, 255, 255, .16)rgba(18, 15, 26, .18)
--accentFundo da ação principal#6c4cf5#5535d9
--accent-hoverAção principal, hover#8a6cff#3d24a8
--accent-fgTexto sobre o accent#ffffff5.3:1 · AA#ffffff7.2:1 · AAA
--accent-inkLinks, rótulos, texto em accent#c2b3ff10.8:1 · AAA#5535d96.9:1 · AA
--accent-softFundo de hover, linha selecionadargba(138, 108, 255, .14)rgba(85, 53, 217, .09)
--accent-glowBrilho atrás de elementos-chavergba(108, 76, 245, .45)rgba(108, 76, 245, .22)
--successDisponibilidade, confirmações#48e3a012.3:1 · AAA#0e74485.5:1 · AA
--highlightÊnfase rara#ff7ab6#c2185b
--focus-ringContorno de foco do teclado#c2b3ff10.8:1 · AAA#5535d96.9:1 · AA
--nav-bgNav translúcidargba(7, 6, 11, .72)rgba(250, 249, 253, .78)
--scene-aCena 3D, cor principal#8a6cff#5535d9
--scene-bCena 3D, luz#c2b3ff#8a6cff
--scene-cCena 3D, sombra#241566#e7e2f2

Tipografia

Geist para tudo, Geist Mono para rótulos e código. Tamanhos grandes ganham espaçamento mais justo; o corpo fica com entrelinha 1.6.

--text-5xlclamp(46px, 8.4vw, 112px)Títulos de hero e página

Produtos que fazem voltar

--text-4xlclamp(40px, 6vw, 72px)Títulos de seção

Produtos que fazem voltar

--text-3xlclamp(32px, 4.2vw, 48px)Títulos de destaque

Produtos que fazem voltar

--text-2xlclamp(24px, 2.4vw, 30px)Títulos de card

Produtos que fazem voltar

--text-xl21pxSubtítulos

Produtos que fazem voltar

--text-lg18pxTexto de abertura

Sete anos criando apps, sites, plataformas e jogos.

--text-md16pxCorpo

Sete anos criando apps, sites, plataformas e jogos.

--text-sm14pxTexto de interface

Sete anos criando apps, sites, plataformas e jogos.

--text-xs12pxRótulos, mono

Sete anos criando apps, sites, plataformas e jogos.

Espaço e raio

Base de 4px. As seções respiram com um valor fluido, --section; as margens laterais acompanham a tela.

--space-14px
--space-28px
--space-312px
--space-416px
--space-524px
--space-632px
--space-748px
--space-864px
--space-996px
--space-10144px
--radius-sm8px
--radius-md12px
--radius-lg20px
--radius-xl28px
--radius-pill999px
--shadow-1Cards em repouso
--shadow-2Mídia em destaque

Movimento

O movimento fica guardado para três momentos: o deck do hero, a história do Orra e a desmontagem do Como o Vk é construído. O resto fica parado. Efeitos ligados ao scroll usam só transform e opacity, e tudo para com prefers-reduced-motion.

--dur-fast160ms
--dur-base280ms
--dur-slow640ms
--dur-reveal1000ms
--ease-outcubic-bezier(.16, 1, .3, 1)
--ease-in-outcubic-bezier(.65, 0, .35, 1)
--ease-standardcubic-bezier(.2, 0, 0, 1)

Componentes

Componentes reais deste site, com as mesmas classes e tokens. Passe o mouse e use o teclado.

Botão

PrimárioVer projetos
SecundárioBaixar CV
PequenoLer o caso
HoverHover
FocoFoco
DesativadoDesativado
Use

Um primário por tela. Secundário para o segundo caminho, como o CV ao lado dos projetos.

Evite

Dois primários lado a lado, ou botão para navegar dentro de um parágrafo (use link).

Acessibilidade

Área mínima de 44px (40px no pequeno em linhas densas), anel de foco de 2px visível, branco sobre --accent em 5,3:1 (7,2:1 no claro).

Status, tag e link

StatusAberto a vagas remotas
Tag
  • UX planning
  • Front-end
Use

Status para um fato atual (disponibilidade). Tags para escanear habilidades, nunca como única fonte de informação.

Evite

Tags que parecem clicáveis, ou mais de seis num card.

Acessibilidade

O ponto verde é decoração; o texto carrega o significado. Links mantêm o sublinhado.

Card de projeto

Use

Imagem primeiro, depois contexto, título, resultado em uma linha e uma ação. O card inteiro é um link só.

Evite

Links ou botões dentro do card; resultado com mais de duas linhas.

Acessibilidade

Uma parada de tab por card, o título é o nome acessível, as imagens têm alt real.

Número

  • 13+produtos entregues liderando um time de 4 designers
  • 6xmais e-mails com o builder interno
Use

Números reais com o contexto que os torna úteis, numa frase.

Evite

Números sem origem, ou um número que precisa de nota de rodapé.

Acessibilidade

Os números são texto estático, então aparecem iguais com ou sem script.

Acordeão

Você faz design, código ou os dois?

Os dois. Design é o foco; o front-end deixa o handoff curto.

Você pode começar agora?

Sim.

Use

Respostas curtas que as pessoas procuram, como fuso ou contrato.

Evite

Esconder conteúdo necessário para a decisão.

Acessibilidade

details e summary nativos: teclado e leitor de tela funcionam sem script.

Tema e idioma

Tema
Idioma
Use

O escuro é o padrão. A escolha fica salva no aparelho.

Evite

Traduzir por script: cada idioma é uma página com URL própria.

Acessibilidade

O rótulo do botão diz o que ele vai fazer. Os links de idioma têm hreflang e lang.

Temas

Os dois temas lado a lado, no mesmo componente. O escuro é o padrão; o claro é um remapeamento dos tokens semânticos, aplicado pelo atributo data-theme em qualquer elemento.

Aberto a vagas remotas

Produtos que fazem voltar.

Mesmo HTML, mesmos nomes. Só a camada semântica muda.

Ver projetosCV
  • Figma
  • React
Aberto a vagas remotas

Produtos que fazem voltar.

Mesmo HTML, mesmos nomes. Só a camada semântica muda.

Ver projetosCV
  • Figma
  • React

Regras de acessibilidade

  1. Todo par de texto passa no WCAG AA nos dois temas. A tabela acima confere isso no build.
  2. O foco sempre aparece: contorno de 2px com --focus-ring e afastamento de 3px.
  3. Áreas de toque têm no mínimo 44px, 40px para botões pequenos em linhas densas.
  4. prefers-reduced-motion para a cena 3D e os efeitos de scroll. Todo o conteúdo continua lá sem eles.
  5. Toda imagem tem alt e dimensões; o build falha se faltar um.
  6. Um h1 por página, landmarks de nav, main e footer, e um link para pular ao conteúdo.

Histórico · v1.0, novembro de 2026: primeira versão pública.