zark-design 1.0.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/README.md +60 -0
- package/bin/cli.js +177 -0
- package/package.json +31 -0
- package/templates/REFERENCE.md +376 -0
- package/templates/SHOWCASE.html +254 -0
- package/templates/assets/zark-icon.png +0 -0
- package/templates/assets/zark-logo.png +0 -0
- package/templates/brand.jsx +89 -0
- package/templates/components.jsx +385 -0
- package/templates/design-canvas.jsx +789 -0
- package/templates/foundations.jsx +363 -0
- package/templates/icons.jsx +65 -0
- package/templates/layouts.jsx +232 -0
- package/templates/patterns.jsx +268 -0
- package/templates/primitives.jsx +306 -0
- package/templates/tokens.css +306 -0
- package/templates/visual-references/icon-zark.png +0 -0
- package/templates/visual-references/logo-zark-principal.png +0 -0
- package/templates/visual-references/pasted-1777605750385-0.png +0 -0
- package/templates/visual-references/pasted-1777605766298-0.png +0 -0
- package/templates/visual-references/pasted-1777605775820-0.png +0 -0
- package/templates/visual-references/pasted-1777605789833-0.png +0 -0
- package/templates/visual-references/pasted-1777605802420-0.png +0 -0
- package/templates/visual-references/pasted-1777605812470-0.png +0 -0
- package/templates/visual-references/pasted-1777605817688-0.png +0 -0
- package/templates/visual-references/pasted-1777605828485-0.png +0 -0
- package/templates/visual-references/pasted-1777605837137-0.png +0 -0
- package/templates/visual-references/pasted-1777605849789-0.png +0 -0
- package/templates/visual-references/pasted-1777605864942-0.png +0 -0
- package/templates/visual-references/pasted-1777605877920-0.png +0 -0
- package/templates/visual-references/pasted-1777605897353-0.png +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# zark-design
|
|
2
|
+
|
|
3
|
+
> ZARK SAAS Design System — instale via `npx zark-design init` em qualquer projeto.
|
|
4
|
+
|
|
5
|
+
O design system fica como **REFERÊNCIA pra IA**, não como dependência runtime. A IA lê os arquivos JSX + tokens + screenshots e adapta pra qualquer stack (React, Vue, Svelte, Blade, Django templates, HTML puro com Tailwind, etc.).
|
|
6
|
+
|
|
7
|
+
## Uso
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Em qualquer pasta de projeto
|
|
11
|
+
npx zark-design init
|
|
12
|
+
|
|
13
|
+
# Cria ./design-system/ com:
|
|
14
|
+
# REFERENCE.md (cérebro: tokens + primitivos + patterns documentados)
|
|
15
|
+
# tokens.css (light + dark themes)
|
|
16
|
+
# primitives.jsx (Button, Input, Tag, etc. — referência visual)
|
|
17
|
+
# components.jsx
|
|
18
|
+
# layouts.jsx
|
|
19
|
+
# patterns.jsx
|
|
20
|
+
# icons.jsx
|
|
21
|
+
# brand.jsx
|
|
22
|
+
# foundations.jsx
|
|
23
|
+
# SHOWCASE.html (preview offline)
|
|
24
|
+
# visual-references/ (15 screenshots — ground truth visual)
|
|
25
|
+
# assets/ (logo + ícone)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Depois, abra a IA na pasta:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
claude # ou cursor . / codex / aider
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
A IA detecta `design-system/REFERENCE.md` e usa como fonte de verdade pra qualquer trabalho de UI/frontend.
|
|
35
|
+
|
|
36
|
+
## Pasta customizada
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx zark-design init ./ui # instala em ./ui em vez de ./design-system
|
|
40
|
+
npx zark-design init ./src/zark # instala em src/zark
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Sobrescrever instalação existente
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx zark-design init --force
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Integração com `.ai-context/CONTEXT.md` ou `CLAUDE.md`
|
|
50
|
+
|
|
51
|
+
Se o projeto já tem ZARK acoplado (via `zark-dev start` ou `audit`), o `init` adiciona automaticamente uma nota em `CLAUDE.md` ou `.ai-context/CONTEXT.md` instruindo a IA a ler o `REFERENCE.md` antes de qualquer UI.
|
|
52
|
+
|
|
53
|
+
## Filosofia
|
|
54
|
+
|
|
55
|
+
ZARK é warm + neutral + ember-on-paper. Cor de marca: Liquid Lava (`#f56f10`).
|
|
56
|
+
Os primitivos JSX são **referência estrutural** — adapte pra stack alvo, nunca copie literal.
|
|
57
|
+
|
|
58
|
+
## Licença
|
|
59
|
+
|
|
60
|
+
MIT — Maycon Jordan
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
import { promises as fs } from 'node:fs';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const TEMPLATES_DIR = path.resolve(__dirname, '../templates');
|
|
10
|
+
const PKG_PATH = path.resolve(__dirname, '../package.json');
|
|
11
|
+
|
|
12
|
+
const c = {
|
|
13
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
14
|
+
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
15
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
16
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
17
|
+
bold: (s) => `\x1b[1m${s}\x1b[0m`,
|
|
18
|
+
dim: (s) => `\x1b[2m${s}\x1b[0m`,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function banner(title) {
|
|
22
|
+
const line = '═'.repeat(Math.max(title.length + 4, 50));
|
|
23
|
+
console.log(c.cyan(`\n╔${line}╗`));
|
|
24
|
+
console.log(c.cyan(`║ ${c.bold(title)}${' '.repeat(line.length - title.length - 2)}║`));
|
|
25
|
+
console.log(c.cyan(`╚${line}╝\n`));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function getVersion() {
|
|
29
|
+
try {
|
|
30
|
+
const pkg = JSON.parse(await fs.readFile(PKG_PATH, 'utf-8'));
|
|
31
|
+
return pkg.version;
|
|
32
|
+
} catch {
|
|
33
|
+
return 'unknown';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function copyDir(src, dest) {
|
|
38
|
+
await fs.mkdir(dest, { recursive: true });
|
|
39
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
const sp = path.join(src, entry.name);
|
|
42
|
+
const dp = path.join(dest, entry.name);
|
|
43
|
+
if (entry.isDirectory()) {
|
|
44
|
+
await copyDir(sp, dp);
|
|
45
|
+
} else if (entry.isFile()) {
|
|
46
|
+
await fs.copyFile(sp, dp);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function appendNoteToContextFiles(targetRoot, designDirName) {
|
|
52
|
+
const note = `\n\n## Design system\nEste projeto usa o **ZARK Design System**. Antes de qualquer trabalho de UI/frontend, leia \`${designDirName}/REFERENCE.md\` (descreve tokens, primitivos, layouts e patterns). Os arquivos \`.jsx\` em \`${designDirName}/\` são REFERÊNCIA visual e estrutural — adapte pra stack atual do projeto (React/Vue/Svelte/Blade/Django templates/etc.), não copie literal. Os PNGs em \`${designDirName}/visual-references/\` são ground truth visual.\n`;
|
|
53
|
+
|
|
54
|
+
const candidates = [
|
|
55
|
+
path.join(targetRoot, '.ai-context', 'CONTEXT.md'),
|
|
56
|
+
path.join(targetRoot, 'CLAUDE.md'),
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
for (const file of candidates) {
|
|
60
|
+
if (!existsSync(file)) continue;
|
|
61
|
+
try {
|
|
62
|
+
const stat = await fs.lstat(file);
|
|
63
|
+
const realFile = stat.isSymbolicLink()
|
|
64
|
+
? path.resolve(path.dirname(file), await fs.readlink(file))
|
|
65
|
+
: file;
|
|
66
|
+
const current = await fs.readFile(realFile, 'utf-8');
|
|
67
|
+
if (current.includes('ZARK Design System')) {
|
|
68
|
+
return realFile + ' (já tem nota — pulando)';
|
|
69
|
+
}
|
|
70
|
+
await fs.writeFile(realFile, current + note, 'utf-8');
|
|
71
|
+
return realFile + ' (nota adicionada)';
|
|
72
|
+
} catch {
|
|
73
|
+
// continue
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function printHelp(version) {
|
|
80
|
+
banner(`zark-design v${version}`);
|
|
81
|
+
console.log(` ${c.bold('Comandos:')}\n`);
|
|
82
|
+
console.log(` ${c.green('init')} ${c.dim('[pasta]')} instala o design system (default: ./design-system)`);
|
|
83
|
+
console.log(` ${c.green('help')} mostra esta ajuda`);
|
|
84
|
+
console.log(` ${c.green('version')} mostra a versão\n`);
|
|
85
|
+
console.log(` ${c.bold('Uso:')}`);
|
|
86
|
+
console.log(` npx zark-design init ${c.dim('# instala em ./design-system')}`);
|
|
87
|
+
console.log(` npx zark-design init ./ui ${c.dim('# instala em ./ui')}`);
|
|
88
|
+
console.log(` npx zark-design init --force ${c.dim('# sobrescreve se já existe')}\n`);
|
|
89
|
+
console.log(` ${c.bold('Filosofia:')}`);
|
|
90
|
+
console.log(` Os arquivos JSX são ${c.bold('REFERÊNCIA')} pra IA, não pra runtime.`);
|
|
91
|
+
console.log(` A IA lê REFERENCE.md + visual-references/ e adapta pra stack atual`);
|
|
92
|
+
console.log(` do projeto (React, Vue, Svelte, Blade, Django, HTML puro, etc.).\n`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function runInit(args) {
|
|
96
|
+
const force = args.includes('--force');
|
|
97
|
+
const positional = args.filter((a) => !a.startsWith('--'));
|
|
98
|
+
const target = path.resolve(positional[0] ?? './design-system');
|
|
99
|
+
const designDirName = path.basename(target);
|
|
100
|
+
const projectRoot = path.dirname(target);
|
|
101
|
+
|
|
102
|
+
banner('🎨 zark-design — install');
|
|
103
|
+
|
|
104
|
+
if (existsSync(target)) {
|
|
105
|
+
if (!force) {
|
|
106
|
+
console.error(c.red(`✗ Pasta '${target}' já existe.`));
|
|
107
|
+
console.error(c.dim(` Use --force pra sobrescrever, ou escolha outro nome.`));
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
console.log(c.yellow(`⚠ Sobrescrevendo ${target} (--force)`));
|
|
111
|
+
await fs.rm(target, { recursive: true, force: true });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log(c.dim(` origem: ${TEMPLATES_DIR}`));
|
|
115
|
+
console.log(c.dim(` destino: ${target}\n`));
|
|
116
|
+
|
|
117
|
+
await copyDir(TEMPLATES_DIR, target);
|
|
118
|
+
|
|
119
|
+
const fileList = [];
|
|
120
|
+
async function walk(dir, base = '') {
|
|
121
|
+
for (const e of await fs.readdir(dir, { withFileTypes: true })) {
|
|
122
|
+
const sub = path.join(base, e.name);
|
|
123
|
+
if (e.isDirectory()) await walk(path.join(dir, e.name), sub);
|
|
124
|
+
else fileList.push(sub);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
await walk(target);
|
|
128
|
+
|
|
129
|
+
for (const f of fileList) {
|
|
130
|
+
console.log(` ${c.green('✓')} ${f}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
console.log('');
|
|
134
|
+
const noteResult = await appendNoteToContextFiles(projectRoot, designDirName);
|
|
135
|
+
if (noteResult) {
|
|
136
|
+
console.log(` ${c.green('✓')} ${noteResult}`);
|
|
137
|
+
} else {
|
|
138
|
+
console.log(c.dim(` (sem .ai-context/CONTEXT.md ou CLAUDE.md no projeto — sem auto-nota)`));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.log('');
|
|
142
|
+
console.log(c.green(`✓ Design system instalado em ${designDirName}/`));
|
|
143
|
+
console.log('');
|
|
144
|
+
console.log(c.bold('Próximo passo:'));
|
|
145
|
+
console.log(` Diga pra IA: ${c.dim(`"use o design system em ${designDirName}/ como referência exata pra UI"`)}`);
|
|
146
|
+
console.log(` Ou abra ${designDirName}/SHOWCASE.html no browser pra ver o sistema.`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function main() {
|
|
150
|
+
const argv = process.argv.slice(2);
|
|
151
|
+
const cmd = argv[0] ?? 'help';
|
|
152
|
+
const version = await getVersion();
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
switch (cmd) {
|
|
156
|
+
case 'init':
|
|
157
|
+
await runInit(argv.slice(1));
|
|
158
|
+
return;
|
|
159
|
+
case 'version':
|
|
160
|
+
case '--version':
|
|
161
|
+
case '-v':
|
|
162
|
+
console.log(version);
|
|
163
|
+
return;
|
|
164
|
+
case 'help':
|
|
165
|
+
case '--help':
|
|
166
|
+
case '-h':
|
|
167
|
+
default:
|
|
168
|
+
printHelp(version);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
} catch (e) {
|
|
172
|
+
console.error(c.red(`✗ ${e.message ?? e}`));
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zark-design",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "ZARK SAAS Design System — install via `npx zark-design init` to drop the design system as REFERENCE for AI in any project (any stack).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"zark-design": "bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"templates/"
|
|
12
|
+
],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=20.0.0"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"design-system",
|
|
18
|
+
"zark",
|
|
19
|
+
"saas",
|
|
20
|
+
"ai-context",
|
|
21
|
+
"scaffold",
|
|
22
|
+
"tokens",
|
|
23
|
+
"ui"
|
|
24
|
+
],
|
|
25
|
+
"author": "Maycon Jordan",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/mayconjordanr/zark-design.git"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# ZARK Design System — Referência para IA
|
|
2
|
+
|
|
3
|
+
> **Para a IA**: este documento é a fonte de verdade do design system ZARK.
|
|
4
|
+
> Os arquivos `.jsx` deste diretório são **REFERÊNCIA visual e estrutural**, não código pra rodar.
|
|
5
|
+
> Adapte os componentes pra stack atual do projeto — React, Vue, Svelte, Solid, Qwik, Blade (Laravel), Django templates, ERB (Rails), HTML puro com Tailwind, CSS modules, styled-components — qualquer uma.
|
|
6
|
+
> Os PNGs em `visual-references/` são **ground truth visual** — quando dúvida sobre aparência, abra e olhe.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Filosofia visual
|
|
11
|
+
|
|
12
|
+
ZARK é um sistema **warm, neutral, ember-on-paper**. Pense em:
|
|
13
|
+
- **Paper** (fundo cremoso quente, não branco puro) com **ink** (texto preto-quente, não preto puro)
|
|
14
|
+
- **Liquid Lava** (`#F56F10`, ember-500) é a única cor de marca — usar **com moderação** em CTAs primários, focus rings, brand moments. Nunca como background dominante de telas inteiras.
|
|
15
|
+
- **Hairlines** finas (1px) em `--line-200` para separação de superfícies — não usar `border` grosso ou caixas duras
|
|
16
|
+
- **Shadows curtas e quentes**, não shadows azuis frios — sombras são `rgba(20, 17, 12, ...)` (warm-black), não `rgba(0,0,0,...)`
|
|
17
|
+
- **Sem gradient** salvo casos pontuais (botão primário ember pode ter mini-gradient interno; nada de big hero gradients)
|
|
18
|
+
- **Tipografia editorial**: Inter pra UI, JetBrains Mono pra código, Darker Grotesque pra moments de display (hero numbers, eyebrows de marketing) — usar com parcimônia
|
|
19
|
+
|
|
20
|
+
A vibe-alvo: **Linear meets Vercel meets Things 3** — superfície limpa, densidade alta de informação por unidade de tela, hierarquia tipográfica clara, microinterações rápidas (120-180ms ease-out).
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. Tokens (`tokens.css`)
|
|
25
|
+
|
|
26
|
+
Importe `tokens.css` no entry-point do projeto. Todos os componentes referenciam variáveis CSS.
|
|
27
|
+
|
|
28
|
+
### 2.1 Brand / Ember
|
|
29
|
+
|
|
30
|
+
| Token | Valor light | Uso |
|
|
31
|
+
|-------|------|-----|
|
|
32
|
+
| `--ember-500` (`--liquid-lava`) | `#f56f10` | Cor de marca. CTAs primários, focus, brand. **Inalterado no dark mode.** |
|
|
33
|
+
| `--ember-600` (`--liquid-lava-dark`) | `#d45e0d` | Hover/active de CTA primário (no light) |
|
|
34
|
+
| `--ember-50/100/200` | tons claros | Bg de tag, code, success-states leves |
|
|
35
|
+
| `--ember-700/800/900` | tons escuros | Texto sobre fundos ember claros |
|
|
36
|
+
| `--dark-void` | `#151419` | Fundo dark mode (canvas) |
|
|
37
|
+
| `--glucon-grey` | `#1b1a1e` | Surface dark mode |
|
|
38
|
+
|
|
39
|
+
### 2.2 Neutros (paper → ink)
|
|
40
|
+
|
|
41
|
+
| Token | Light | Dark | Uso |
|
|
42
|
+
|-------|-------|------|-----|
|
|
43
|
+
| `--paper` | `#fafaf8` | `#0e0d11` | App background |
|
|
44
|
+
| `--canvas` | `#f5f4f1` | `#151419` | Sidebar, painel secundário |
|
|
45
|
+
| `--surface` | `#ffffff` | `#1b1a1e` | Cards, modais, dropdown |
|
|
46
|
+
| `--line-100` | `#f0eeea` | `#232227` | Hairlines em fundos tintados |
|
|
47
|
+
| `--line-200` | `#e8e6e1` | `#2c2b32` | Border padrão |
|
|
48
|
+
| `--line-300` | `#d8d5cf` | `#3a383f` | Divider mais forte |
|
|
49
|
+
| `--ink-700` | `#1a1916` | `#f0ede5` | Texto primary |
|
|
50
|
+
| `--ink-500` | `#4a4741` | `#c8c5bf` | Texto body |
|
|
51
|
+
| `--ink-400` | `#6f6b64` | `#a09c95` | Texto secondary, labels |
|
|
52
|
+
| `--ink-300` | `#a09c95` | `#6f6b64` | Texto disabled, placeholder |
|
|
53
|
+
|
|
54
|
+
### 2.3 Semânticos
|
|
55
|
+
|
|
56
|
+
| Token | Valor | Uso |
|
|
57
|
+
|-------|-------|-----|
|
|
58
|
+
| `--success-500` | `#10a960` | Ícones, badges OK. NUNCA texto sobre fundo claro sem contraste |
|
|
59
|
+
| `--warning-500` | `#d99000` | Avisos não-críticos |
|
|
60
|
+
| `--danger-500` | `#dc3545` | Erros, destrutivo. Em botões: bg + white text |
|
|
61
|
+
| `--info-500` | `#2f7adc` | Info neutra |
|
|
62
|
+
|
|
63
|
+
Sempre acompanha um par `*-50` (bg suave) e `*-700` (texto sobre `*-50`).
|
|
64
|
+
|
|
65
|
+
### 2.4 Tipografia
|
|
66
|
+
|
|
67
|
+
| Token | Valor | Uso |
|
|
68
|
+
|-------|-------|-----|
|
|
69
|
+
| `--font-sans` (`--font-ui`) | Inter | UI texto, botões, labels |
|
|
70
|
+
| `--font-mono` | JetBrains Mono | Código, keyboard shortcuts (`<kbd>`), specs |
|
|
71
|
+
| `--font-display` | Darker Grotesque | Hero numbers, marketing display, eyebrows raros |
|
|
72
|
+
|
|
73
|
+
Escala (px): 10, 11, 12, 13, **14 (base UI)**, 16, 18, 22, 28, 36, 48, 64, 88. Use `--fs-base` (14) como padrão de UI; `--fs-md` (13) pra denso; `--fs-2xl+` pra display.
|
|
74
|
+
|
|
75
|
+
Line-heights: `--lh-tight` (1.1, hero/display), `--lh-snug` (1.25, headings), `--lh-base` (1.45, body), `--lh-loose` (1.6, longform).
|
|
76
|
+
|
|
77
|
+
Letter-spacing: use `--ls-tight` (-0.02em) em headings grandes; `--ls-widest` (0.14em uppercase) em eyebrows e tags.
|
|
78
|
+
|
|
79
|
+
Pesos: 400 regular, 500 medium (UI label/btn), 600 semibold (heading médio), 700 bold (display, ênfase).
|
|
80
|
+
|
|
81
|
+
### 2.5 Espaçamento (4px base)
|
|
82
|
+
|
|
83
|
+
`--sp-1` (2px) → `--sp-48` (96px). Default de stack vertical: `--sp-12` (24px). Default de gap em flex: `--sp-8` (16px). Padding interno de card: `--sp-16` ou `--sp-20`.
|
|
84
|
+
|
|
85
|
+
### 2.6 Raios
|
|
86
|
+
|
|
87
|
+
`--r-xs` (3px) inputs/tags densos · `--r-sm` (4px) inputs/buttons · `--r-md` (6px) padrão · `--r-lg` (8px) cards · `--r-xl` (12px) modals · `--r-2xl` (16px) hero panels · `--r-pill` (999px) avatars/pills.
|
|
88
|
+
|
|
89
|
+
### 2.7 Sombras
|
|
90
|
+
|
|
91
|
+
`--shadow-xs` hairline · `--shadow-sm` card neutro · `--shadow-md` card elevated/hover · `--shadow-lg` popover · `--shadow-xl` modal/sheet · `--shadow-modal` modal full · `--shadow-inset` highlight no topo de elementos.
|
|
92
|
+
|
|
93
|
+
Focus ring: sempre `--ring-focus` em qualquer elemento interativo recebendo foco via teclado.
|
|
94
|
+
|
|
95
|
+
### 2.8 Motion
|
|
96
|
+
|
|
97
|
+
`--t-fast` (120ms) hover de botão · `--t-base` (180ms) padrão · `--t-slow` (280ms) sheets/modals abrindo · `--t-slower` (420ms) transições maiores.
|
|
98
|
+
|
|
99
|
+
Easings: `--ease-out` (saída natural, default), `--ease-in-out` (transitions complexas), `--ease-spring` (microinteractions playful, evite em UI sério).
|
|
100
|
+
|
|
101
|
+
### 2.9 Layout
|
|
102
|
+
|
|
103
|
+
`--sidebar-w` 240px · `--topbar-h` 56px · `--container-max` 1280px.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 3. Tema dark/light
|
|
108
|
+
|
|
109
|
+
`tokens.css` define light por padrão. Dark mode ativado de duas formas:
|
|
110
|
+
|
|
111
|
+
1. **Manual / opt-in:** `<html data-theme="dark">` — controla via JS/setting do user
|
|
112
|
+
2. **Automático via OS:** `@media (prefers-color-scheme: dark)` aplica se `data-theme` não estiver setado pra `light`
|
|
113
|
+
|
|
114
|
+
**Implemente sempre o toggle**. Recomendação UX: salvar preferência em `localStorage` + respeitar OS por padrão.
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
// Exemplo de toggle (adapte pra stack)
|
|
118
|
+
const setTheme = (mode) => {
|
|
119
|
+
document.documentElement.dataset.theme = mode;
|
|
120
|
+
localStorage.setItem('zark-theme', mode);
|
|
121
|
+
};
|
|
122
|
+
const initTheme = () => {
|
|
123
|
+
const saved = localStorage.getItem('zark-theme');
|
|
124
|
+
if (saved) setTheme(saved);
|
|
125
|
+
// sem saved → respeita OS via @media query (não precisa setar)
|
|
126
|
+
};
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Brand:** `--ember-500` (`#f56f10`) é **inalterado** no dark — é assinatura ZARK. Os tons claros `--ember-50/100/200/300` invertem (viram escuros) pra servir de bg suave em cards dark.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 4. Primitivos (`primitives.jsx`)
|
|
134
|
+
|
|
135
|
+
Componentes atômicos. Adapte pra stack atual.
|
|
136
|
+
|
|
137
|
+
### 4.1 `Section` — bloco temático com eyebrow + título + descrição
|
|
138
|
+
Props: `eyebrow` (uppercase tracking-wide, font-display), `title`, `description`, `columns` (grid columns).
|
|
139
|
+
Padding vertical generoso (`--sp-32` top, `--sp-16` bottom).
|
|
140
|
+
|
|
141
|
+
### 4.2 `Panel` — card padrão
|
|
142
|
+
Props: `title`, `kicker` (uppercase pequena), `padded` (default true), `children`. Surface bg, hairline border, raio `--r-lg`, sombra `--shadow-sm`. Hover (em variante interativa): eleva pra `--shadow-md`.
|
|
143
|
+
|
|
144
|
+
### 4.3 `Spec` — linha label/value
|
|
145
|
+
Display flex space-between. Label em `--ink-400` `--fs-sm`. Value em `--ink-700` `--fw-medium`. Quando `mono` true, value usa `--font-mono` `--fs-md`. Use em painéis técnicos (config, specs, metadata).
|
|
146
|
+
|
|
147
|
+
### 4.4 `Button`
|
|
148
|
+
**Variantes:**
|
|
149
|
+
- `primary` — bg `--ember-500`, texto `--surface`, sombra leve. Hover: `--ember-600`.
|
|
150
|
+
- `secondary` (default) — bg `--surface`, texto `--ink-700`, border `--line-200`. Hover: bg `--canvas`.
|
|
151
|
+
- `ghost` — sem bg, sem border, texto `--ink-500`. Hover: bg `--canvas`.
|
|
152
|
+
- `danger` — bg `--danger-500`, texto white. Hover escurece.
|
|
153
|
+
- `link` — texto-only, ember underline no hover.
|
|
154
|
+
|
|
155
|
+
**Sizes:** `sm` (h 28px, px 10px, fs 12px) · `md` (h 32px, padrão) · `lg` (h 40px).
|
|
156
|
+
|
|
157
|
+
**Props extras:** `icon` (esquerda), `iconRight`, `full` (width 100%), `disabled` (opacity 0.5, cursor not-allowed).
|
|
158
|
+
|
|
159
|
+
**Focus:** sempre `--ring-focus` no foco via teclado. Nunca remover outline sem oferecer ring custom.
|
|
160
|
+
|
|
161
|
+
### 4.5 `Input`
|
|
162
|
+
Container com `icon` (esquerda) e `suffix` (direita opcional). Border `--line-200`, raio `--r-sm`, padding interno `--sp-8 --sp-10`. Focus: border `--ember-400` + `--ring-focus`. State `invalid`: border `--danger-500` + `--ring` em rgba danger. Mono via prop `mono` (font-mono).
|
|
163
|
+
|
|
164
|
+
### 4.6 `Tag`
|
|
165
|
+
Pill compacto. Tons: `default` (canvas/ink-500), `ember` (ember-100/ember-700), `success`, `warning`, `danger`, `info` (todos usando `--*-50` bg + `--*-700` fg). Sizes `sm`/`md`. Prop `square` muda raio pra `--r-xs`.
|
|
166
|
+
|
|
167
|
+
### 4.7 `Badge`
|
|
168
|
+
Contador pequeno (notificação). Pill, fs `--fs-2xs`, bg `--ember-500`, fg white. Variants tonais via `tone`.
|
|
169
|
+
|
|
170
|
+
### 4.8 `Toggle` (switch)
|
|
171
|
+
Container 40×24 (md), 32×20 (sm). Off: bg `--ink-200`. On: bg `--ember-500`. Knob bg white com sombra-xs. Animação: `--t-base ease-out` no knob translateX.
|
|
172
|
+
|
|
173
|
+
### 4.9 `Segmented`
|
|
174
|
+
Grupo de botões em pill (radio horizontal). Bg `--canvas`, item ativo: bg `--surface` + sombra-xs. Item inativo: text `--ink-400`. Transição `--t-fast`.
|
|
175
|
+
|
|
176
|
+
### 4.10 `Avatar`
|
|
177
|
+
Quadrado/círculo com inicial. Default 24px, bg `--ember-500`, fg white, fw 600. Prop `square` true → `--r-sm`, false → `--r-pill`.
|
|
178
|
+
|
|
179
|
+
### 4.11 `Kbd`
|
|
180
|
+
Tecla. `<kbd>` styled: bg `--canvas`, border `--line-200`, raio `--r-xs`, font-mono, fs `--fs-2xs`, padding `2px 6px`, sombra-inset.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 5. Componentes (`components.jsx`)
|
|
185
|
+
|
|
186
|
+
Mais complexos, compostos de primitivos.
|
|
187
|
+
|
|
188
|
+
### 5.1 Cards / Endpoint cards
|
|
189
|
+
Layout: ícone à esquerda, label heading + tag à direita, descrição abaixo. Use em listagens (API endpoints, integrações, plans).
|
|
190
|
+
|
|
191
|
+
### 5.2 Showcases (Buttons / Inputs / Tags)
|
|
192
|
+
Padrão de organização visual: linha (`ComponentRow`) com label sticky à esquerda + variantes lado a lado à direita. Use pra documentação interna do design system.
|
|
193
|
+
|
|
194
|
+
### 5.3 Sidebar item
|
|
195
|
+
Linha com ícone (16px), label, opcional `sub` (descrição menor cinza), opcional `kbd` (atalho). Estado active: bg `--canvas` + barra `--ember-500` à esquerda (3px width). Hover: bg `--line-100`.
|
|
196
|
+
|
|
197
|
+
### 5.4 Nav showcase
|
|
198
|
+
Demo de top nav: brand logo à esquerda, items centrais, ações à direita (search, avatar). Altura `--topbar-h`, border-bottom `--line-200`.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 6. Layouts (`layouts.jsx`)
|
|
203
|
+
|
|
204
|
+
### 6.1 `HeaderBar`
|
|
205
|
+
Topo fixo, altura 56px, bg `--surface`, border-bottom `--line-200`. Contém: brand (esquerda), nav (centro), search + avatar (direita).
|
|
206
|
+
|
|
207
|
+
### 6.2 `Sidebar`
|
|
208
|
+
Lateral 240px, bg `--canvas`, border-right `--line-200`. Contém: brand, search input, list de items agrupados por section (uppercase eyebrow `--ink-400` `--fs-2xs` tracking-wider).
|
|
209
|
+
|
|
210
|
+
### 6.3 `DashboardLayout`
|
|
211
|
+
Composição: HeaderBar + Sidebar + main content area. Main: padding `--sp-24`, max-width opcional `--container-max`.
|
|
212
|
+
|
|
213
|
+
### 6.4 `HeroLayout`
|
|
214
|
+
Marketing/landing. Centered text (max-width 720px), título font-display `--fs-5xl/6xl`, kicker em ember pequeno uppercase, CTA primary + secondary side-by-side abaixo.
|
|
215
|
+
|
|
216
|
+
### 6.5 `PlaygroundLayout`
|
|
217
|
+
Demo interativo. Painel esquerdo (controls/inputs), painel direito (preview). Divisor vertical hairline.
|
|
218
|
+
|
|
219
|
+
### 6.6 `FooterShowcase`
|
|
220
|
+
Footer mínimo: 4 colunas de links com headings + brand+copy à esquerda. bg `--canvas`, border-top `--line-200`.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## 7. Patterns (`patterns.jsx`)
|
|
225
|
+
|
|
226
|
+
### 7.1 Modal
|
|
227
|
+
Overlay `rgba(20,17,12,0.6)` (light) ou `rgba(0,0,0,0.7)` (dark). Modal: max-width 480px, raio `--r-xl`, sombra `--shadow-modal`. Header: título + close icon. Body. Footer: botões à direita.
|
|
228
|
+
|
|
229
|
+
### 7.2 CodeBlock
|
|
230
|
+
Bg `--code-bg`, fg `--code-fg`, raio `--r-md`, padding `--sp-12`, font-mono `--fs-md`. Copy button no canto top-right (ghost size sm). Use `<pre><code>`.
|
|
231
|
+
|
|
232
|
+
### 7.3 DataTable
|
|
233
|
+
Header: bg `--canvas`, fs `--fs-sm`, fw `--fw-medium`, uppercase letter-spacing-wide, padding `--sp-8 --sp-12`. Row: hover bg `--line-100`. Cell: fs `--fs-md`, padding `--sp-10 --sp-12`. Border-bottom `--line-200` em todas as rows. Selected row: bg `--ember-50` + border-left 2px `--ember-500`.
|
|
234
|
+
|
|
235
|
+
### 7.4 DatePicker
|
|
236
|
+
Calendar grid 7×6, dias 32px square. Today: dot ember abaixo. Selected: bg `--ember-500` text white. Hover: bg `--canvas`. Range: bg `--ember-50` (entre datas), endpoints bg `--ember-500`.
|
|
237
|
+
|
|
238
|
+
### 7.5 Banner
|
|
239
|
+
Tons: `info` (info-50 bg, info-700 fg), `success`, `warning`, `danger`. Layout: ícone + texto + close X opcional + CTA opcional à direita. Padding `--sp-12 --sp-16`. Border-left 3px na cor do tom.
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## 8. Brand (`brand.jsx`)
|
|
244
|
+
|
|
245
|
+
### 8.1 ZarkLogo
|
|
246
|
+
Variants: `full` (icon + wordmark) · `mark` (só ícone) · `wordmark` (só texto). Default size 28px. Usa font-display Darker Grotesque para wordmark.
|
|
247
|
+
|
|
248
|
+
### 8.2 AsciiBackdrop / AsciiCurve
|
|
249
|
+
Background decorativo retro. ASCII chars em `--ink-200` opacity 0.55 num grid. Use em hero sections, login screens, brand moments. Não usar em UI funcional.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 9. Iconografia (`icons.jsx`)
|
|
254
|
+
|
|
255
|
+
**Padrão**: outline, stroke 1.5px, viewBox 18×18, `currentColor`. Tamanhos: 14 (denso), 16 (default), 18 (botão), 20 (header), 24 (display).
|
|
256
|
+
|
|
257
|
+
Evite ícones preenchidos (filled) salvo em badge/notificação. Mantenha consistência: se um ícone é outline, todos os outros na mesma linha visual também são.
|
|
258
|
+
|
|
259
|
+
Quando precisar de ícone que não existe: criar seguindo as mesmas regras (1.5px stroke, 18 viewBox), ou usar lucide-icons (que segue padrão similar).
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 10. Como aplicar em qualquer stack
|
|
264
|
+
|
|
265
|
+
### Workflow recomendado pra IA
|
|
266
|
+
|
|
267
|
+
1. **Importar tokens.css** no entry-point do projeto (ex: `src/styles/global.css` em Next, `app.css` em Laravel, `static/css/zark.css` em Django).
|
|
268
|
+
2. **Identificar a unidade equivalente na stack alvo** — em React: componente .jsx; em Vue: .vue; em Blade: partial `.blade.php`; em Django: `{% include %}` template; em HTML/Tailwind: classe utility.
|
|
269
|
+
3. **Reler a definição do primitivo no JSX** + olhar o PNG correspondente em `visual-references/`.
|
|
270
|
+
4. **Implementar usando vars CSS** — `var(--ember-500)`, `var(--paper)` etc. Nunca hardcode `#f56f10` no código stack-side.
|
|
271
|
+
5. **Variantes via prop ou data-attribute** (`data-variant="primary"`), nunca via classe utility crua sem semântica.
|
|
272
|
+
6. **Testar light + dark** com `<html data-theme="dark">`.
|
|
273
|
+
7. **Ajustar tipografia/spacing** seguindo escala dos tokens (`--sp-*`, `--fs-*`).
|
|
274
|
+
|
|
275
|
+
### Exemplos de tradução
|
|
276
|
+
|
|
277
|
+
**JSX (referência)**:
|
|
278
|
+
```jsx
|
|
279
|
+
<button style={{
|
|
280
|
+
background: 'var(--ember-500)',
|
|
281
|
+
color: 'var(--surface)',
|
|
282
|
+
height: 32, padding: '0 14px',
|
|
283
|
+
borderRadius: 'var(--r-sm)',
|
|
284
|
+
fontWeight: 500
|
|
285
|
+
}}>Save</button>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Tailwind + CSS vars** (recomendado):
|
|
289
|
+
```html
|
|
290
|
+
<button class="h-8 px-3.5 rounded font-medium" style="background: var(--ember-500); color: var(--surface);">Save</button>
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Vue 3**:
|
|
294
|
+
```vue
|
|
295
|
+
<template>
|
|
296
|
+
<button :class="['btn', `btn-${variant}`]"><slot /></button>
|
|
297
|
+
</template>
|
|
298
|
+
<style scoped>
|
|
299
|
+
.btn-primary { background: var(--ember-500); color: var(--surface); }
|
|
300
|
+
</style>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Laravel Blade**:
|
|
304
|
+
```php
|
|
305
|
+
<button {{ $attributes->merge(['class' => 'zk-btn zk-btn-primary']) }}>
|
|
306
|
+
{{ $slot }}
|
|
307
|
+
</button>
|
|
308
|
+
```
|
|
309
|
+
+ `zk-btn-primary` no CSS global usando vars.
|
|
310
|
+
|
|
311
|
+
**Django template**:
|
|
312
|
+
```django
|
|
313
|
+
{% include "components/button.html" with variant="primary" label="Save" %}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**HTML puro**:
|
|
317
|
+
```html
|
|
318
|
+
<button style="background: var(--ember-500); color: var(--surface); height: 32px; padding: 0 14px; border-radius: var(--r-sm); font-weight: 500;">
|
|
319
|
+
Save
|
|
320
|
+
</button>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Checklist quando implementar uma tela
|
|
324
|
+
|
|
325
|
+
- [ ] `tokens.css` importado no entry-point
|
|
326
|
+
- [ ] Toggle de tema (light/dark) implementado
|
|
327
|
+
- [ ] Tipografia: Inter carregado (Google Fonts ou self-hosted), fallback `-apple-system`
|
|
328
|
+
- [ ] Cores: nenhum hex hardcoded — tudo via `var(--...)`
|
|
329
|
+
- [ ] Spacing: usando escala `--sp-*`, sem números mágicos
|
|
330
|
+
- [ ] Hairlines (1px) em vez de borders grossos
|
|
331
|
+
- [ ] Focus visível em todo elemento interativo (`--ring-focus`)
|
|
332
|
+
- [ ] Microinterações em `--t-fast` (120ms) ou `--t-base` (180ms)
|
|
333
|
+
- [ ] Brand `--ember-500` usado com moderação (CTAs, focus, brand moments)
|
|
334
|
+
- [ ] Conferiu visualmente contra `visual-references/*.png` correspondente
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## 11. O que NÃO fazer
|
|
339
|
+
|
|
340
|
+
- ❌ Trocar a cor de marca por outra. Ember `#f56f10` é assinatura.
|
|
341
|
+
- ❌ Usar `border: 1px solid black` quando o token é `--line-200`.
|
|
342
|
+
- ❌ Hardcode de cor (`#fafaf8` etc) — sempre use vars.
|
|
343
|
+
- ❌ Sombras frias `rgba(0,0,0,...)` — use as warm `rgba(20,17,12,...)`.
|
|
344
|
+
- ❌ Border-radius inconsistente — use a escala (`--r-sm` em forms, `--r-lg` em cards).
|
|
345
|
+
- ❌ Tipografia fora da escala (`13.5px` etc).
|
|
346
|
+
- ❌ Display font (Darker Grotesque) em UI texto — só hero/marketing.
|
|
347
|
+
- ❌ Animação > 280ms em microinterações.
|
|
348
|
+
- ❌ Brand color como bg dominante de tela inteira.
|
|
349
|
+
- ❌ Substituir Inter por outra fonte sans sem justificativa documentada.
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## 12. Arquivos neste diretório
|
|
354
|
+
|
|
355
|
+
| Arquivo | Conteúdo |
|
|
356
|
+
|---|---|
|
|
357
|
+
| `REFERENCE.md` | Este documento (cérebro do sistema) |
|
|
358
|
+
| `tokens.css` | Todas as variáveis CSS (light + dark) |
|
|
359
|
+
| `primitives.jsx` | Section, Panel, Spec, Button, Input, Tag, Badge, Toggle, Segmented, Avatar, Kbd |
|
|
360
|
+
| `components.jsx` | Cards, Showcases, SidebarItem, NavShowcase |
|
|
361
|
+
| `layouts.jsx` | HeaderBar, Sidebar, DashboardLayout, HeroLayout, PlaygroundLayout, FooterShowcase |
|
|
362
|
+
| `patterns.jsx` | Modal, CodeBlock, DataTable, DatePicker, Banner |
|
|
363
|
+
| `brand.jsx` | ZarkLogo, AsciiBackdrop, AsciiCurve |
|
|
364
|
+
| `foundations.jsx` | Tipografia/escala/cores em formato visual |
|
|
365
|
+
| `icons.jsx` | Set de ícones outline 18px |
|
|
366
|
+
| `design-canvas.jsx` | Figma-like canvas wrapper (referência de organização interna do design) |
|
|
367
|
+
| `SHOWCASE.html` | Renderização offline do design system (abra no browser) |
|
|
368
|
+
| `visual-references/*.png` | Screenshots originais da composição — ground truth visual |
|
|
369
|
+
| `assets/` | Logo + ícone ZARK |
|
|
370
|
+
|
|
371
|
+
**Quando dúvida sobre aparência exata** → abra `SHOWCASE.html` no browser ou os PNGs em `visual-references/`.
|
|
372
|
+
**Quando dúvida sobre comportamento** → reler o componente correspondente em `.jsx` (estrutura) + esta referência (semântica).
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
*Versão deste documento: 1.0 — gerado por `npx zark-design init`. Mantido em <https://github.com/mayconjordanr/zark-design>.*
|