Arquitetura de Sistemas de Design na Prática: O Caminho Completo de Construção de Design Tokens a Bibliotecas de Componentes

前端工程

A Arquitetura de Três Camadas dos Sistemas de Design

┌─────────────────────────────────┐
│  Camada de Componentes          │  Button, Card, Modal...
├─────────────────────────────────┤
│  Camada de Padrões              │  Formulários, Navegação, Tabelas de Dados
├─────────────────────────────────┤
│  Camada de Tokens (Design Tokens)│  Cores, Espaçamento, Tamanhos de Fonte, Sombras
└─────────────────────────────────┘

Os tokens são a base, os padrões são a composição, os componentes são o ponto final. Construir de baixo para cima, consumir de cima para baixo.


O Sistema de Design Tokens

1. Tokens de Cor

/* Tokens semânticos de três camadas */

/* Camada 1: Valores Primitivos */
:root {
  --blue-50: #eff6ff;
  --blue-500: #3b82f6;
  --blue-700: #1d4ed8;
  --gray-50: #f9fafb;
  --gray-900: #111827;
  --red-500: #ef4444;
  --green-500: #22c55e;
}

/* Camada 2: Mapeamento Semântico */
:root {
  --color-primary: var(--blue-500);
  --color-primary-hover: var(--blue-700);
  --color-surface: var(--gray-50);
  --color-text: var(--gray-900);
  --color-danger: var(--red-500);
  --color-success: var(--green-500);
}

/* Camada 3: Específica do Componente */
:root {
  --button-bg: var(--color-primary);
  --button-bg-hover: var(--color-primary-hover);
  --button-text: white;
  --input-border: var(--color-border);
  --input-border-focus: var(--color-primary);
}

2. Tokens de Espaçamento (Sistema de Grade 8pt)

:root {
  --space-0: 0;
  --space-1: 0.25rem;  /* 4px */
  --space-2: 0.5rem;   /* 8px */
  --space-3: 0.75rem;  /* 12px */
  --space-4: 1rem;     /* 16px */
  --space-5: 1.5rem;   /* 24px */
  --space-6: 2rem;     /* 32px */
  --space-8: 3rem;     /* 48px */
  --space-10: 4rem;    /* 64px */
}

3. Tokens de Tipografia

:root {
  /* Tamanhos de fonte */
  --text-xs: 0.75rem;    /* 12px */
  --text-sm: 0.875rem;   /* 14px */
  --text-base: 1rem;     /* 16px */
  --text-lg: 1.125rem;   /* 18px */
  --text-xl: 1.25rem;    /* 20px */
  --text-2xl: 1.5rem;    /* 24px */
  --text-3xl: 1.875rem;  /* 30px */

  /* Alturas de linha */
  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.75;

  /* Pesos de fonte */
  --font-normal: 400;
  --font-medium: 500;
  --font-semibold: 600;
  --font-bold: 700;
}

4. Tokens de Sombra

:root {
  --shadow-xs: 0 1px 2px rgba(0,0,0,0.05);
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);
  --shadow-md: 0 4px 6px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.06);
  --shadow-lg: 0 10px 15px rgba(0,0,0,0.1), 0 4px 6px rgba(0,0,0,0.05);
  --shadow-xl: 0 20px 25px rgba(0,0,0,0.1), 0 8px 10px rgba(0,0,0,0.04);
}

Mecanismo de Troca de Tema

Abordagem com Variáveis CSS

/* Tema claro (padrão) */
:root {
  --color-surface: #ffffff;
  --color-text: #111827;
  --color-border: #e5e7eb;
  --color-primary: #3b82f6;
}

/* Tema escuro */
[data-theme="dark"] {
  --color-surface: #1f2937;
  --color-text: #f9fafb;
  --color-border: #374151;
  --color-primary: #60a5fa;
}

/* Tema de alto contraste */
[data-theme="high-contrast"] {
  --color-surface: #000000;
  --color-text: #ffffff;
  --color-border: #ffffff;
  --color-primary: #ffff00;
}

Troca de Tema em React

import { useEffect, useState } from 'react';

type Theme = 'light' | 'dark' | 'system';

function useTheme() {
  const [theme, setTheme] = useState<Theme>(() => {
    return (localStorage.getItem('theme') as Theme) || 'system';
  });

  useEffect(() => {
    const root = document.documentElement;
    const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    const resolved = theme === 'system' ? (systemDark ? 'dark' : 'light') : theme;

    root.setAttribute('data-theme', resolved);
    localStorage.setItem('theme', theme);
  }, [theme]);

  return { theme, setTheme };
}

Modo Escuro com Tailwind CSS v4

/* tailwind.config.ts usando modo de variáveis CSS */
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
<!-- Auto-responsivo ao tema -->
<div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
  O conteúdo se adapta automaticamente ao tema atual
</div>

Princípios de Design de API de Componentes

1. Responsabilidade Única + Composição Primeiro

// ❌ Sobre-encapsulamento: Todas as funcionalidades empilhadas em um componente
<SuperButton variant="primary" size="lg" icon="save" loading disabled />

// ✅ Padrão de composição: Montar via componentes filhos
<Button variant="primary" size="lg">
  <Icon name="save" />
  <Button.Label>Salvar</Button.Label>
  <Button.Loading />
