Communitygithub.com

cdesiles/design-system

Construa um sistema de design como dois arquivos CSS que outros aplicativos podem copiar — tokens.css (propriedades personalizadas) e components.css (classes baseadas neles) — documentados por uma página de espécime. Leia antes de projetar qualquer coisa que terá mais de uma tela, e sempre que o projeto não tiver um sistema existente.

O que é design-system?

Este skill cria um sistema de design modular e reutilizável, gerando dois arquivos CSS essenciais: `tokens.css`, que contém propriedades personalizadas (tokens) organizados em camadas primitivas e semânticas, e `components.css`, com classes de componentes construídas exclusivamente a partir dos tokens semânticos. A saída inclui uma página de espécime HTML que documenta visualmente todos os tokens e componentes, garantindo que a documentação nunca se desvie dos valores reais. O sistema é projetado para ser copiado e integrado em qualquer projeto (React, páginas estáticas, outras ferramentas de design) sem conflitos, graças a regras de prefixação, CSS puro e resolução em tempo de execução. É útil para equipes que precisam de um design system leve, extensível e de fácil manutenção, com foco em contraste medido, escalas tipográficas e de espaçamento consistentes, e suporte a temas escuros por meio de troca de tokens.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/cdesiles/opencode-kit/tree/HEAD/skills/design-system

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Sistema de design

O sistema é o artefato. Tudo o mais é construído a partir dele. Um entregável que inventa suas próprias cores e espaçamentos é um item único; um entregável construído sobre tokens pode ser estendido, renomeado e mantido consistente.

Saída

Três arquivos, e a separação é o ponto:

  • design/tokens.css — os tokens, e nada mais. Propriedades personalizadas CSS simples.
  • design/components.css — os componentes, como classes construídas apenas a partir dos tokens semânticos.
  • design/Design System.html — o espécime. Ele <link>a ambos os arquivos e os documenta. Documentação apenas: não declara valores próprios.

Os dois arquivos CSS são o sistema: são o que outros aplicativos copiam. O espécime permanece no projeto como sua documentação.

Seções no espécime, nesta ordem:

  1. Intenção — três frases: para quem é, como deve se sentir, o que explicitamente não é.
  2. Cor — cada amostra com seu nome de token, o valor que resolve e os pares que passam no contraste.
  3. Tipografia — famílias, pesos, a escala com uma função nomeada por passo e uma amostra de parágrafo no tamanho do corpo.
  4. Espaço e forma — a escala de espaçamento, raios, sombras, bordas.
  5. Componentes — cada um renderizado em seus estados reais, junto com a marcação que um aplicativo copia.
  6. Regras — as cinco ou seis decisões que alguém normalmente erraria.
  7. Usar em um aplicativo — a versão, os dois arquivos para copiar, a ordem de carregamento, o <link> da fonte, a classe raiz e o que mudou desde a última versão.

Tokens

Duas camadas. Primitivas mantêm valores brutos; tokens semânticos nomeiam uma função e apontam para uma primitiva. Os componentes referenciam apenas tokens semânticos — é isso que torna uma mudança de marca uma alteração de uma linha.

Escreva isso em design/tokens.css. É o único arquivo no projeto onde um valor bruto pode aparecer. acme representa o prefixo do sistema (veja Compartilhamento):

