@stacklist-app/brandkit 1.1.1 → 1.2.1
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 +37 -11
- package/bin/brandkit.js +4 -0
- package/cli/build.js +7 -2
- package/cli/export.js +64 -0
- package/cli/generate.js +35 -1
- package/cli/init.js +16 -0
- package/config.schema.json +253 -0
- package/dist/engine.js +49 -13
- package/dist/logos/brandkit-mark-white.svg +8 -0
- package/dist/logos/brandkit-mark.svg +14 -0
- package/dist/logos/brandkit-wordmark-dark.svg +15 -0
- package/dist/logos/brandkit-wordmark-light.svg +9 -0
- package/dist/styles.css +113 -30
- package/integrations/vite.js +20 -1
- package/lib/config-schema.js +124 -78
- package/lib/export.js +356 -0
- package/lib/extract-css.js +1 -1
- package/lib/generate-helpers.js +1 -1
- package/lib/template.js +26 -7
- package/package.json +3 -2
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="324" height="96" viewBox="0 0 324 96" role="img" aria-label="brandkit">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bk-wm-grad" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#4F46E5"/>
|
|
5
|
+
<stop offset="1" stop-color="#7C3AED"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<rect x="0" y="8" width="80" height="80" rx="19" fill="url(#bk-wm-grad)"/>
|
|
9
|
+
<g fill="#FFFFFF">
|
|
10
|
+
<rect x="22" y="31" width="36" height="9" rx="4.5"/>
|
|
11
|
+
<rect x="22" y="44" width="36" height="9" rx="4.5" opacity="0.82"/>
|
|
12
|
+
<rect x="22" y="57" width="23" height="9" rx="4.5" opacity="0.64"/>
|
|
13
|
+
</g>
|
|
14
|
+
<text x="100" y="61" font-family="'Space Grotesk', 'Helvetica Neue', Arial, sans-serif" font-size="46" font-weight="600" letter-spacing="-1.5" fill="#111827">brandkit</text>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="324" height="96" viewBox="0 0 324 96" role="img" aria-label="brandkit, reversed">
|
|
2
|
+
<rect x="1" y="9" width="78" height="78" rx="18" fill="none" stroke="#FFFFFF" stroke-width="2.5"/>
|
|
3
|
+
<g fill="#FFFFFF">
|
|
4
|
+
<rect x="22" y="31" width="36" height="9" rx="4.5"/>
|
|
5
|
+
<rect x="22" y="44" width="36" height="9" rx="4.5" opacity="0.82"/>
|
|
6
|
+
<rect x="22" y="57" width="23" height="9" rx="4.5" opacity="0.64"/>
|
|
7
|
+
</g>
|
|
8
|
+
<text x="100" y="61" font-family="'Space Grotesk', 'Helvetica Neue', Arial, sans-serif" font-size="46" font-weight="600" letter-spacing="-1.5" fill="#FFFFFF">brandkit</text>
|
|
9
|
+
</svg>
|
package/dist/styles.css
CHANGED
|
@@ -4,6 +4,73 @@
|
|
|
4
4
|
CSS custom properties injected by engine.js from config.json.
|
|
5
5
|
═══════════════════════════════════════════════════════════════════ */
|
|
6
6
|
|
|
7
|
+
/* ───────────────────────────────────────────────────────────────────
|
|
8
|
+
Default tokens — a config only needs to OVERRIDE these.
|
|
9
|
+
This stylesheet consumes every variable below; shipping defaults here
|
|
10
|
+
means a minimal or ported config never renders broken (invisible
|
|
11
|
+
buttons, colorless code, system fonts, transparent tints).
|
|
12
|
+
|
|
13
|
+
The injected config.theme (dev) and the generated :root (build) both
|
|
14
|
+
cascade AFTER this block, so any token a config sets wins.
|
|
15
|
+
|
|
16
|
+
Backward compatibility: pre-1.1.2 configs set --purple / --purple-rgb.
|
|
17
|
+
Those feed --accent / --accent-rgb below, so old configs keep working
|
|
18
|
+
without setting the new accent tokens.
|
|
19
|
+
─────────────────────────────────────────────────────────────────── */
|
|
20
|
+
:root {
|
|
21
|
+
/* Surfaces & ink */
|
|
22
|
+
--white: #FFFFFF;
|
|
23
|
+
--cloud: #F9FAFB;
|
|
24
|
+
--mist: #F3F4F6;
|
|
25
|
+
--haze: #D1D5DB;
|
|
26
|
+
--slate: #6B7280;
|
|
27
|
+
--graphite: #374151;
|
|
28
|
+
--ink: #111827;
|
|
29
|
+
--ink-rgb: 17, 24, 39;
|
|
30
|
+
|
|
31
|
+
/* Fonts (overridden per-brand from config.fonts) */
|
|
32
|
+
--font-display: 'Inter', sans-serif;
|
|
33
|
+
--font-body: 'Inter', sans-serif;
|
|
34
|
+
|
|
35
|
+
/* Accent — fill vs. text split (Material/shadcn "on-color" convention)
|
|
36
|
+
--accent the fill color (buttons, active chips)
|
|
37
|
+
--accent-foreground text/icon color ON the fill (must pass on --accent)
|
|
38
|
+
--accent-text the accent used AS text/links on a light surface */
|
|
39
|
+
--accent: var(--purple, #6366F1);
|
|
40
|
+
--accent-rgb: var(--purple-rgb, 99, 102, 241);
|
|
41
|
+
--accent-foreground: #FFFFFF;
|
|
42
|
+
--accent-text: var(--accent);
|
|
43
|
+
|
|
44
|
+
/* Primary action — the fill for primary buttons / CTAs.
|
|
45
|
+
Defaults to the accent, so single-accent brands are unchanged. Brands that
|
|
46
|
+
separate the primary action from the accent (e.g. a black CTA with an orange
|
|
47
|
+
accent) override --primary / --primary-foreground. */
|
|
48
|
+
--primary: var(--accent);
|
|
49
|
+
--primary-foreground: var(--accent-foreground);
|
|
50
|
+
|
|
51
|
+
/* Gradients */
|
|
52
|
+
--gradient-brand: linear-gradient(135deg, #4338CA 0%, #6366F1 50%, #EC4899 100%);
|
|
53
|
+
--gradient-brand-subtle: linear-gradient(135deg, rgba(99, 102, 241, 0.06) 0%, rgba(236, 72, 153, 0.06) 100%);
|
|
54
|
+
|
|
55
|
+
/* Header background — the hero block behind the wordmark/logo.
|
|
56
|
+
Defaults to the brand gradient; override (e.g. a flat dark color) for a
|
|
57
|
+
hero that shouldn't carry the accent. */
|
|
58
|
+
--header-bg: var(--gradient-brand);
|
|
59
|
+
|
|
60
|
+
/* Semantic */
|
|
61
|
+
--success: #10B981;
|
|
62
|
+
--success-rgb: 16, 185, 129;
|
|
63
|
+
--warning: #F59E0B;
|
|
64
|
+
--error: #EF4444;
|
|
65
|
+
--error-rgb: 239, 68, 68;
|
|
66
|
+
|
|
67
|
+
/* Extended palette (coral accents, code-syntax highlight) */
|
|
68
|
+
--coral: #F87171;
|
|
69
|
+
--coral-dark: #DC2626;
|
|
70
|
+
--coral-light: #FCA5A5;
|
|
71
|
+
--lavender: #A5B4FC;
|
|
72
|
+
}
|
|
73
|
+
|
|
7
74
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
8
75
|
|
|
9
76
|
body {
|
|
@@ -33,12 +100,20 @@ body {
|
|
|
33
100
|
font-family: var(--font-display), sans-serif;
|
|
34
101
|
font-size: 18px;
|
|
35
102
|
font-weight: 700;
|
|
36
|
-
color: var(--
|
|
103
|
+
color: var(--accent-text);
|
|
37
104
|
padding: 0 24px;
|
|
38
105
|
margin-bottom: 32px;
|
|
39
106
|
letter-spacing: -0.02em;
|
|
40
107
|
}
|
|
41
108
|
|
|
109
|
+
/* Optional logo image in the sidebar top (brand.sidebarLogo) */
|
|
110
|
+
.sidebar-logo {
|
|
111
|
+
display: block;
|
|
112
|
+
max-height: 28px;
|
|
113
|
+
max-width: 100%;
|
|
114
|
+
width: auto;
|
|
115
|
+
}
|
|
116
|
+
|
|
42
117
|
.sidebar-nav { list-style: none; }
|
|
43
118
|
|
|
44
119
|
.sidebar-nav a {
|
|
@@ -52,7 +127,7 @@ body {
|
|
|
52
127
|
}
|
|
53
128
|
|
|
54
129
|
.sidebar-nav a:hover { color: var(--ink); background: var(--cloud); }
|
|
55
|
-
.sidebar-nav a.active { color: var(--
|
|
130
|
+
.sidebar-nav a.active { color: var(--accent-text); border-left-color: var(--accent-text); background: rgba(var(--accent-rgb), 0.04); font-weight: 500; }
|
|
56
131
|
|
|
57
132
|
/* ── Sidebar Grouped Navigation ── */
|
|
58
133
|
.nav-group {
|
|
@@ -86,7 +161,7 @@ body {
|
|
|
86
161
|
}
|
|
87
162
|
|
|
88
163
|
.nav-group-items a:hover { color: var(--ink); background: var(--cloud); }
|
|
89
|
-
.nav-group-items a.active { color: var(--
|
|
164
|
+
.nav-group-items a.active { color: var(--accent-text); border-left-color: var(--accent-text); background: rgba(var(--accent-rgb), 0.04); font-weight: 500; }
|
|
90
165
|
|
|
91
166
|
.main { margin-left: 200px; flex: 1; }
|
|
92
167
|
|
|
@@ -126,8 +201,8 @@ body {
|
|
|
126
201
|
}
|
|
127
202
|
|
|
128
203
|
.copy-format-bar button.active {
|
|
129
|
-
background: var(--
|
|
130
|
-
color: var(--
|
|
204
|
+
background: var(--accent);
|
|
205
|
+
color: var(--accent-foreground);
|
|
131
206
|
}
|
|
132
207
|
|
|
133
208
|
.copy-format-bar button:hover:not(.active) { background: var(--cloud); }
|
|
@@ -168,7 +243,7 @@ body {
|
|
|
168
243
|
|
|
169
244
|
/* ── Header ── */
|
|
170
245
|
.header {
|
|
171
|
-
background: var(--
|
|
246
|
+
background: var(--header-bg);
|
|
172
247
|
border-radius: 24px;
|
|
173
248
|
padding: 64px 56px;
|
|
174
249
|
margin-bottom: 72px;
|
|
@@ -209,6 +284,14 @@ body {
|
|
|
209
284
|
z-index: 1;
|
|
210
285
|
}
|
|
211
286
|
|
|
287
|
+
/* Optional logo image in the header (brand.headerLogo) */
|
|
288
|
+
.header-logo {
|
|
289
|
+
display: block;
|
|
290
|
+
max-height: 56px;
|
|
291
|
+
max-width: 100%;
|
|
292
|
+
width: auto;
|
|
293
|
+
}
|
|
294
|
+
|
|
212
295
|
/* ── Section ── */
|
|
213
296
|
.section { margin-bottom: 72px; scroll-margin-top: 24px; }
|
|
214
297
|
|
|
@@ -293,7 +376,7 @@ body {
|
|
|
293
376
|
padding: 2px 0;
|
|
294
377
|
}
|
|
295
378
|
|
|
296
|
-
.color-value:hover { color: var(--
|
|
379
|
+
.color-value:hover { color: var(--accent-text); }
|
|
297
380
|
|
|
298
381
|
.color-role { font-size: 11px; color: var(--haze); margin-top: 2px; }
|
|
299
382
|
|
|
@@ -428,9 +511,9 @@ body {
|
|
|
428
511
|
font-family: var(--font-body), sans-serif;
|
|
429
512
|
font-size: 12px;
|
|
430
513
|
font-weight: 500;
|
|
431
|
-
color: var(--
|
|
432
|
-
background: rgba(var(--
|
|
433
|
-
border: 1px solid rgba(var(--
|
|
514
|
+
color: var(--accent-text);
|
|
515
|
+
background: rgba(var(--accent-rgb), 0.06);
|
|
516
|
+
border: 1px solid rgba(var(--accent-rgb), 0.15);
|
|
434
517
|
border-radius: 6px;
|
|
435
518
|
padding: 4px 8px;
|
|
436
519
|
cursor: pointer;
|
|
@@ -488,7 +571,7 @@ body {
|
|
|
488
571
|
.hierarchy-demo .h-primary { font-size: 15px; color: var(--ink); line-height: 1.7; margin-bottom: 14px; }
|
|
489
572
|
.hierarchy-demo .h-secondary { font-size: 15px; color: var(--graphite); line-height: 1.7; margin-bottom: 14px; }
|
|
490
573
|
.hierarchy-demo .h-tertiary { font-size: 13px; color: var(--slate); line-height: 1.6; margin-bottom: 14px; }
|
|
491
|
-
.hierarchy-demo .h-accent { font-size: 15px; font-weight: 500; color: var(--
|
|
574
|
+
.hierarchy-demo .h-accent { font-size: 15px; font-weight: 500; color: var(--accent-text); }
|
|
492
575
|
|
|
493
576
|
.hierarchy-labels { display: flex; gap: 28px; flex-wrap: wrap; }
|
|
494
577
|
|
|
@@ -512,8 +595,8 @@ body {
|
|
|
512
595
|
|
|
513
596
|
.wordmark-box.on-gradient { background: var(--gradient-brand); color: var(--white); }
|
|
514
597
|
.wordmark-box.on-dark { background: var(--ink); color: var(--white); }
|
|
515
|
-
.wordmark-box.on-light { background: var(--mist); color: var(--
|
|
516
|
-
.wordmark-box.on-white { background: var(--white); color: var(--
|
|
598
|
+
.wordmark-box.on-light { background: var(--mist); color: var(--accent-text); }
|
|
599
|
+
.wordmark-box.on-white { background: var(--white); color: var(--accent-text); box-shadow: inset 0 0 0 1px rgba(var(--ink-rgb), 0.08); }
|
|
517
600
|
|
|
518
601
|
.wordmark-note { font-size: 12px; color: var(--slate); text-align: center; margin-top: 6px; }
|
|
519
602
|
|
|
@@ -607,8 +690,8 @@ body {
|
|
|
607
690
|
}
|
|
608
691
|
|
|
609
692
|
.logo-format-toggle button.active {
|
|
610
|
-
background: var(--
|
|
611
|
-
color: var(--
|
|
693
|
+
background: var(--accent);
|
|
694
|
+
color: var(--accent-foreground);
|
|
612
695
|
}
|
|
613
696
|
|
|
614
697
|
.logo-format-toggle button:hover:not(.active) {
|
|
@@ -627,8 +710,8 @@ body {
|
|
|
627
710
|
}
|
|
628
711
|
|
|
629
712
|
.logo-card.bg-light .logo-format-toggle button.active {
|
|
630
|
-
background: var(--
|
|
631
|
-
color: var(--
|
|
713
|
+
background: var(--accent);
|
|
714
|
+
color: var(--accent-foreground);
|
|
632
715
|
}
|
|
633
716
|
|
|
634
717
|
.logo-card.bg-light .logo-format-toggle button:hover:not(.active) {
|
|
@@ -682,8 +765,8 @@ body {
|
|
|
682
765
|
color: var(--slate);
|
|
683
766
|
}
|
|
684
767
|
.logo-card.on-light .logo-format-toggle button.active {
|
|
685
|
-
background: var(--
|
|
686
|
-
color: var(--
|
|
768
|
+
background: var(--accent);
|
|
769
|
+
color: var(--accent-foreground);
|
|
687
770
|
}
|
|
688
771
|
.logo-card.on-light .logo-format-toggle button:hover:not(.active) {
|
|
689
772
|
background: var(--cloud);
|
|
@@ -696,7 +779,7 @@ body {
|
|
|
696
779
|
.logo-card.on-light .logo-download-btn {
|
|
697
780
|
border-color: var(--haze);
|
|
698
781
|
background: transparent;
|
|
699
|
-
color: var(--
|
|
782
|
+
color: var(--accent-text);
|
|
700
783
|
}
|
|
701
784
|
.logo-card.on-light .logo-download-btn:hover {
|
|
702
785
|
background: var(--cloud);
|
|
@@ -727,11 +810,11 @@ body {
|
|
|
727
810
|
.logo-card.bg-light .logo-download-btn {
|
|
728
811
|
border-color: var(--haze);
|
|
729
812
|
background: transparent;
|
|
730
|
-
color: var(--
|
|
813
|
+
color: var(--accent-text);
|
|
731
814
|
}
|
|
732
815
|
|
|
733
816
|
.logo-card.bg-light .logo-download-btn:hover {
|
|
734
|
-
background: rgba(var(--
|
|
817
|
+
background: rgba(var(--accent-rgb), 0.06);
|
|
735
818
|
}
|
|
736
819
|
|
|
737
820
|
/* ── Voice ── */
|
|
@@ -759,7 +842,7 @@ body {
|
|
|
759
842
|
color: var(--ink);
|
|
760
843
|
margin-bottom: 10px;
|
|
761
844
|
padding-left: 16px;
|
|
762
|
-
border-left: 2px solid rgba(var(--
|
|
845
|
+
border-left: 2px solid rgba(var(--accent-rgb), 0.2);
|
|
763
846
|
}
|
|
764
847
|
|
|
765
848
|
.voice-example:last-child { margin-bottom: 0; }
|
|
@@ -792,11 +875,11 @@ body {
|
|
|
792
875
|
.btn-sm { height: 32px; padding: 0 16px; font-size: 13px; border-radius: 9999px; }
|
|
793
876
|
.btn-md { height: 40px; padding: 0 24px; font-size: 14px; border-radius: 9999px; }
|
|
794
877
|
.btn-lg { height: 48px; padding: 0 28px; font-size: 16px; border-radius: 9999px; }
|
|
795
|
-
.btn-primary { background: var(--
|
|
796
|
-
.btn-primary:hover {
|
|
878
|
+
.btn-primary { background: var(--primary); color: var(--primary-foreground); }
|
|
879
|
+
.btn-primary:hover { filter: brightness(0.9); }
|
|
797
880
|
.btn-secondary { background: var(--mist); color: var(--ink); }
|
|
798
|
-
.btn-secondary:hover {
|
|
799
|
-
.btn-ghost { background: transparent; color: var(--
|
|
881
|
+
.btn-secondary:hover { filter: brightness(0.96); }
|
|
882
|
+
.btn-ghost { background: transparent; color: var(--accent-text); border: 1px solid var(--haze); }
|
|
800
883
|
.btn-ghost:hover { background: var(--cloud); }
|
|
801
884
|
.btn-gradient { background: var(--gradient-brand); color: var(--white); }
|
|
802
885
|
.btn-gradient:hover { opacity: 0.9; }
|
|
@@ -827,8 +910,8 @@ body {
|
|
|
827
910
|
font-weight: 500;
|
|
828
911
|
padding: 3px 10px;
|
|
829
912
|
border-radius: 9999px;
|
|
830
|
-
background: rgba(var(--
|
|
831
|
-
color: var(--
|
|
913
|
+
background: rgba(var(--accent-rgb), 0.08);
|
|
914
|
+
color: var(--accent-text);
|
|
832
915
|
}
|
|
833
916
|
|
|
834
917
|
.dark-card-demo { background: var(--ink); border-radius: 20px; padding: 36px; margin-top: 20px; }
|
|
@@ -915,7 +998,7 @@ body {
|
|
|
915
998
|
|
|
916
999
|
.a11y-badge.pass { background: rgba(var(--success-rgb), 0.15); color: var(--success); }
|
|
917
1000
|
.a11y-badge.fail { background: rgba(var(--error-rgb), 0.12); color: var(--error); }
|
|
918
|
-
.a11y-badge.large { background: rgba(var(--
|
|
1001
|
+
.a11y-badge.large { background: rgba(var(--accent-rgb), 0.12); color: var(--accent-text); }
|
|
919
1002
|
|
|
920
1003
|
/* ── Code Block ── */
|
|
921
1004
|
.code-block {
|
package/integrations/vite.js
CHANGED
|
@@ -52,7 +52,6 @@ module.exports = function brandkitVite(options) {
|
|
|
52
52
|
},
|
|
53
53
|
|
|
54
54
|
closeBundle: function () {
|
|
55
|
-
// Copy brand directory to build output
|
|
56
55
|
var srcDir = path.resolve(brandDir);
|
|
57
56
|
if (!fs.existsSync(srcDir)) return;
|
|
58
57
|
|
|
@@ -61,7 +60,27 @@ module.exports = function brandkitVite(options) {
|
|
|
61
60
|
fs.mkdirSync(outDir, { recursive: true });
|
|
62
61
|
}
|
|
63
62
|
|
|
63
|
+
// Copy assets (config.json, logos, anything in brand/) to the output.
|
|
64
64
|
copyDir(srcDir, outDir);
|
|
65
|
+
|
|
66
|
+
// Then produce a real production build into the output: theme baked into
|
|
67
|
+
// styles.css, engine.js copied, and the agent-native exports written +
|
|
68
|
+
// embedded in index.html. This makes the deployed /brand carry brand.json,
|
|
69
|
+
// tokens.json, brand.md and the inline <script id="brandkit-brand"> — so an
|
|
70
|
+
// agent pointed at the URL gets structured brand data without a manual
|
|
71
|
+
// `brandkit build` step. Falls back to the raw copy if config is missing.
|
|
72
|
+
var configPath = path.join(srcDir, 'config.json');
|
|
73
|
+
if (fs.existsSync(configPath)) {
|
|
74
|
+
try {
|
|
75
|
+
var config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
76
|
+
var template = require('../lib/template');
|
|
77
|
+
var resolve = require('../lib/resolve');
|
|
78
|
+
template.build(resolve.getDistPath(), outDir, config);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
// Leave the raw copy in place; don't fail the host build, but say why.
|
|
81
|
+
console.warn('[brandkit] agent-export step skipped: ' + e.message);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
65
84
|
}
|
|
66
85
|
};
|
|
67
86
|
};
|