@lugom.io/hefesto 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/hefesto-argos.md +279 -0
- package/agents/hefesto-athena.md +379 -0
- package/agents/hefesto-hermes.md +128 -0
- package/bin/install.js +54 -20
- package/package.json +3 -3
- package/skills/hefesto-context/SKILL.md +28 -8
- package/skills/hefesto-design/SKILL.md +194 -0
- package/skills/hefesto-design/data/animations.csv +21 -0
- package/skills/hefesto-design/data/anti-patterns.csv +41 -0
- package/skills/hefesto-design/data/charts.csv +26 -0
- package/skills/hefesto-design/data/colors.csv +108 -0
- package/skills/hefesto-design/data/components.csv +31 -0
- package/skills/hefesto-design/data/google-fonts.csv +56 -0
- package/skills/hefesto-design/data/icons.csv +23 -0
- package/skills/hefesto-design/data/landing-pages.csv +28 -0
- package/skills/hefesto-design/data/products.csv +46 -0
- package/skills/hefesto-design/data/spacing.csv +16 -0
- package/skills/hefesto-design/data/styles.csv +53 -0
- package/skills/hefesto-design/data/typography.csv +41 -0
- package/skills/hefesto-design/data/ux-rules.csv +61 -0
- package/skills/hefesto-design/references/accessibility.md +335 -0
- package/skills/hefesto-design/references/aesthetics.md +343 -0
- package/skills/hefesto-design/references/anti-patterns.md +107 -0
- package/skills/hefesto-design/references/checklist.md +66 -0
- package/skills/hefesto-design/references/color-psychology.md +203 -0
- package/skills/hefesto-design/references/component-specs.md +318 -0
- package/skills/hefesto-design/references/polish.md +339 -0
- package/skills/hefesto-design/references/token-architecture.md +394 -0
- package/skills/hefesto-design/references/ux-rules.md +349 -0
- package/skills/hefesto-design/scripts/__pycache__/audit.cpython-314.pyc +0 -0
- package/skills/hefesto-design/scripts/__pycache__/contrast.cpython-314.pyc +0 -0
- package/skills/hefesto-design/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/skills/hefesto-design/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/skills/hefesto-design/scripts/__pycache__/search.cpython-314.pyc +0 -0
- package/skills/hefesto-design/scripts/__pycache__/validate_tokens.cpython-314.pyc +0 -0
- package/skills/hefesto-design/scripts/audit.py +450 -0
- package/skills/hefesto-design/scripts/contrast.py +195 -0
- package/skills/hefesto-design/scripts/core.py +155 -0
- package/skills/hefesto-design/scripts/design_system.py +311 -0
- package/skills/hefesto-design/scripts/search.py +235 -0
- package/skills/hefesto-design/scripts/validate_tokens.py +274 -0
- package/{commands/hefesto/init.md → skills/hefesto-init/SKILL.md} +5 -2
- package/{commands/hefesto/new-feature.md → skills/hefesto-new-feature/SKILL.md} +5 -2
- package/{commands/hefesto/update.md → skills/hefesto-update/SKILL.md} +6 -3
- package/templates/DESIGN.md +137 -0
- package/templates/RECON.md +54 -0
- package/templates/RESEARCH.md +22 -25
- package/templates/STATE.md +1 -1
- package/templates/VERDICT.md +52 -0
- package/agents/.gitkeep +0 -0
- package/agents/hefesto-researcher.md +0 -180
- package/commands/hefesto/status.md +0 -46
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# Arquitetura de Design Tokens — 3 Camadas
|
|
2
|
+
|
|
3
|
+
## O que são tokens e por que importam
|
|
4
|
+
|
|
5
|
+
Design tokens são decisões de design codificadas como variáveis. Em vez de espalhar `#2563EB` por 47 arquivos, você define uma vez e referencia sempre. Tokens são o contrato entre design e código — quando o designer muda a cor primária, o dev muda um token e tudo atualiza.
|
|
6
|
+
|
|
7
|
+
Sem tokens: valores mágicos espalhados, inconsistência acumulada, dark mode impossível.
|
|
8
|
+
Com tokens: fonte única de verdade, theming trivial, escala previsível.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Camada 1: Primitivos (Core)
|
|
13
|
+
|
|
14
|
+
Valores brutos e absolutos. Não expressam intenção — são a paleta completa de possibilidades. Nomeados pelo que SÃO, não pelo que FAZEM.
|
|
15
|
+
|
|
16
|
+
### Convenção de nomes
|
|
17
|
+
|
|
18
|
+
`--color-{hue}-{shade}` para cores, `--space-{number}` para espaçamento, `--font-{property}-{value}` para tipografia.
|
|
19
|
+
|
|
20
|
+
### Exemplos completos
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
/* ═══ Cores ═══ */
|
|
24
|
+
--color-blue-50: #eff6ff;
|
|
25
|
+
--color-blue-100: #dbeafe;
|
|
26
|
+
--color-blue-200: #bfdbfe;
|
|
27
|
+
--color-blue-300: #93c5fd;
|
|
28
|
+
--color-blue-400: #60a5fa;
|
|
29
|
+
--color-blue-500: #3b82f6;
|
|
30
|
+
--color-blue-600: #2563eb;
|
|
31
|
+
--color-blue-700: #1d4ed8;
|
|
32
|
+
--color-blue-800: #1e40af;
|
|
33
|
+
--color-blue-900: #1e3a8a;
|
|
34
|
+
--color-blue-950: #172554;
|
|
35
|
+
|
|
36
|
+
--color-gray-50: #f9fafb;
|
|
37
|
+
--color-gray-100: #f3f4f6;
|
|
38
|
+
--color-gray-200: #e5e7eb;
|
|
39
|
+
--color-gray-300: #d1d5db;
|
|
40
|
+
--color-gray-400: #9ca3af;
|
|
41
|
+
--color-gray-500: #6b7280;
|
|
42
|
+
--color-gray-600: #4b5563;
|
|
43
|
+
--color-gray-700: #374151;
|
|
44
|
+
--color-gray-800: #1f2937;
|
|
45
|
+
--color-gray-900: #111827;
|
|
46
|
+
--color-gray-950: #030712;
|
|
47
|
+
|
|
48
|
+
--color-red-500: #ef4444;
|
|
49
|
+
--color-red-600: #dc2626;
|
|
50
|
+
--color-green-500: #22c55e;
|
|
51
|
+
--color-green-600: #16a34a;
|
|
52
|
+
--color-amber-500: #f59e0b;
|
|
53
|
+
--color-white: #ffffff;
|
|
54
|
+
--color-black: #000000;
|
|
55
|
+
|
|
56
|
+
/* ═══ Espaçamento ═══ */
|
|
57
|
+
--space-0: 0;
|
|
58
|
+
--space-1: 0.25rem; /* 4px */
|
|
59
|
+
--space-2: 0.5rem; /* 8px */
|
|
60
|
+
--space-3: 0.75rem; /* 12px */
|
|
61
|
+
--space-4: 1rem; /* 16px */
|
|
62
|
+
--space-5: 1.25rem; /* 20px */
|
|
63
|
+
--space-6: 1.5rem; /* 24px */
|
|
64
|
+
--space-8: 2rem; /* 32px */
|
|
65
|
+
--space-10: 2.5rem; /* 40px */
|
|
66
|
+
--space-12: 3rem; /* 48px */
|
|
67
|
+
--space-16: 4rem; /* 64px */
|
|
68
|
+
--space-20: 5rem; /* 80px */
|
|
69
|
+
--space-24: 6rem; /* 96px */
|
|
70
|
+
|
|
71
|
+
/* ═══ Tipografia ═══ */
|
|
72
|
+
--font-family-sans: 'Inter', system-ui, -apple-system, sans-serif;
|
|
73
|
+
--font-family-serif: 'Lora', Georgia, serif;
|
|
74
|
+
--font-family-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
|
75
|
+
|
|
76
|
+
--font-size-xs: 0.75rem; /* 12px */
|
|
77
|
+
--font-size-sm: 0.875rem; /* 14px */
|
|
78
|
+
--font-size-base: 1rem; /* 16px */
|
|
79
|
+
--font-size-lg: 1.125rem; /* 18px */
|
|
80
|
+
--font-size-xl: 1.25rem; /* 20px */
|
|
81
|
+
--font-size-2xl: 1.5rem; /* 24px */
|
|
82
|
+
--font-size-3xl: 1.875rem; /* 30px */
|
|
83
|
+
--font-size-4xl: 2.25rem; /* 36px */
|
|
84
|
+
--font-size-5xl: 3rem; /* 48px */
|
|
85
|
+
|
|
86
|
+
--font-weight-regular: 400;
|
|
87
|
+
--font-weight-medium: 500;
|
|
88
|
+
--font-weight-semibold: 600;
|
|
89
|
+
--font-weight-bold: 700;
|
|
90
|
+
|
|
91
|
+
--line-height-tight: 1.25;
|
|
92
|
+
--line-height-normal: 1.5;
|
|
93
|
+
--line-height-relaxed: 1.75;
|
|
94
|
+
|
|
95
|
+
/* ═══ Bordas ═══ */
|
|
96
|
+
--radius-none: 0;
|
|
97
|
+
--radius-sm: 0.25rem; /* 4px */
|
|
98
|
+
--radius-md: 0.375rem; /* 6px */
|
|
99
|
+
--radius-lg: 0.5rem; /* 8px */
|
|
100
|
+
--radius-xl: 0.75rem; /* 12px */
|
|
101
|
+
--radius-2xl: 1rem; /* 16px */
|
|
102
|
+
--radius-full: 9999px;
|
|
103
|
+
|
|
104
|
+
/* ═══ Sombras ═══ */
|
|
105
|
+
--shadow-xs: 0 1px 2px rgba(0,0,0,0.05);
|
|
106
|
+
--shadow-sm: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);
|
|
107
|
+
--shadow-md: 0 4px 6px rgba(0,0,0,0.1), 0 2px 4px rgba(0,0,0,0.06);
|
|
108
|
+
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1), 0 4px 6px rgba(0,0,0,0.05);
|
|
109
|
+
--shadow-xl: 0 20px 25px rgba(0,0,0,0.1), 0 10px 10px rgba(0,0,0,0.04);
|
|
110
|
+
|
|
111
|
+
/* ═══ Duração (animação) ═══ */
|
|
112
|
+
--duration-fast: 100ms;
|
|
113
|
+
--duration-normal: 200ms;
|
|
114
|
+
--duration-slow: 300ms;
|
|
115
|
+
--duration-slower: 500ms;
|
|
116
|
+
|
|
117
|
+
--easing-default: cubic-bezier(0.4, 0, 0.2, 1);
|
|
118
|
+
--easing-in: cubic-bezier(0.4, 0, 1, 1);
|
|
119
|
+
--easing-out: cubic-bezier(0, 0, 0.2, 1);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Camada 2: Semânticos
|
|
125
|
+
|
|
126
|
+
Expressam propósito e intenção. Não dizem qual cor — dizem para que serve. É aqui que o theming acontece: dark mode troca semânticos apontando para primitivos diferentes.
|
|
127
|
+
|
|
128
|
+
### Exemplos completos
|
|
129
|
+
|
|
130
|
+
```css
|
|
131
|
+
/* ═══ Superfícies ═══ */
|
|
132
|
+
--surface-primary: var(--color-white);
|
|
133
|
+
--surface-secondary: var(--color-gray-50);
|
|
134
|
+
--surface-tertiary: var(--color-gray-100);
|
|
135
|
+
--surface-inverse: var(--color-gray-900);
|
|
136
|
+
--surface-elevated: var(--color-white);
|
|
137
|
+
|
|
138
|
+
/* ═══ Texto ═══ */
|
|
139
|
+
--text-primary: var(--color-gray-900);
|
|
140
|
+
--text-secondary: var(--color-gray-600);
|
|
141
|
+
--text-tertiary: var(--color-gray-400);
|
|
142
|
+
--text-inverse: var(--color-white);
|
|
143
|
+
--text-link: var(--color-blue-600);
|
|
144
|
+
--text-link-hover: var(--color-blue-700);
|
|
145
|
+
|
|
146
|
+
/* ═══ Bordas ═══ */
|
|
147
|
+
--border-default: var(--color-gray-200);
|
|
148
|
+
--border-strong: var(--color-gray-300);
|
|
149
|
+
--border-focus: var(--color-blue-500);
|
|
150
|
+
|
|
151
|
+
/* ═══ Status ═══ */
|
|
152
|
+
--status-info: var(--color-blue-500);
|
|
153
|
+
--status-success: var(--color-green-500);
|
|
154
|
+
--status-warning: var(--color-amber-500);
|
|
155
|
+
--status-error: var(--color-red-500);
|
|
156
|
+
--status-info-bg: var(--color-blue-50);
|
|
157
|
+
--status-success-bg: var(--color-green-50);
|
|
158
|
+
--status-warning-bg: var(--color-amber-50);
|
|
159
|
+
--status-error-bg: var(--color-red-50);
|
|
160
|
+
|
|
161
|
+
/* ═══ Interação ═══ */
|
|
162
|
+
--interactive-primary: var(--color-blue-600);
|
|
163
|
+
--interactive-primary-hover: var(--color-blue-700);
|
|
164
|
+
--interactive-primary-active: var(--color-blue-800);
|
|
165
|
+
--interactive-secondary: var(--color-gray-100);
|
|
166
|
+
--interactive-secondary-hover: var(--color-gray-200);
|
|
167
|
+
--interactive-disabled: var(--color-gray-300);
|
|
168
|
+
--interactive-disabled-text: var(--color-gray-400);
|
|
169
|
+
|
|
170
|
+
/* ═══ Layout ═══ */
|
|
171
|
+
--spacing-page-x: var(--space-6);
|
|
172
|
+
--spacing-page-y: var(--space-8);
|
|
173
|
+
--spacing-section: var(--space-16);
|
|
174
|
+
--spacing-element: var(--space-4);
|
|
175
|
+
--spacing-inline: var(--space-2);
|
|
176
|
+
--container-max: 1200px;
|
|
177
|
+
--radius-component: var(--radius-lg);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Camada 3: Componente
|
|
183
|
+
|
|
184
|
+
Tokens específicos por componente. Usados quando um componente precisa de valores que não fazem sentido como semânticos globais. Derivam de semânticos.
|
|
185
|
+
|
|
186
|
+
### Quando usar
|
|
187
|
+
|
|
188
|
+
Use tokens de componente quando:
|
|
189
|
+
- O valor é único para aquele componente (ex: altura fixa de um botão)
|
|
190
|
+
- Múltiplos componentes usariam o mesmo semântico mas precisam divergir
|
|
191
|
+
- A complexidade do componente justifica namespace próprio
|
|
192
|
+
|
|
193
|
+
### Exemplos completos
|
|
194
|
+
|
|
195
|
+
```css
|
|
196
|
+
/* ═══ Button ═══ */
|
|
197
|
+
--button-height-sm: 2rem; /* 32px */
|
|
198
|
+
--button-height-md: 2.5rem; /* 40px */
|
|
199
|
+
--button-height-lg: 3rem; /* 48px */
|
|
200
|
+
--button-padding-x: var(--space-4);
|
|
201
|
+
--button-font-size: var(--font-size-sm);
|
|
202
|
+
--button-font-weight: var(--font-weight-medium);
|
|
203
|
+
--button-radius: var(--radius-component);
|
|
204
|
+
--button-primary-bg: var(--interactive-primary);
|
|
205
|
+
--button-primary-bg-hover: var(--interactive-primary-hover);
|
|
206
|
+
--button-primary-text: var(--text-inverse);
|
|
207
|
+
|
|
208
|
+
/* ═══ Input ═══ */
|
|
209
|
+
--input-height: 2.5rem;
|
|
210
|
+
--input-padding-x: var(--space-3);
|
|
211
|
+
--input-font-size: var(--font-size-base);
|
|
212
|
+
--input-border: var(--border-default);
|
|
213
|
+
--input-border-focus: var(--border-focus);
|
|
214
|
+
--input-border-error: var(--status-error);
|
|
215
|
+
--input-bg: var(--surface-primary);
|
|
216
|
+
--input-radius: var(--radius-component);
|
|
217
|
+
--input-placeholder: var(--text-tertiary);
|
|
218
|
+
|
|
219
|
+
/* ═══ Card ═══ */
|
|
220
|
+
--card-bg: var(--surface-elevated);
|
|
221
|
+
--card-border: var(--border-default);
|
|
222
|
+
--card-radius: var(--radius-xl);
|
|
223
|
+
--card-padding: var(--space-6);
|
|
224
|
+
--card-shadow: var(--shadow-sm);
|
|
225
|
+
--card-shadow-hover: var(--shadow-md);
|
|
226
|
+
|
|
227
|
+
/* ═══ Modal ═══ */
|
|
228
|
+
--modal-bg: var(--surface-primary);
|
|
229
|
+
--modal-overlay: rgba(0, 0, 0, 0.5);
|
|
230
|
+
--modal-radius: var(--radius-2xl);
|
|
231
|
+
--modal-padding: var(--space-8);
|
|
232
|
+
--modal-shadow: var(--shadow-xl);
|
|
233
|
+
--modal-max-width: 32rem;
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Dark Mode via Tokens
|
|
239
|
+
|
|
240
|
+
O dark mode NÃO inverte cores — redefine semânticos apontando para primitivos diferentes.
|
|
241
|
+
|
|
242
|
+
```css
|
|
243
|
+
/* Light (default) */
|
|
244
|
+
:root {
|
|
245
|
+
--surface-primary: var(--color-white);
|
|
246
|
+
--surface-secondary: var(--color-gray-50);
|
|
247
|
+
--text-primary: var(--color-gray-900);
|
|
248
|
+
--text-secondary: var(--color-gray-600);
|
|
249
|
+
--border-default: var(--color-gray-200);
|
|
250
|
+
--interactive-primary: var(--color-blue-600);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* Dark */
|
|
254
|
+
[data-theme="dark"] {
|
|
255
|
+
--surface-primary: var(--color-gray-950);
|
|
256
|
+
--surface-secondary: var(--color-gray-900);
|
|
257
|
+
--surface-elevated: var(--color-gray-800);
|
|
258
|
+
--text-primary: var(--color-gray-50);
|
|
259
|
+
--text-secondary: var(--color-gray-400);
|
|
260
|
+
--border-default: var(--color-gray-800);
|
|
261
|
+
--interactive-primary: var(--color-blue-400);
|
|
262
|
+
--shadow-sm: 0 1px 3px rgba(0,0,0,0.4);
|
|
263
|
+
--shadow-md: 0 4px 6px rgba(0,0,0,0.4);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* Respeitar preferência do sistema */
|
|
267
|
+
@media (prefers-color-scheme: dark) {
|
|
268
|
+
:root:not([data-theme="light"]) {
|
|
269
|
+
/* mesmos valores de [data-theme="dark"] */
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Regras de dark mode:
|
|
275
|
+
1. Fundo nunca é `#000000` — usar `#030712` a `#111827`
|
|
276
|
+
2. Texto nunca é `#ffffff` — usar `#f9fafb` a `#e5e7eb`
|
|
277
|
+
3. Saturação das cores deve ser reduzida 10-20% em dark
|
|
278
|
+
4. Sombras precisam ser mais fortes (maior opacidade) ou substituídas por bordas sutis
|
|
279
|
+
5. Testar contraste WCAG AA separadamente para dark mode
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Export para CSS Custom Properties
|
|
284
|
+
|
|
285
|
+
```css
|
|
286
|
+
/* tokens.css — gerado automaticamente */
|
|
287
|
+
:root {
|
|
288
|
+
/* Primitivos */
|
|
289
|
+
--color-blue-600: #2563eb;
|
|
290
|
+
/* ... todos primitivos ... */
|
|
291
|
+
|
|
292
|
+
/* Semânticos */
|
|
293
|
+
--surface-primary: var(--color-white);
|
|
294
|
+
--text-primary: var(--color-gray-900);
|
|
295
|
+
/* ... todos semânticos ... */
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/* Componentes importam separadamente */
|
|
299
|
+
/* button.css */
|
|
300
|
+
.button {
|
|
301
|
+
height: var(--button-height-md);
|
|
302
|
+
padding: 0 var(--button-padding-x);
|
|
303
|
+
/* ... */
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Export para Tailwind Config
|
|
310
|
+
|
|
311
|
+
```js
|
|
312
|
+
// tailwind.config.js
|
|
313
|
+
export default {
|
|
314
|
+
theme: {
|
|
315
|
+
colors: {
|
|
316
|
+
// Primitivos como palette
|
|
317
|
+
blue: {
|
|
318
|
+
50: 'var(--color-blue-50)',
|
|
319
|
+
100: 'var(--color-blue-100)',
|
|
320
|
+
// ...
|
|
321
|
+
900: 'var(--color-blue-900)',
|
|
322
|
+
},
|
|
323
|
+
// Semânticos como aliases
|
|
324
|
+
surface: {
|
|
325
|
+
primary: 'var(--surface-primary)',
|
|
326
|
+
secondary: 'var(--surface-secondary)',
|
|
327
|
+
elevated: 'var(--surface-elevated)',
|
|
328
|
+
},
|
|
329
|
+
foreground: {
|
|
330
|
+
primary: 'var(--text-primary)',
|
|
331
|
+
secondary: 'var(--text-secondary)',
|
|
332
|
+
inverse: 'var(--text-inverse)',
|
|
333
|
+
},
|
|
334
|
+
border: {
|
|
335
|
+
DEFAULT: 'var(--border-default)',
|
|
336
|
+
strong: 'var(--border-strong)',
|
|
337
|
+
focus: 'var(--border-focus)',
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
borderRadius: {
|
|
341
|
+
none: 'var(--radius-none)',
|
|
342
|
+
sm: 'var(--radius-sm)',
|
|
343
|
+
md: 'var(--radius-md)',
|
|
344
|
+
lg: 'var(--radius-lg)',
|
|
345
|
+
xl: 'var(--radius-xl)',
|
|
346
|
+
'2xl': 'var(--radius-2xl)',
|
|
347
|
+
full: 'var(--radius-full)',
|
|
348
|
+
},
|
|
349
|
+
// spacing usa a escala do Tailwind
|
|
350
|
+
// apontando para custom properties
|
|
351
|
+
},
|
|
352
|
+
};
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Validação de Cobertura
|
|
358
|
+
|
|
359
|
+
Como verificar que tokens estão sendo usados corretamente:
|
|
360
|
+
|
|
361
|
+
1. **Grep por valores hardcoded**: buscar hex colors, px values diretos no CSS
|
|
362
|
+
```bash
|
|
363
|
+
grep -rn '#[0-9a-fA-F]\{3,8\}' src/ --include='*.css' --include='*.tsx'
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
2. **Verificar tokens não utilizados**: listar tokens definidos vs referenciados
|
|
367
|
+
```bash
|
|
368
|
+
# Tokens definidos
|
|
369
|
+
grep -oh 'var(--[a-z-]*)' tokens.css | sort -u > defined.txt
|
|
370
|
+
# Tokens usados
|
|
371
|
+
grep -roh 'var(--[a-z-]*)' src/ | sort -u > used.txt
|
|
372
|
+
# Diferença
|
|
373
|
+
comm -23 defined.txt used.txt # definidos mas não usados
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
3. **Camada correta**: componentes nunca referenciam primitivos diretamente
|
|
377
|
+
```bash
|
|
378
|
+
# Componentes não devem usar --color-* diretamente
|
|
379
|
+
grep -rn 'var(--color-' src/components/ --include='*.css'
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## Anti-padrões
|
|
385
|
+
|
|
386
|
+
| Anti-padrão | Problema | Solução |
|
|
387
|
+
|---|---|---|
|
|
388
|
+
| Hardcoded `#2563eb` no componente | Impossível tematizar, dark mode quebra | Usar `var(--interactive-primary)` |
|
|
389
|
+
| Token sem semântica: `--blue-button` | Mistura valor com propósito | Separar: `--button-primary-bg` → `--interactive-primary` → `--color-blue-600` |
|
|
390
|
+
| Over-tokenization: token para cada pixel | Complexidade sem benefício | Tokenizar padrões repetidos, não valores únicos |
|
|
391
|
+
| Componente referencia primitivo | Pula camada semântica, theming não funciona | Componente → semântico → primitivo |
|
|
392
|
+
| Naming inconsistente | `--bgColor` vs `--bg-color` vs `--backgroundColor` | kebab-case sempre: `--surface-primary` |
|
|
393
|
+
| Tokens no JavaScript | Duplicação, dessincronização | CSS custom properties como fonte, ler com `getComputedStyle` |
|
|
394
|
+
| Sombras sem token | Inconsistência entre componentes | Definir escala de sombras como primitivos |
|