/* Sistema de design Acme 1.0.0 — tokens. Copie este arquivo como está; altere-o em seu projeto de origem. */
:root {
  /* primitivas */
  --acme-ink-900: oklch(0.22 0.02 260);
  --acme-ink-600: oklch(0.48 0.02 260);
  --acme-paper-50: oklch(0.99 0.005 90);
  --acme-paper-100: oklch(0.96 0.008 90);
  --acme-line-200: oklch(0.90 0.006 90);
  --acme-accent-500: oklch(0.55 0.14 35);
  --acme-accent-600: oklch(0.45 0.15 35);
  --acme-accent-100: oklch(0.94 0.03 35);

  /* semânticas */
  --acme-text: var(--acme-ink-900);
  --acme-text-muted: var(--acme-ink-600);
  --acme-bg: var(--acme-paper-50);
  --acme-surface: var(--acme-paper-100);
  --acme-border: var(--acme-line-200);
  --acme-accent: var(--acme-accent-500);
  --acme-accent-hover: var(--acme-accent-600);
  --acme-accent-wash: var(--acme-accent-100);

  /* tipo */
  --acme-font-display: "Fraunces", Georgia, serif;
  --acme-font-text: "Public Sans", system-ui, sans-serif;
  --acme-step--1: 0.875rem;
  --acme-step-0: 1rem;
  --acme-step-1: 1.25rem;
  --acme-step-2: 1.5625rem;
  --acme-step-3: 1.953rem;
  --acme-step-4: 2.441rem;
  --acme-step-5: 3.052rem;

  /* espaço, em base de 4px */
  --acme-s-1: 4px;  --acme-s-2: 8px;   --acme-s-3: 12px;  --acme-s-4: 16px;
  --acme-s-5: 24px; --acme-s-6: 32px;  --acme-s-7: 48px;  --acme-s-8: 64px;  --acme-s-9: 96px;

  /* forma e movimento */
  --acme-radius-sm: 4px; --acme-radius: 8px; --acme-radius-lg: 16px;
  --acme-border-width: 1px; --acme-ring-width: 2px;
  --acme-shadow-1: 0 1px 2px oklch(0.2 0.02 260 / 0.06);
  --acme-shadow-2: 0 4px 16px oklch(0.2 0.02 260 / 0.08);
  --acme-ease: cubic-bezier(0.2, 0.7, 0.3, 1);
  --acme-dur: 160ms;
}

Esse bloco é um ponto de partida, não um modelo para copiar cegamente. Altere o matiz do acento, o par tipográfico e a temperatura da tinta para corresponder ao briefing — mas mantenha a estrutura.

Regras para os tokens

  • O contraste é medido, não estimado visualmente. Texto do corpo 4,5:1 contra seu fundo real; texto grande e bordas de UI 3:1. Cada página de amostra informa seus pares.
  • Oklch, não hex aleatório. Etapas uniformes de luminosidade evitam que paletas fiquem turvas. Mantenha o croma aproximadamente constante em uma família de matizes.
  • Nenhum token não utilizado. Se nada referencia um token, delete-o.
  • Nenhum valor fora deste arquivo. Um hex, literal oklch(), tamanho em px ou sombra em qualquer outro lugar é um token que ainda não foi nomeado.
  • Duas famílias tipográficas. Uma de exibição, uma de texto. As pilhas de fallback devem ser reais, não apenas sans-serif.
  • Escala, não improvise. Se um valor não está na escala de espaçamento ou tipo, adicione-o deliberadamente ou use o mais próximo.
  • Modo escuro apenas se solicitado — mas mantenha as cores semânticas para que adicioná-lo depois seja uma troca de token, não uma reescrita.

Componentes

Escreva-os em design/components.css, e renderize cada um no espécime em estado padrão, hover, foco, ativo e desabilitado, quando aplicável:

  • Botão — primário, secundário, fantasma. Um tamanho geralmente é suficiente.
  • Input de texto e select, com rótulo, texto de ajuda e estado de erro.
  • Card, com um exemplo de conteúdo real, não "Lorem ipsum".
  • Navegação, tanto em desktop quanto em largura estreita.
  • Tabela ou linha de lista com cabeçalho.
  • Badge e tag.
  • Modal ou diálogo.
  • Estado vazio.
  • Toast ou aviso inline.

Cada componente usa apenas tokens semânticos. Se um componente precisar de um valor que não possui token, isso é uma lacuna no sistema — adicione o token, não codifique o valor diretamente.

/* Sistema de design Acme 1.0.0 — componentes. Precisa de tokens.css da mesma versão, carregado primeiro. */

.acme {
  font-family: var(--acme-font-text);
  font-size: var(--acme-step-0);
  color: var(--acme-text);
  background: var(--acme-bg);
}

.acme-button {
  font: inherit;
  padding: var(--acme-s-2) var(--acme-s-4);
  border: var(--acme-border-width) solid transparent;
  border-radius: var(--acme-radius);
  background: var(--acme-accent);
  color: var(--acme-bg);
  transition: background var(--acme-dur) var(--acme-ease);
}
.acme-button:hover { background: var(--acme-accent-hover); }
.acme-button:focus-visible { outline: var(--acme-ring-width) solid var(--acme-accent); outline-offset: var(--acme-ring-width); }
.acme-button--ghost { background: transparent; color: var(--acme-accent); border-color: var(--acme-border); }