</Button>

2. Controlado vs Não Controlado

// Modo controlado: Estado gerenciado externamente
<Input value={value} onChange={setValue} />

// Modo não controlado: Estado gerenciado internamente pelo componente
<Input defaultValue="hello" onChange={handleChange} />

// Compatível com ambos
interface InputProps {
  value?: string;          // Controlado
  defaultValue?: string;   // Não controlado
  onChange?: (value: string) => void;
}

3. Componentes Polimórficos

// Button pode renderizar como button, a, ou Link do Next.js
type ButtonProps<C extends React.ElementType = 'button'> = {
  as?: C;
} & React.ComponentPropsWithoutRef<C>;

function Button<C extends React.ElementType = 'button'>(
  { as, ...props }: ButtonProps<C>
) {
  const Component = as || 'button';
  return <Component className="btn" {...props} />;
}

// Uso
<Button>Clicar</Button>
<Button as="a" href="/link">Link</Button>
<Button as={Link} to="/page">Link de Rota</Button>

4. Padrão de Slots

// Design de Slots do componente Card
interface CardSlots {
  header?: React.ReactNode;
  media?: React.ReactNode;
  content: React.ReactNode;
  footer?: React.ReactNode;
  actions?: React.ReactNode;
}

function Card({ header, media, content, footer, actions }: CardSlots) {
  return (
    <div className="card">
      {header && <div className="card-header">{header}</div>}
      {media && <div className="card-media">{media}</div>}
      <div className="card-content">{content}</div>
      {footer && <div className="card-footer">{footer}</div>}
      {actions && <div className="card-actions">{actions}</div>}
    </div>
  );
}

Adaptação Multi-Marca

Camada de Sobrescrita de Marca

/* Tokens base (Marca A) */
:root {
  --brand-primary: #3b82f6;
  --brand-radius: 8px;
  --brand-font: 'Inter', sans-serif;
}

/* Sobrescrita Marca B */
[data-brand="b"] {
  --brand-primary: #8b5cf6;
  --brand-radius: 12px;
  --brand-font: 'Poppins', sans-serif;
}

/* Sobrescrita Marca C */
[data-brand="c"] {
  --brand-primary: #f59e0b;
  --brand-radius: 4px;
  --brand-font: 'Roboto', sans-serif;
}

Pipeline de Compilação de Tokens

Arquivos fonte de design (Figma)
  ↓
Compilação Style Dictionary
  ↓
├── Variáveis CSS (Web)
├── Configuração Tailwind (Projetos Tailwind)
├── Arquivos Swift para iOS
├── Arquivos Kotlin para Android
└── JSON (Site de documentação)
// style-dictionary.config.js
const StyleDictionary = require('style-dictionary');

module.exports = {
  source: ['tokens/**/*.json'],
  platforms: {
    css: {
      transformGroup: 'css',
      buildPath: 'dist/css/',
      files: [{ destination: 'variables.css', format: 'css/variables' }],
    },
    tailwind: {
      transformGroup: 'js',
      buildPath: 'dist/tailwind/',
      files: [{ destination: 'theme.js', format: 'javascript/module' }],
    },
  },
};

Práticas do Sistema de Design do ToolsKu

O ToolsKu usa Tailwind CSS v4 + variáveis CSS para construir seu sistema de design:

/* Tokens de tema do ToolsKu */
:root {
  --color-primary: #2563eb;
  --color-surface: #ffffff;
  --color-text: #1f2937;
  --radius: 8px;
  --font-sans: 'Inter', system-ui, sans-serif;
}

/* Componente de card de ferramenta */
.tool-card {
  padding: var(--space-4);
  border-radius: var(--radius);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  transition: transform 0.2s, box-shadow 0.2s;
}

.tool-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

Governança do Sistema de Design

Gestão de Versões

@toolsku/tokens     v2.4.0  → Pacote de Design Tokens
@toolsku/components v3.1.0  → Biblioteca de componentes
@toolsku/patterns   v1.2.0  → Biblioteca de padrões

Cadeia de dependências: patterns → components → tokens

Fluxo de Mudanças

1. O designer modifica tokens no Figma
2. Auto-sincronização para o repositório Git (Plugin do Figma)
3. CI executa compilação do Style Dictionary
4. Testes de regressão visual (Chromatic/Storybook)
5. Auto-publicação de nova versão (Changesets)

Site de Documentação

Storybook
├── Tokens      → Apresentação de cores, espaçamento, tamanhos de fonte
├── Components  → Documentação de interação de componentes
├── Patterns    → Guia de uso de padrões
└── Guidelines  → Documentação de especificações de design

Resumo

Um sistema de design não é apenas uma biblioteca de componentes, mas uma arquitetura completa de Tokens a Componentes a Padrões. Os tokens de três camadas (Primitivo → Semântico → Componente) são a base da escalabilidade. Padrões de composição superam o sobre-encapsulamento, e variáveis CSS + Tailwind é a escolha tecnológica mais prática em 2026. Lembre-se: um bom sistema de design permite que designers e desenvolvedores falem a mesma língua, e os tokens são o vocabulário dessa língua.

Experimente estas ferramentas executadas localmente no navegador — nenhum cadastro necessário →

#设计系统#Design Token#组件库#Tailwind CSS#前端架构