Projeto exemplo
★ destaqueSeparação por borda, não por sombra. Raio de 12px.
designSystem("developer")
Dracula — terminal, monoespaçado e nenhum ornamento que não informe.
// objetivo
Dar a O _Dev uma linguagem visual aplicável sem adivinhação: as decisões já estão escritas, então quem constrói uma tela nova não recomeça do zero nem inventa mais uma variação do mesmo botão.
// filosofia
Este guia documenta o que existe no código, não o que seria bom existir. Cada exemplo usa as classes reais de dracula.css — se um quebrar, quebra aqui.
// princípios
▍02Foundations
As decisões de base ditas como um arquivo de config: chave = valor. Antes de cor e componente vêm o ritmo, a medida e a densidade — e a primeira decisão do _Dev é que o corpo lê como código, não como revista.
# _dev.foundations
base=monospace-first// o corpo lê como código: fonte mono, ligaduras off
ritmo=8px// toda distância é múltiplo de 8 — 4 só em detalhe fino
medida=46rem// largura de leitura, ~72ch, como um wrap de editor
raio=12px// --d-radius; card e input; nunca pill em superfície
traço=1px --d-current// a borda é a única separação — sem sombra pesada
densidade=compacta// IDE, não landing: informação por pixel, não respiro
▍03Design Tokens
Token é o contrato: o nome dura, o valor muda. A paleta canônica do Dracula, cada cor com o papel gramatical que cumpre na sintaxe. Fonte em src/styles/dracula.css.
acentos
--d-green#50fa7b--d-cyan#8be9fd--d-purple#bd93f9--d-pink#ff79c6--d-orange#ffb86c--d-yellow#f1fa8c--d-red#ff5555└─03.1Elevação & Raio
Profundidade sutil: o card não tem sombra, só borda. Sombra fica para o que flutua — dock e overlays.
| card | nenhuma — borda 1px --d-current | // Cards: separação por borda, não por sombra |
| dock | 0 6px 24px rgba(0,0,0,0.45) | // Dock flutuante e overlays |
| --d-radius | 12px | // Cards e superfícies — o padrão do realm |
| tag/chip | 999px | // Tags e pílulas |
| tab | 9px | // Abas |
| code | 8px | // Blocos de código e snippets |
▍04Typography
Uma família só, monoespaçada, para tudo. Título não é outra fonte — é peso. Se o texto não é código, ainda assim é lido por quem lê código.
JetBrains Mono
--d-mono · .font-monoMono
Tudo. Títulos, corpo, rótulos — o realm inteiro é monoespaçado.
JetBrains Mono
--d-mono · .dv-titleTítulo
Hero e títulos de página. Peso, não fonte diferente.
JetBrains Mono
--d-mono · .dv-section-titleSeção
Divisor de seção, com marca de comentário.
▍05Colors
A camada de superfície: fundos, bordas e tintas de texto. É o que faz o realm parecer um editor — recuos por --d-bg-2, divisores por --d-current, ruído por --d-comment.
superfícies
--d-bg#282a36--d-bg-2#21222c--d-current#44475a--d-fg#f8f8f2--d-comment#6272a4└─05.1A paleta é um tema de sintaxe
Aqui a cor não decora: ela classifica. A Dracula nasceu como tema de editor, e cada tinta carrega um papel gramatical — rosa é palavra-chave, verde é função, amarelo é string. É o que separa sistema de gosto pessoal: a cor de um elemento se deduz do que ele é, não do que ficaria bonito.
--d-pink--d-green--d-yellow--d-purple--d-cyan--d-orange--d-red--d-comment▍06Grid
A grelha do _Dev é a régua de colunas do editor: uma medida travada em 1120px e breakpoints escritos como as media queries que já existem no CSS. Sem colunas mágicas — a coluna é o guia de 80/120 caracteres.
| breakpoint | min-width | colunas | nota |
|---|---|---|---|
| sm | 640px | 4 | telefone deitado |
| md | 768px | 8 | tablet |
| lg | 1024px | 12 | índice fixa ao lado |
| xl | 1120px | 12 | --dv-container: trava a medida |
▍07Iconography
O ícone do _Dev é glifo de terminal, não pictograma desenhado: o mesmo caractere que sai no build. A decisão tem consequência técnica, não só estética — glifo herda cor, peso e tamanho do texto ao redor, não tem viewBox, não precisa de sprite e não adiciona um único byte de rede. Nada de biblioteca de SVG para dizer o que ✓ já diz.
// a grade é a caixa do mono, não 24×24
Não há grade de 16/20/24px como numa biblioteca de SVG: o glifo ocupa uma célula da fonte monoespaçada e escala com font-size. Isso é uma vantagem — ele nunca desalinha com o texto — e uma limitação: você não controla o peso do traço independentemente do corpo.
// alinhamento óptico com o rótulo
✓items-center — o correto
✗items-baseline — afunda
Glifos geométricos (✓ ✗ ● ▲) têm altura óptica diferente das letras: alinhados pela linha de base, parecem afundados. Use items-center e um gap fixo — nunca espaço em branco no texto, que não é ajustável.
// sempre
Decorativo → aria-hidden="true". Um ✓ ao lado da palavra "sucesso" é redundância sonora.
Sozinho → precisa de rótulo acessível. O glifo é a única informação, e leitor de tela lê "seta preta para a direita".
Cor com significado → repita em texto. Vermelho + ✗ é reforço; vermelho sozinho exclui daltônicos.
// nunca
Emoji colorido. 🚀 quebra a paleta, muda de desenho por sistema operacional e não herda a tinta.
Glifo raro. Se a fonte mono do usuário não tiver o caractere, ele vira ▯. Fique no conjunto acima, que é testado.
Dois glifos no mesmo rótulo. ➜ ✓ deploy não diz duas coisas — diz que ninguém decidiu qual.
glifos Unicode · sem dependência · herdam color e font-size
▍08Motion
Movimento discreto: nada salta. O caret pisca em passos (cursor não desvanece), o card só troca a cor da borda. Registro dos gestos e curvas do realm abaixo.
// caret — a assinatura
➜ ~/portfolio
// hover de card
passe o mouse
a borda acende — sem transform
| caret | blink em passos | // Cursor do terminal — a assinatura do realm |
| hover de card | borda muda de cor, sem transform | // Discreto: nada salta |
| entrada por rolagem | fade + 14px, escalonado | // Blocos da home chegam conforme a leitura desce |
| ease.out | cubic-bezier(0,0,0.2,1) | // Padrão — entra e assenta, sem passar do ponto |
└─08.2O inventário do movimento
Toda animação que este realm executa, extraída dos @keyframes reais das duas folhas de estilo. Documentar movimento em prosa é o jeito mais fácil de a documentação mentir — o easing muda no código e a tabela continua igual. Esta lista existe para ser conferível: são oito, e dá para contar.
| @keyframes | aplica em | dur. | curva | papel |
|---|---|---|---|---|
| dv-blink | .dv-caret | 1.1s | steps(2) | O cursor. Liga/desliga sem meio-termo — cursor de terminal não desvanece. |
| learn-flow | .learn-edge | 2.4s | linear | Fluxo ao longo de uma aresta de grafo. Linear porque representa transporte, não gesto. |
| learn-pulse | .learn-node | 1.8s | ease-in-out | Nó ativo respirando. A única curva suave do realm — e é por ser estado, não transição. |
| vibe-sweep | .vibe-morph | 0.82s | cubic-bezier(.7,0,.3,1) | A varredura que troca o modo. Entrada e saída rápidas, meio lento: parece corte, não deslize. |
| vibe-flick | .vibe-morph-label | 0.82s | steps(6) | O rótulo piscando durante a troca — seis quadros, como fluorescente ao acender. |
| crt-scan | .crt::before | 6s | linear | A linha de varredura descendo pelo tubo. Lenta o bastante para não competir com a leitura. |
| crt-flicker | .crt::after | 0.15s | steps(2) | Instabilidade do fósforo. Dois estados, sem interpolação. |
| crt-blink | .crt-cursor | 1s | steps(1) | O cursor do modo CRT — um passo só: aparece, some. |
// a assinatura do realm: steps(), não ease
steps(). Não é limitação: hardware de terminal comuta, não interpola. Um cursor com ease-in-out parece um respirador — e denuncia na hora que a peça foi desenhada por quem nunca olhou um terminal de verdade.// o que NÃO anima, de propósito
passe o ponteiro
só a borda acende — sem transform
Nenhum card sobe, inclina ou escala. As dez transition da folha são de cor e borda, nada de layout. Movimento que desloca conteúdo custa leitura — e este realm existe para ser lido.
// prefers-reduced-motion — tratado, e verificável
As duas folhas declaram @media (prefers-reduced-motion: reduce) em três blocos, com animation: none !important. Ligue a preferência no sistema e recarregue: o caret para de piscar, a varredura do CRT some, o rótulo do morph aparece estático em opacity: 1 — nenhum conteúdo some junto, que é o erro comum de quem desliga animação sem pensar no estado final. Compare com o Anfitrião, onde a preferência não muda nada porque não há o que desligar: dois realms, duas maneiras honestas de chegar ao mesmo lugar.
▍09Components
A biblioteca do realm, em quinze matérias: seis galerias que equiparam os grupos do Criativo, cinco peças que só existem aqui (terminal, diff, estados de projeto, cartões, vazio) e o chrome que toda página usa — navegação, bloco de código e as primitivas de composição. Fecha com o kit vivo, que é este mesmo catálogo rodando.
└─09.1Componentes · Botões
Quatro papéis, quatro tintas: roxo é a ação primária, borda é a de apoio, rosa é o link, vermelho é destrutivo. A cor não decora — ela diz o que acontece ao clicar, coerente com a gramática da sintaxe (05.1), onde verde é sucesso e vermelho é erro.
// papel — qual tinta, e quantas por tela
.primaryA ação que a tela existe para realizar — deploy, salvar, confirmar.
Uma por tela. Duas primárias competindo é o mesmo que nenhuma.
.secondaryAção de apoio legítima, que o usuário faz com frequência mas não é o objetivo.
Quantas fizerem sentido, lado a lado.
.ghostNavegação disfarçada de botão: ver docs, abrir repositório, cancelar.
Se leva para outro lugar, considere um link de verdade.
.dangerDestrutivo e irreversível — apagar, revogar, forçar push.
Nunca como primária. O vermelho pede confirmação, não convida.
// anatomia — o que compõe a peça
padding 0.375rem 0.75rem — vertical menor que horizontal: o alvo cresce na direção da leitura
radius 8px (--d-radius) — card e input usam o mesmo; nunca pill
gap 0.375rem entre glifo e rótulo
fonte mono, 0.75rem — o rótulo é comando, então lê-se como comando
borda 1px só nos tons que não têm preenchimento
// estados — os seis, em cada tom
| tom | default | hover | focus | loading | disabled |
|---|---|---|---|---|---|
| primary | |||||
| secondary | |||||
| danger |
Nota sobre o foco: o anel é --d-cyan com outline-offset: 2px — ciano porque é a única tinta da paleta que não carrega significado de estado (verde=ok, vermelho=erro, roxo=ação), então pode significar "onde você está" sem ambiguidade. Use :focus-visible, nunca :focus: o segundo acende também no clique de mouse e treina o usuário a ignorar o anel.
// tamanhos
md é o padrão e resolve quase tudo. `sm` só dentro de tabela ou barra densa; `lg` só quando o botão é a única ação da tela. Três tamanhos na mesma tela é sinal de hierarquia mal resolvida.
// com glifo, e só glifo
O glifo vem antes do rótulo e reforça o que ele já diz — nunca o substitui. Botão só de glifo exige aria-label e title: sem eles a peça é muda para leitor de tela e adivinhação para todo mundo.
// quando NÃO usar
✗ Para navegar
Se leva a outra rota, é <a>. Botão que navega quebra abrir-em-nova-aba, o meio-clique e o histórico.
✗ Duas primárias
Se a tela tem duas ações igualmente importantes, o problema é a tela, não o botão.
✗ Danger como padrão
Ação destrutiva não é a ação principal de nada. Vermelho confirma; nunca convida.
// acessibilidade
type
Sempre explícito. Dentro de <form>, o padrão é submit e envia sem querer.
alvo
Mínimo 24×24px de área clicável (WCAG 2.2 · 2.5.8). O `sm` chega no limite — não encolha mais.
disabled
Não recebe foco e não é anunciado. Se o motivo importa, diga em texto ao lado.
loading
Troque o rótulo, não só o ícone: leitor de tela não vê spinner. Use aria-busy.
contraste
Roxo sobre --d-bg e o texto --d-bg sobre roxo passam AA. Ghost em --d-pink também.
teclado
Enter e Espaço já funcionam em <button>. Em <div role="button"> você teria de reimplementar os dois.
// código — o que realmente está no projeto
// base compartilhada por todos os tons
const BASE = "inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 font-mono text-xs transition-colors"
const TONES = {
primary: "bg-[var(--d-purple)] text-[var(--d-bg)] hover:brightness-110",
secondary: "border border-[var(--d-current)] text-[var(--d-fg)] …",
ghost: "text-[var(--d-pink)] hover:underline",
danger: "border border-[var(--d-red)] text-[var(--d-red)] …",
}
<button type="button" className={`${BASE} ${TONES[tone]}`}>
➜ deploy
</button>.dv-snippet · .dv-code · --d-purple · --d-red · --d-pink · --d-current · --d-radius
└─09.2Componentes · Inputs & Forms
Campo é terminal: fundo recuado, borda que acende no foco (--d-purple/--d-cyan), texto mono. Rótulo em comentário, ajuda em cinza.
.dv-search · .dv-tool-field
└─09.3Componentes · Seleção
Filtro é estado, não enfeite: data-on liga, e a cor confirma. Abas com borda e raio 9px, checkbox que vira ✓ preenchido.
.dv-tab · .dv-filter · checkbox
└─09.4Componentes · Data Display
Como o _Dev mostra dado: card sem sombra, contadores ligados a rotas, tags de stack, tabela mono e linha do tempo. Nada salta — lê-se.
portfolio-2026
Next.js · TypeScript · Supabase
| rota | status | build |
|---|---|---|
| / | done | 12kb |
| /portal | done | 8kb |
| /lab | wip | — |
└─09.5Componentes · Overlays
O que flutua — e só aqui a sombra aparece (dock/overlay). Modal centrado, tooltip mono, dropdown que é uma lista de comandos.
// modal
descartar alterações?
3 arquivos não commitados
// dropdown / tooltip
└─09.6Componentes · Feedback
O feedback do _Dev fala como o processo: exit code, barra de progresso, estado (idea→done) e o vazio como linha de comentário.
// progresso
// exit code
✓ exit 0 — tudo passou
✗ exit 1 — 2 testes falharam
// nenhum resultado
➜ tente todos
└─09.7Terminal
O prompt é a assinatura do realm. Caret piscando em passos (nunca fade — cursor não desvanece), saída monoespaçada e exit code visível: 0 é verde, qualquer outra coisa é vermelha.
➜ ~/portfolio npm run build
Next.js 15.5.19
✓ Compiled successfully in 21.9s
➜ ~/portfolio
exit 0
✓ tudo passou
exit 1
✗ 2 testes falharam
└─09.8Código & diff
O bloco de código é conteúdo de primeira classe neste universo, não um adorno. O diff usa verde e vermelho da própria paleta — as mesmas tintas de sucesso e erro, porque adicionar e remover são exatamente isso.
// realm-variants.ts
export const REALM_VARIANTS: Record<RealmId, RealmVariant[]> = {
creative: CREATIVE_VARIANTS,
developer: DEVELOPER_VARIANTS,
}@@ dimension-cards.tsx @@
- FEATURED.map(id => DIMENSIONS.find(d => d.id === id)!)+ FEATURED.flatMap(id => DIMENSIONS.filter(d => d.id === id))└─09.9Estados de projeto
Um portfólio de dev mente quando mostra tudo como pronto. Os cinco estados existem para dizer a verdade sobre cada projeto — e cada um tem tinta própria, herdada do papel que a cor já cumpre na sintaxe.
.dv-status.idea · .mvp · .building · .done · .paused
└─09.10Cartões, tags e números
O card do _Dev não salta nem inclina: a borda acende e pronto. Nada aqui distrai de ler.
portfolio-2026
Next.js · TypeScript · Supabase
└─09.11Vazio
Sem onomatopeia, sem ilustração: uma linha de comentário explicando o que fazer. O vazio do _Dev fala como o código fala.
// nenhum projeto com esse filtro
➜ tente todos
└─09.13O bloco de código
A peça mais usada de um portfólio de dev e a que estava menos documentada. Três classes cooperam: o bloco em si, o invólucro que posiciona o rótulo da linguagem, e o botão de copiar. Separadas porque nem todo bloco precisa das três.
// as três camadas, juntas
# clonar e subir o ambiente
git clone git@github.com:LucasRiboldi/Portifolio2026.git
npm install && npm run dev.dv-code
O bloco: fundo --d-bg-2, borda de 1px, raio de 10px e overflow-x: auto. A rolagem horizontal é deliberada — quebrar linha de código altera o significado do que se lê.
.dv-snippet · .lang
Só um position: relative em volta, para o rótulo da linguagem ancorar no canto superior direito. Use quando a linguagem não for óbvia pelo conteúdo.
.dv-copy
Botão discreto que vira verde no hover — verde porque copiar é uma ação que dá certo, e a paleta já usa verde para sucesso. Coerente com 05.1.
// acessibilidade
Semântica
<pre><code> — não <div>. Leitor de tela anuncia bloco de código e preserva o espaçamento.
Copiar
Confirme em texto ('copiado'), não só trocando o ícone: leitor de tela não vê ⧉ virar ✓.
Rolagem
Um bloco com overflow precisa ser focável por teclado (tabindex="0"), senão quem não usa mouse não alcança o fim da linha.
Realce
As cores de sintaxe são decorativas — o código precisa ser legível se todas virarem --d-fg.
.dv-code · .dv-snippet · .lang · .dv-copy
└─09.14Primitivas de página
As três peças de composição que sustentam qualquer tela do realm: o título de seção com o marcador roxo, o chapéu que fala em sintaxe, e a grade que se organiza sozinha. Pequenas demais para virar capítulo, essenciais demais para ficarem fora do catálogo.
// título de seção
Projetos recentes
.dv-section-title injeta o ▍ por ::before — o mesmo caret que marca o cursor, agora marcando a seção. O glifo não está no HTML, então não é lido em duplicidade por leitor de tela.
// chapéu em sintaxe
buscar("projetos")
.dv-kicker escreve o chapéu como chamada de função, com .tok-fn em verde e .tok-str em amarelo — as mesmas tintas da tabela de sintaxe (05.1). É o realm sendo coerente até no subtítulo.
// a grade que se resolve sozinha
portfolio-2026
Next.js · TypeScript
sports-widget
Next.js · TypeScript
skill-seekers
Next.js · TypeScript
.dv-grid usa repeat(auto-fill, minmax(280px, 1fr)): sem breakpoint, sem variante, sem decisão. A coluna nasce quando cabem 280px e some quando não cabem — o layout responde à largura real do container, não à do viewport.
.dv-section-title · .dv-kicker · .tok-fn · .tok-str · .dv-grid
└─09.15UI Kit
Os componentes reais, não capturas — troque a versão para reimprimir o kit inteiro.
Padrão do realm — a paleta do editor, roxo profundo e verde menta
Hero & prompt
const dev = "Lucas"
Card
Separação por borda, não por sombra. Raio de 12px.
Contadores
Abas
Paleta em uso
Estado vazio
▍10Patterns
Composições que já vêm resolvidas: autenticação, busca, formulário em etapas e FAQ — mais duas nativas do realm, a paleta de comandos e o devlog. Não são telas, são arranjos que se repetem.
└─10.1Pattern · Login / Auth
Autenticar é abrir uma sessão. Sem card centrado com sombra: um prompt pede o token, o segredo é mascarado, e o exit 0 confirma.
➜ ~ auth login
email: lucas@dev.io
token: ••••••••••••
✓ autenticado — sessão aberta (exp 24h)
➜ ~
// erro → exit 1: 'token inválido', foco volta ao campo
└─10.2Pattern · Busca & filtros
Sem drawer, sem modal: campo, filtros ligados por data-on e a contagem do resultado. O dev quer ver e alternar sem sair da página.
└─10.3Pattern · Multi-step
A jornada em etapas é um pipeline: cada passo tem um estado (done/running/idle), a barra mostra onde se está, e não se pula etapa quebrada.
// passo 3 de 4 — test em execução
└─10.4Pattern · FAQ
Pergunta é uma linha de comentário; a resposta abre abaixo. Sem ícone de acordeão desenhado — o [+]/[−] basta.
[−]// por que 3 realms?
cada perfil tem gramática visual própria; um só sistema mentiria sobre a fonte.
[+]// posso linkar direto uma seção?
[+]// as amostras são reais?
└─10.5Patterns
Composição resolvida, na forma do _Dev: um command palette. Onde o Criativo abre um menu, aqui se digita. O padrão é sempre o mesmo — atalho, campo, lista filtrada, ação — porque é como o dev já navega o próprio editor.
└─10.6Devlog
A linha do tempo é o formato nativo de quem versiona: data à esquerda, o que mudou à direita. É um git log que virou UI.
Guia do _Dev: sintaxe, terminal, diff e contraste medido
Design System separado em três perfis
Portal de entrada dos 3 multiversos
▍11Templates
Páginas inteiras montadas com o kit, das oito que o portfólio realmente usa até a lista de rotas que as serve. Template aqui não é maquete: é a página que existe.
└─11.1Template · Landing
A home do dev: hero com prompt, contadores e grade de projetos.
landing.tsx · /desenvolvedor
ship()
código que roda.
└─11.2Template · Dashboard
Painel de controle: sidebar de rotas, faixa de métricas, tabela de builds.
dashboard.tsx
└─11.3Template · Artigo
O devlog longo: título, metadados e corpo com blocos de código (.dv-prose).
article.tsx · /devlog/[slug]
Como separei o DS em 3 realms
2026-07-16 · 6 min
const realms = 3
└─11.4Template · Pricing
Planos como tiers de conta: três colunas, o do meio destacado pela borda acesa.
free
$0
/mês
pro
$12
/mês
team
$40
/mês
└─11.5Template · Perfil
A página do dev: avatar mono, bio, stack em tags e heatmap de contribuição.
profile.tsx
@lucasriboldi
full-stack · Dracula enjoyer
└─11.6Template · Documentação
Docs técnica: índice à esquerda, conteúdo com code fences, âncoras por seção.
docs.tsx
# start
# api
# cli
npm i @lr/ds
└─11.7Template · Changelog
Histórico versionado: um git log com semver, tag e tipo de commit.
└─11.8Template · Coming soon
A página de espera do dev: um build em andamento, não um contador com flores.
// deploy agendado
building
└─11.9Templates
As páginas inteiras que o kit monta — listadas como arquivos, porque é o que são. Cada uma vive de verdade sob /desenvolvedor; o template não é maquete, é a rota.
▍12Contraste da paleta
Medido, não estimado: razões calculadas pela fórmula do WCAG 2 sobre --d-bg (#282a36). O resultado tem uma consequência prática que o tema não anuncia — --d-comment reprova em texto normal (3.03:1, abaixo dos 4.5:1 exigidos). Serve para comentário e ruído de fundo; não use para conteúdo que precisa ser lido.
| token | hex | vs --d-bg | WCAG AA |
|---|---|---|---|
| --d-fg | #f8f8f2 | 13.36:1 | AA |
| --d-yellow | #f1fa8c | 12.74:1 | AA |
| --d-green | #50fa7b | 10.38:1 | AA |
| --d-cyan | #8be9fd | 10.29:1 | AA |
| --d-orange | #ffb86c | 8.36:1 | AA |
| --d-pink | #ff79c6 | 5.97:1 | AA |
| --d-purple | #bd93f9 | 5.90:1 | AA |
| --d-red | #ff5555 | 4.53:1 | AA (no limite) |
| --d-comment | #6272a4 | 3.03:1 | REPROVA em texto normal |
▍13Content Design
A voz do _Dev é a do compilador: minúscula, terse, imperativa. Não pede desculpa nem usa emoji de alívio — diz o quê, onde e quantos. O erro é uma mensagem de log, não um pop-up simpático.
| ✗ evite | ✓ prefira |
|---|---|
| Ops! Algo deu errado :( | erro: build falhou em 2 arquivos |
| Clique aqui para começar | ➜ npm run dev |
| Nenhum resultado encontrado | // nenhum projeto com esse filtro |
| Salvo com sucesso! | ✓ salvo · 3 arquivos |
| Tem certeza que deseja sair? | descartar alterações não commitadas? |
▍14Brand
A marca do realm: o cursor de terminal que não para de piscar.
RealmLogoMini com cursor de terminal piscando. Classes .rl / .rl-dev em realm-logo.css.
▍15Resources
Recurso, no _Dev, é arquivo e comando — não um botão de download. Copia-se o caminho, roda-se o script. Cada linha abaixo é executável ou aponta para o código real.
src/styles/dracula.css// o tema, escopado em .draculascripts/export-tokens.mjs// gera tokens.json a partir do códigodraculatheme.com// tema oficial, upstream das cores▍16Changelog
O histórico do _Dev é literalmente um git log com semver: hash, tag, tipo e a mensagem. Documentar versão em prosa é reescrever o que o próprio repositório já registra — aqui a fonte é o commit.
// git log --oneline --decorate — fonte: o repositório
▍17Seções de página
Os blocos que montam uma página do _Dev: hero com prompt, faixa de contadores e um CTA que é um comando.
build("portfolio")
deploy rápido.
Do commit ao ar em 21.9s.
▍18Temas e janelas
Duas famílias de tema no mesmo realm, e é a comparação entre elas que ensina: o tema de editor repinta o CONTEÚDO (a sintaxe), a era de janela repinta o CHROME (a moldura). Um design system que serve a um IDE precisa dos dois, e precisa saber que são eixos independentes — Dracula numa janela do 95 é uma combinação legítima, não um erro.
// temas de editor — o mesmo código, quatro paletas
Dracula
● canônico// realm-variants.ts
export const REALMS = {
criativo: "comic",
dev: "dracula",
}
➜ ~/portfolio npm run build
✓ Compiled in 8.4s
Nord
// realm-variants.ts
export const REALMS = {
criativo: "comic",
dev: "dracula",
}
➜ ~/portfolio npm run build
✓ Compiled in 8.4s
Gruvbox
// realm-variants.ts
export const REALMS = {
criativo: "comic",
dev: "dracula",
}
➜ ~/portfolio npm run build
✓ Compiled in 8.4s
Solarized Dark
// realm-variants.ts
export const REALMS = {
criativo: "comic",
dev: "dracula",
}
➜ ~/portfolio npm run build
✓ Compiled in 8.4s
// por que renderizar em vez de listar cores
Esta seção mostrava três fileiras de amostras de cor. Amostra de cor prova que a paleta existe; não prova que o tema funciona — para isso é preciso ver o mesmo componente repintado, porque o que quebra um tema quase nunca é a cor isolada: é o par. O --cmt do Gruvbox sobre o próprio fundo, por exemplo, tem contraste mais folgado que o do Dracula, onde --d-comment reprova em texto normal (3,03:1 — ver seção 12). Duas paletas bonitas, uma decisão diferente.
└─18.1A janela de sistema — três eras
Transposta do Criativo, onde ilustrava nostalgia. Aqui é outra coisa: três gerações de resposta à mesma pergunta de interface — como uma janela anuncia que é arrastável, redimensionável e fechável, antes de existir convenção para isso.
➜ npm run build
✓ Compiled in 8.4s
Windows 951995
Bisel duro em quatro lados: a luz vem do canto superior esquerdo e a peça finge relevo físico. O botão inverte o bisel ao ser pressionado — a única animação de estado que existia.
.os-window .os-95➜ npm run build
✓ Compiled in 8.4s
Windows XP2001
Luna azul: gradiente na barra, cantos arredondados, e a primeira vez que o chrome tentou parecer plástico moldado em vez de metal dobrado.
.os-window .os-xp➜ npm run build
✓ Compiled in 8.4s
Mac OS clássico1984–2001
Listras na barra de título como pegada para arrastar, borda de 1px e nenhum gradiente. É a mais econômica das três, e a que envelheceu melhor.
.os-window .os-mac// a arquitetura é a mesma das dimensões
A estrutura não muda: .os-window > .os-titlebar (com .os-title e .os-btns) + .os-body. A era é uma classe a mais no wrapper — exatamente como as vinte dimensões do Criativo fazem com o canvas, e como o tema de editor faz com a sintaxe.
Três sistemas de tema no projeto, a mesma forma: declare no wrapper, deixe o filho ignorante. É o que permite escrever o componente uma vez.
// acessibilidade — o custo do chrome falso
"_" e "×" não dizem nada a quem ouve a página: os botões acima levam aria-label. Mas a pergunta antes dessa é se eles deviam ser botões.
Se a janela é decorativa — e numa página de portfólio ela quase sempre é —, esses controles são cenário. Botão que não faz nada mas recebe foco é uma parada morta na navegação por teclado. Nesse caso, o conjunto inteiro leva aria-hidden e os <button> viram <span>. Aqui eles são botões porque esta página os apresenta como componente — quem copiar para uma tela real precisa fazer a escolha.
.os-window · .os-titlebar · .os-title · .os-btns · .os-body · .os-btn · .os-btn-ghost · .os-inset · .os-95 · .os-xp · .os-mac
▍19Lab
Onde o realm testa ideias antes de virarem componente: uma ferramentinha interna, entrada e saída, sem sair da página.
▍20Documentação
A doc do _Dev aponta para o código, não o reescreve: cada linha é um arquivo que existe. Prosa duplicada envelhece calada.
col 1 10 20 30 40 50 60 72
··································································
| largura de leitura — ~72ch / 46rem |