Compartilhamento

Outros aplicativos usam o sistema copiando tokens.css e components.css. As regras abaixo são o que permite que uma cópia funcione em qualquer lugar.

  • Prefixe tudo. Escolha um nome curto para o sistema antes do primeiro token e coloque-o em toda propriedade personalizada e toda classe: --acme-accent, .acme-button. As cópias então ficam lado a lado com o CSS do próprio aplicativo sem conflitos. O prefixo faz parte da API; nunca o mude.
  • CSS puro em ambos os arquivos. Sem diretivas Tailwind, sem sintaxe de pré-processador, sem aninhamento, sem exigência de @layer, sem @import entre eles. Um aplicativo React, uma página estática ou outra ferramenta de design deve obter resultados idênticos de uma cópia direta.
  • Tudo resolve em tempo de execução. Sem matemática de cores em tempo de compilação, sem saída compilada.
  • Nada global em components.css. Sem resets, sem seletores de elemento, nada em html ou body: inserir o arquivo em um aplicativo não deve reestilizá-lo. Os estilos base de texto residem na classe raiz, .acme, que um aplicativo adiciona onde desejar.
  • Estados vêm da marcação. Estilize :hover, :focus-visible, :disabled, [aria-invalid="true"], [aria-current] e [aria-expanded] em vez de classes de estado que um aplicativo teria que alternar, para que os componentes funcionem com o HTML de qualquer framework.
  • Fácil de sobrescrever. Uma classe por regra sempre que possível, sem IDs, sem !important.
  • Uma versão para ambos os arquivos. A primeira linha de cada um nomeia o sistema e sua versão; incremente a cada alteração, em ambos. Patch para um valor alterado, minor para um novo token ou componente, major para uma remoção. Renomeie adicionando o novo token e mantendo o antigo como um alias, --acme-old: var(--acme-new);, até que os aplicativos tenham migrado; remover o alias é o major bump.
  • Coisas do projeto ficam no espécime. Tags <link> de fonte, larguras de contêiner e caminhos de ativos não são tokens. O espécime mostra o <link> da fonte para que um aplicativo possa copiá-lo junto com os arquivos.

Se o projeto de destino já tiver um arquivo de token, corresponda à sua nomenclatura antes de inventar a sua própria. Um vocabulário compartilhado vale mais do que um nome melhor.

Página espécime

O espécime é documentação para humanos, não uma galeria de componentes para ser admirada. Mostre o nome do token ao lado da amostra. Mostre cada componente com a marcação que um aplicativo copia. Observe os estados que são difíceis de ver (anéis de foco, desabilitado).

Link para ambos os arquivos, tokens primeiro, e coloque a classe raiz em <body>. Use o próprio tipo e espaçamento do sistema para organizar o espécime — é a primeira prova de que o sistema funciona.

Leia os valores do arquivo em vez de digitá-los, para que a documentação não se desvie:

<link rel="stylesheet" href="tokens.css">
<link rel="stylesheet" href="components.css">
…
<body class="acme">
<figure class="swatch" data-token="--acme-accent-500"></figure>
…
<script>
  for (const el of document.querySelectorAll('[data-token]')) {
    const name = el.dataset.token;
    const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
    el.dataset.value = value;                // impresso pelo CSS
    el.style.setProperty('--swatch', value); // pintado pelo CSS
  }
</script>

A amostra se pinta a partir do token e imprime o valor que o navegador resolveu. Um hex digitado manualmente é uma mentira futura.

Finalizar

Execute design-verify no espécime. Ele lista qualquer literal de cor no espécime ou em components.css; não deve haver nenhum. Verifique se cada rótulo de amostra é legível, cada componente está alinhado à mesma grade de linha de base e nenhum texto de amostra transborda seu contêiner a 1024px de largura.

Quando o sistema for para outro aplicativo, ele copia tokens.css e components.css inalterados, além do <link> da fonte do espécime — não o espécime em si. Exporte uma cópia independente do espécime apenas se ele precisar ser lido em algum lugar sem a pasta.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Habilidades Relacionadas