@hewnui/themes 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +33 -2
- package/dist/authoring/css-vars.d.ts +10 -0
- package/dist/authoring/css-vars.js +83 -0
- package/dist/authoring/derive.d.ts +9 -0
- package/dist/authoring/derive.js +79 -0
- package/dist/authoring/export-css.d.ts +8 -0
- package/dist/authoring/export-css.js +60 -0
- package/dist/authoring/export-design-md.d.ts +5 -0
- package/dist/authoring/export-design-md.js +113 -0
- package/dist/authoring/export-dtcg.d.ts +6 -0
- package/dist/authoring/export-dtcg.js +85 -0
- package/dist/authoring/export-figma.d.ts +27 -0
- package/dist/authoring/export-figma.js +76 -0
- package/dist/authoring/export-formats.d.ts +27 -0
- package/dist/authoring/export-formats.js +62 -0
- package/dist/authoring/export-skill.d.ts +5 -0
- package/dist/authoring/export-skill.js +75 -0
- package/dist/authoring/export-sticker.d.ts +6 -0
- package/dist/authoring/export-sticker.js +54 -0
- package/dist/authoring/export-style-dictionary.d.ts +3 -0
- package/dist/authoring/export-style-dictionary.js +52 -0
- package/dist/authoring/figma-kit.d.ts +16 -0
- package/dist/authoring/figma-kit.js +41 -0
- package/dist/authoring/index.d.ts +21 -0
- package/dist/authoring/index.js +18 -0
- package/dist/authoring/oklch.d.ts +11 -0
- package/dist/authoring/oklch.js +116 -0
- package/dist/authoring/override-map.d.ts +9 -0
- package/dist/authoring/override-map.js +150 -0
- package/dist/authoring/pack-def.d.ts +7 -0
- package/dist/authoring/pack-def.js +3 -0
- package/dist/authoring/pack-meta.d.ts +10 -0
- package/dist/authoring/pack-meta.js +58 -0
- package/dist/authoring/packs-dual.d.ts +129 -0
- package/dist/authoring/packs-dual.js +130 -0
- package/dist/authoring/packs-single.d.ts +87 -0
- package/dist/authoring/packs-single.js +88 -0
- package/dist/authoring/packs.d.ts +8 -0
- package/dist/authoring/packs.js +26 -0
- package/dist/authoring/pro-apply.d.ts +8 -0
- package/dist/authoring/pro-apply.js +107 -0
- package/dist/authoring/propose.d.ts +21 -0
- package/dist/authoring/propose.js +162 -0
- package/dist/authoring/ramps.d.ts +13 -0
- package/dist/authoring/ramps.js +40 -0
- package/dist/authoring/status-ramps.d.ts +13 -0
- package/dist/authoring/status-ramps.js +76 -0
- package/dist/authoring/token-entries.d.ts +10 -0
- package/dist/authoring/token-entries.js +52 -0
- package/dist/authoring/types.d.ts +110 -0
- package/dist/authoring/types.js +11 -0
- package/exports/clay/DESIGN.md +138 -0
- package/exports/clay/SKILL.md +94 -0
- package/exports/clay/theme.css +37 -0
- package/exports/clay/tokens.dtcg.json +200 -0
- package/exports/dune/DESIGN.md +138 -0
- package/exports/dune/SKILL.md +94 -0
- package/exports/dune/theme.css +37 -0
- package/exports/dune/tokens.dtcg.json +200 -0
- package/exports/ember/DESIGN.md +138 -0
- package/exports/ember/SKILL.md +94 -0
- package/exports/ember/theme.css +37 -0
- package/exports/ember/tokens.dtcg.json +200 -0
- package/exports/forest/DESIGN.md +138 -0
- package/exports/forest/SKILL.md +94 -0
- package/exports/forest/theme.css +67 -0
- package/exports/forest/tokens.dtcg.json +348 -0
- package/exports/graphite/DESIGN.md +138 -0
- package/exports/graphite/SKILL.md +94 -0
- package/exports/graphite/theme.css +67 -0
- package/exports/graphite/tokens.dtcg.json +348 -0
- package/exports/index.json +45 -0
- package/exports/tide/DESIGN.md +138 -0
- package/exports/tide/SKILL.md +94 -0
- package/exports/tide/theme.css +67 -0
- package/exports/tide/tokens.dtcg.json +348 -0
- package/figma/README.md +16 -0
- package/figma/hewn.tokens.json +1308 -0
- package/figma/sticker-sheet.svg +93 -0
- package/package.json +98 -4
- package/src/authoring/css-vars.ts +92 -0
- package/src/authoring/derive.ts +106 -0
- package/src/authoring/export-css.ts +86 -0
- package/src/authoring/export-design-md.ts +134 -0
- package/src/authoring/export-dtcg.ts +116 -0
- package/src/authoring/export-figma.ts +109 -0
- package/src/authoring/export-formats.ts +101 -0
- package/src/authoring/export-skill.ts +93 -0
- package/src/authoring/export-sticker.ts +60 -0
- package/src/authoring/export-style-dictionary.ts +67 -0
- package/src/authoring/figma-kit.ts +60 -0
- package/src/authoring/index.ts +61 -0
- package/src/authoring/oklch.ts +137 -0
- package/src/authoring/override-map.ts +191 -0
- package/src/authoring/pack-def.ts +11 -0
- package/src/authoring/pack-meta.ts +66 -0
- package/src/authoring/packs-dual.ts +131 -0
- package/src/authoring/packs-single.ts +89 -0
- package/src/authoring/packs.ts +43 -0
- package/src/authoring/pro-apply.ts +156 -0
- package/src/authoring/propose.ts +181 -0
- package/src/authoring/ramps.ts +62 -0
- package/src/authoring/status-ramps.ts +98 -0
- package/src/authoring/token-entries.ts +59 -0
- package/src/authoring/types.ts +133 -0
- package/src/glass-buttons.css +46 -0
- package/src/glass.css +266 -0
- package/src/motion.css +60 -0
- package/src/packs/clay.css +45 -0
- package/src/packs/dune.css +45 -0
- package/src/packs/ember.css +45 -0
- package/src/packs/forest.css +80 -0
- package/src/packs/graphite.css +79 -0
- package/src/packs/tide.css +79 -0
- package/src/radius.css +25 -0
- package/src/tokens.css +104 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="616" height="664" viewBox="0 0 616 664" role="img" aria-label="Hewn sticker sheet">
|
|
3
|
+
<rect width="100%" height="100%" fill="#f4f4f2"/>
|
|
4
|
+
<text x="24" y="40" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="16" font-weight="600" fill="#1a1a18">Hewn · sticker sheet</text>
|
|
5
|
+
<text x="112" y="58" font-family="IBM Plex Mono, ui-monospace, monospace" font-size="10" fill="#6b6b66">surface</text>
|
|
6
|
+
<text x="232" y="58" font-family="IBM Plex Mono, ui-monospace, monospace" font-size="10" fill="#6b6b66">raised</text>
|
|
7
|
+
<text x="352" y="58" font-family="IBM Plex Mono, ui-monospace, monospace" font-size="10" fill="#6b6b66">button</text>
|
|
8
|
+
<text x="472" y="58" font-family="IBM Plex Mono, ui-monospace, monospace" font-size="10" fill="#6b6b66">input</text>
|
|
9
|
+
<g>
|
|
10
|
+
<text x="24" y="106" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">forest</text>
|
|
11
|
+
<rect x="112" y="64" width="100" height="72" rx="10" fill="oklch(0.972 0.012 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
|
|
12
|
+
<rect x="124" y="78" width="76" height="44" rx="8" fill="oklch(0.995 0.004 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
|
|
13
|
+
<rect x="232" y="64" width="100" height="72" rx="10" fill="oklch(0.972 0.012 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
|
|
14
|
+
<rect x="244" y="78" width="76" height="44" rx="8" fill="oklch(1 0 0)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
|
|
15
|
+
<rect x="352" y="64" width="100" height="72" rx="10" fill="oklch(0.972 0.012 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
|
|
16
|
+
<rect x="366" y="86" width="72" height="28" rx="8" fill="oklch(0.49 0.105 148)"/>
|
|
17
|
+
<text x="402" y="104" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.985 0.008 145)">Button</text>
|
|
18
|
+
<rect x="472" y="64" width="100" height="72" rx="10" fill="oklch(0.972 0.012 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
|
|
19
|
+
<rect x="482" y="86" width="80" height="28" rx="8" fill="oklch(0.995 0.004 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
|
|
20
|
+
<text x="490" y="104" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.49 0.035 145)">Input</text>
|
|
21
|
+
<text x="542" y="104" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.225 0.028 145)" opacity="0.35">|</text>
|
|
22
|
+
</g>
|
|
23
|
+
<g>
|
|
24
|
+
<text x="24" y="202" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">tide</text>
|
|
25
|
+
<rect x="112" y="160" width="100" height="72" rx="10" fill="oklch(0.97 0.01 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
|
|
26
|
+
<rect x="124" y="174" width="76" height="44" rx="8" fill="oklch(0.995 0.004 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
|
|
27
|
+
<rect x="232" y="160" width="100" height="72" rx="10" fill="oklch(0.97 0.01 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
|
|
28
|
+
<rect x="244" y="174" width="76" height="44" rx="8" fill="oklch(1 0 0)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
|
|
29
|
+
<rect x="352" y="160" width="100" height="72" rx="10" fill="oklch(0.97 0.01 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
|
|
30
|
+
<rect x="366" y="182" width="72" height="28" rx="8" fill="oklch(0.52 0.07 210)"/>
|
|
31
|
+
<text x="402" y="200" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.98 0.01 210)">Button</text>
|
|
32
|
+
<rect x="472" y="160" width="100" height="72" rx="10" fill="oklch(0.97 0.01 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
|
|
33
|
+
<rect x="482" y="182" width="80" height="28" rx="8" fill="oklch(0.995 0.004 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
|
|
34
|
+
<text x="490" y="200" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.48 0.03 230)">Input</text>
|
|
35
|
+
<text x="542" y="200" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.24 0.03 230)" opacity="0.35">|</text>
|
|
36
|
+
</g>
|
|
37
|
+
<g>
|
|
38
|
+
<text x="24" y="298" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">graphite</text>
|
|
39
|
+
<rect x="112" y="256" width="100" height="72" rx="10" fill="oklch(0.965 0.005 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
|
|
40
|
+
<rect x="124" y="270" width="76" height="44" rx="8" fill="oklch(0.99 0.003 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
|
|
41
|
+
<rect x="232" y="256" width="100" height="72" rx="10" fill="oklch(0.965 0.005 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
|
|
42
|
+
<rect x="244" y="270" width="76" height="44" rx="8" fill="oklch(1 0 0)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
|
|
43
|
+
<rect x="352" y="256" width="100" height="72" rx="10" fill="oklch(0.965 0.005 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
|
|
44
|
+
<rect x="366" y="278" width="72" height="28" rx="8" fill="oklch(0.48 0.06 250)"/>
|
|
45
|
+
<text x="402" y="296" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.98 0.01 250)">Button</text>
|
|
46
|
+
<rect x="472" y="256" width="100" height="72" rx="10" fill="oklch(0.965 0.005 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
|
|
47
|
+
<rect x="482" y="278" width="80" height="28" rx="8" fill="oklch(0.99 0.003 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
|
|
48
|
+
<text x="490" y="296" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.47 0.02 255)">Input</text>
|
|
49
|
+
<text x="542" y="296" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.23 0.02 255)" opacity="0.35">|</text>
|
|
50
|
+
</g>
|
|
51
|
+
<g>
|
|
52
|
+
<text x="24" y="394" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">dune</text>
|
|
53
|
+
<rect x="112" y="352" width="100" height="72" rx="10" fill="oklch(0.96 0.02 85)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
|
|
54
|
+
<rect x="124" y="366" width="76" height="44" rx="8" fill="oklch(0.985 0.012 90)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
|
|
55
|
+
<rect x="232" y="352" width="100" height="72" rx="10" fill="oklch(0.96 0.02 85)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
|
|
56
|
+
<rect x="244" y="366" width="76" height="44" rx="8" fill="oklch(0.995 0.006 95)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
|
|
57
|
+
<rect x="352" y="352" width="100" height="72" rx="10" fill="oklch(0.96 0.02 85)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
|
|
58
|
+
<rect x="366" y="374" width="72" height="28" rx="8" fill="oklch(0.58 0.11 70)"/>
|
|
59
|
+
<text x="402" y="392" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.98 0.01 90)">Button</text>
|
|
60
|
+
<rect x="472" y="352" width="100" height="72" rx="10" fill="oklch(0.96 0.02 85)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
|
|
61
|
+
<rect x="482" y="374" width="80" height="28" rx="8" fill="oklch(0.985 0.012 90)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
|
|
62
|
+
<text x="490" y="392" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.5 0.04 70)">Input</text>
|
|
63
|
+
<text x="542" y="392" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.28 0.04 65)" opacity="0.35">|</text>
|
|
64
|
+
</g>
|
|
65
|
+
<g>
|
|
66
|
+
<text x="24" y="490" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">clay</text>
|
|
67
|
+
<rect x="112" y="448" width="100" height="72" rx="10" fill="oklch(0.955 0.02 55)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
|
|
68
|
+
<rect x="124" y="462" width="76" height="44" rx="8" fill="oklch(0.98 0.012 50)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
|
|
69
|
+
<rect x="232" y="448" width="100" height="72" rx="10" fill="oklch(0.955 0.02 55)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
|
|
70
|
+
<rect x="244" y="462" width="76" height="44" rx="8" fill="oklch(0.995 0.006 45)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
|
|
71
|
+
<rect x="352" y="448" width="100" height="72" rx="10" fill="oklch(0.955 0.02 55)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
|
|
72
|
+
<rect x="366" y="470" width="72" height="28" rx="8" fill="oklch(0.55 0.12 40)"/>
|
|
73
|
+
<text x="402" y="488" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.98 0.01 50)">Button</text>
|
|
74
|
+
<rect x="472" y="448" width="100" height="72" rx="10" fill="oklch(0.955 0.02 55)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
|
|
75
|
+
<rect x="482" y="470" width="80" height="28" rx="8" fill="oklch(0.98 0.012 50)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
|
|
76
|
+
<text x="490" y="488" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.5 0.045 40)">Input</text>
|
|
77
|
+
<text x="542" y="488" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.27 0.045 40)" opacity="0.35">|</text>
|
|
78
|
+
</g>
|
|
79
|
+
<g>
|
|
80
|
+
<text x="24" y="586" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">ember</text>
|
|
81
|
+
<rect x="112" y="544" width="100" height="72" rx="10" fill="oklch(0.17 0.02 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
|
|
82
|
+
<rect x="124" y="558" width="76" height="44" rx="8" fill="oklch(0.21 0.025 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
|
|
83
|
+
<rect x="232" y="544" width="100" height="72" rx="10" fill="oklch(0.17 0.02 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
|
|
84
|
+
<rect x="244" y="558" width="76" height="44" rx="8" fill="oklch(0.255 0.03 42)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
|
|
85
|
+
<rect x="352" y="544" width="100" height="72" rx="10" fill="oklch(0.17 0.02 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
|
|
86
|
+
<rect x="366" y="566" width="72" height="28" rx="8" fill="oklch(0.7 0.15 50)"/>
|
|
87
|
+
<text x="402" y="584" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.985 0.015 50)">Button</text>
|
|
88
|
+
<rect x="472" y="544" width="100" height="72" rx="10" fill="oklch(0.17 0.02 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
|
|
89
|
+
<rect x="482" y="566" width="80" height="28" rx="8" fill="oklch(0.21 0.025 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
|
|
90
|
+
<text x="490" y="584" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.72 0.03 60)">Input</text>
|
|
91
|
+
<text x="542" y="584" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.93 0.02 70)" opacity="0.35">|</text>
|
|
92
|
+
</g>
|
|
93
|
+
</svg>
|
package/package.json
CHANGED
|
@@ -1,6 +1,100 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hewnui/themes",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/hewnui/Hewn.git",
|
|
8
|
+
"directory": "packages/themes"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"sideEffects": [
|
|
12
|
+
"**/*.css"
|
|
13
|
+
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public",
|
|
16
|
+
"exports": {
|
|
17
|
+
"./tokens.css": "./src/tokens.css",
|
|
18
|
+
"./motion.css": "./src/motion.css",
|
|
19
|
+
"./glass.css": "./src/glass.css",
|
|
20
|
+
"./glass-buttons.css": "./src/glass-buttons.css",
|
|
21
|
+
"./radius.css": "./src/radius.css",
|
|
22
|
+
"./packs/clay.css": "./src/packs/clay.css",
|
|
23
|
+
"./packs/dune.css": "./src/packs/dune.css",
|
|
24
|
+
"./packs/ember.css": "./src/packs/ember.css",
|
|
25
|
+
"./packs/forest.css": "./src/packs/forest.css",
|
|
26
|
+
"./packs/graphite.css": "./src/packs/graphite.css",
|
|
27
|
+
"./packs/tide.css": "./src/packs/tide.css",
|
|
28
|
+
"./authoring": {
|
|
29
|
+
"types": "./dist/authoring/index.d.ts",
|
|
30
|
+
"default": "./dist/authoring/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./figma/hewn.tokens.json": "./figma/hewn.tokens.json",
|
|
33
|
+
"./figma/sticker-sheet.svg": "./figma/sticker-sheet.svg",
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc -p tsconfig.build.json && tsx ../../tooling/fix-esm-relative-extensions.ts dist/authoring",
|
|
39
|
+
"generate": "tsx ../../tooling/build-figma-kit.ts && tsx ../../tooling/build-theme-exports.ts",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "vitest run"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"README.md",
|
|
45
|
+
"LICENSE",
|
|
46
|
+
"dist",
|
|
47
|
+
"src",
|
|
48
|
+
"figma",
|
|
49
|
+
"exports",
|
|
50
|
+
"!src/**/*.test.ts",
|
|
51
|
+
"!src/**/*.test.tsx",
|
|
52
|
+
"!**/__tests__/**"
|
|
53
|
+
],
|
|
54
|
+
"exports": {
|
|
55
|
+
"./tokens.css": "./src/tokens.css",
|
|
56
|
+
"./motion.css": "./src/motion.css",
|
|
57
|
+
"./glass.css": "./src/glass.css",
|
|
58
|
+
"./glass-buttons.css": "./src/glass-buttons.css",
|
|
59
|
+
"./radius.css": "./src/radius.css",
|
|
60
|
+
"./packs/clay.css": "./src/packs/clay.css",
|
|
61
|
+
"./packs/dune.css": "./src/packs/dune.css",
|
|
62
|
+
"./packs/ember.css": "./src/packs/ember.css",
|
|
63
|
+
"./packs/forest.css": "./src/packs/forest.css",
|
|
64
|
+
"./packs/graphite.css": "./src/packs/graphite.css",
|
|
65
|
+
"./packs/tide.css": "./src/packs/tide.css",
|
|
66
|
+
"./authoring": {
|
|
67
|
+
"types": "./src/authoring/index.ts",
|
|
68
|
+
"default": "./src/authoring/index.ts"
|
|
69
|
+
},
|
|
70
|
+
"./figma/hewn.tokens.json": "./figma/hewn.tokens.json",
|
|
71
|
+
"./figma/sticker-sheet.svg": "./figma/sticker-sheet.svg",
|
|
72
|
+
"./package.json": "./package.json"
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@hewnui/tsconfig": "workspace:*",
|
|
76
|
+
"typescript": "6.0.3",
|
|
77
|
+
"vitest": "4.1.10"
|
|
78
|
+
},
|
|
79
|
+
"homepage": "https://hewnui.dev",
|
|
80
|
+
"bugs": {
|
|
81
|
+
"url": "https://github.com/hewnui/Hewn/issues"
|
|
82
|
+
},
|
|
83
|
+
"author": "Himanshu Kumar",
|
|
84
|
+
"description": "Semantic OKLCH design tokens, motion tokens and six curated theme packs (forest, tide, graphite, dune, clay, ember), with DESIGN.md, DTCG and Tailwind v4 exports.",
|
|
85
|
+
"keywords": [
|
|
86
|
+
"design-tokens",
|
|
87
|
+
"oklch",
|
|
88
|
+
"css-variables",
|
|
89
|
+
"themes",
|
|
90
|
+
"tailwindcss",
|
|
91
|
+
"tailwind-v4",
|
|
92
|
+
"dtcg",
|
|
93
|
+
"design-md",
|
|
94
|
+
"dark-mode",
|
|
95
|
+
"glassmorphism",
|
|
96
|
+
"wcag",
|
|
97
|
+
"figma-tokens",
|
|
98
|
+
"hewnui"
|
|
99
|
+
]
|
|
100
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { formatOklch } from "./oklch";
|
|
2
|
+
import { colorEntries, structuralEntries } from "./token-entries";
|
|
3
|
+
import type { ResolvedMode } from "./types";
|
|
4
|
+
|
|
5
|
+
const COLOR_BRIDGE = [
|
|
6
|
+
"background",
|
|
7
|
+
"foreground",
|
|
8
|
+
"surface",
|
|
9
|
+
"surface-raised",
|
|
10
|
+
"muted",
|
|
11
|
+
"muted-foreground",
|
|
12
|
+
"accent",
|
|
13
|
+
"accent-foreground",
|
|
14
|
+
"border",
|
|
15
|
+
"ring",
|
|
16
|
+
"danger",
|
|
17
|
+
"danger-foreground",
|
|
18
|
+
"danger-subtle",
|
|
19
|
+
"danger-border",
|
|
20
|
+
"success",
|
|
21
|
+
"success-foreground",
|
|
22
|
+
"success-subtle",
|
|
23
|
+
"success-border",
|
|
24
|
+
"warning",
|
|
25
|
+
"warning-foreground",
|
|
26
|
+
"warning-subtle",
|
|
27
|
+
"warning-border",
|
|
28
|
+
"info",
|
|
29
|
+
"info-foreground",
|
|
30
|
+
"info-subtle",
|
|
31
|
+
"info-border",
|
|
32
|
+
] as const;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Map a resolved mode to CSS custom properties for scoped live preview.
|
|
36
|
+
* Includes Tailwind `--color-*` rebinds so utilities do not keep :root-resolved
|
|
37
|
+
* docs-shell values, plus local glass vars so html[data-material=glass] rules
|
|
38
|
+
* sample the draft pack instead of the documentation theme.
|
|
39
|
+
*/
|
|
40
|
+
export function modeToCssVars(mode: ResolvedMode): Record<string, string> {
|
|
41
|
+
const vars: Record<string, string> = {};
|
|
42
|
+
for (const entry of colorEntries(mode)) {
|
|
43
|
+
vars[`--kp-${entry.name}`] = entry.value;
|
|
44
|
+
}
|
|
45
|
+
for (const entry of structuralEntries(mode)) {
|
|
46
|
+
vars[`--kp-${entry.name}`] = entry.value;
|
|
47
|
+
}
|
|
48
|
+
vars["--kp-font-sans"] =
|
|
49
|
+
'var(--font-plex-sans, "IBM Plex Sans"), ui-sans-serif, system-ui, sans-serif';
|
|
50
|
+
vars["--kp-font-mono"] =
|
|
51
|
+
'var(--font-plex-mono, "IBM Plex Mono"), ui-monospace, monospace';
|
|
52
|
+
vars["--kp-font-display"] =
|
|
53
|
+
'var(--font-space-grotesk, "Space Grotesk"), var(--kp-font-sans)';
|
|
54
|
+
vars["--kp-shadow-surface"] =
|
|
55
|
+
`0 1px 2px color-mix(in oklch, ${formatOklch(mode.foreground)} 8%, transparent), ` +
|
|
56
|
+
`0 16px 40px -28px color-mix(in oklch, ${formatOklch(mode.foreground)} 28%, transparent)`;
|
|
57
|
+
|
|
58
|
+
// Recompute glass locally so inherited html glass fills cannot leak docs tint.
|
|
59
|
+
vars["--kp-glass-fill"] =
|
|
60
|
+
"color-mix(in oklch, var(--kp-surface) 46%, transparent)";
|
|
61
|
+
vars["--kp-glass-border"] =
|
|
62
|
+
"color-mix(in oklch, var(--kp-foreground) 16%, transparent)";
|
|
63
|
+
vars["--kp-glass-sheen"] =
|
|
64
|
+
"linear-gradient(148deg, color-mix(in oklch, var(--kp-glass-tint) 70%, white 8%), " +
|
|
65
|
+
"color-mix(in oklch, var(--kp-surface) 22%, transparent) 42%, " +
|
|
66
|
+
"color-mix(in oklch, var(--kp-surface) 38%, transparent))";
|
|
67
|
+
|
|
68
|
+
for (const name of COLOR_BRIDGE) {
|
|
69
|
+
vars[`--color-${name}`] = `var(--kp-${name})`;
|
|
70
|
+
}
|
|
71
|
+
// Fumadocs tokens occasionally paint nested chrome; keep them on the draft.
|
|
72
|
+
vars["--color-fd-background"] = "var(--kp-background)";
|
|
73
|
+
vars["--color-fd-foreground"] = "var(--kp-foreground)";
|
|
74
|
+
vars["--color-fd-card"] = "var(--kp-surface)";
|
|
75
|
+
vars["--color-fd-card-foreground"] = "var(--kp-foreground)";
|
|
76
|
+
vars["--color-fd-muted"] = "var(--kp-muted)";
|
|
77
|
+
vars["--color-fd-muted-foreground"] = "var(--kp-muted-foreground)";
|
|
78
|
+
vars["--color-fd-primary"] = "var(--kp-accent)";
|
|
79
|
+
vars["--color-fd-primary-foreground"] = "var(--kp-accent-foreground)";
|
|
80
|
+
vars["--color-fd-border"] = "var(--kp-border)";
|
|
81
|
+
vars["--color-fd-ring"] = "var(--kp-ring)";
|
|
82
|
+
|
|
83
|
+
return vars;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Stylesheet block for a live-preview selector (no :root). */
|
|
87
|
+
export function modeToPreviewCss(selector: string, mode: ResolvedMode): string {
|
|
88
|
+
const lines = Object.entries(modeToCssVars(mode)).map(
|
|
89
|
+
([name, value]) => ` ${name}: ${value};`,
|
|
90
|
+
);
|
|
91
|
+
return `${selector} {\n${lines.join("\n")}\n}\n`;
|
|
92
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { applyGlass, applyMotion, applyNeutrals, applySemantic, applyShape } from "./pro-apply";
|
|
2
|
+
import { BASE_PACKS, supportedModes } from "./packs";
|
|
3
|
+
import { accentSetFromSeed } from "./ramps";
|
|
4
|
+
import type {
|
|
5
|
+
OverrideMap,
|
|
6
|
+
RadiusPreset,
|
|
7
|
+
ResolvedMode,
|
|
8
|
+
ResolvedPack,
|
|
9
|
+
StructuralTokens,
|
|
10
|
+
ThemeMode,
|
|
11
|
+
} from "./types";
|
|
12
|
+
|
|
13
|
+
const RADIUS_PRESETS: Record<
|
|
14
|
+
Exclude<RadiusPreset, "soft">,
|
|
15
|
+
Pick<
|
|
16
|
+
StructuralTokens,
|
|
17
|
+
"radiusSm" | "radiusMd" | "radiusLg" | "radiusPanel"
|
|
18
|
+
>
|
|
19
|
+
> = {
|
|
20
|
+
sharp: {
|
|
21
|
+
radiusSm: "0.125rem",
|
|
22
|
+
radiusMd: "0.2rem",
|
|
23
|
+
radiusLg: "0.3rem",
|
|
24
|
+
radiusPanel: "0.25rem",
|
|
25
|
+
},
|
|
26
|
+
rounded: {
|
|
27
|
+
radiusSm: "0.85rem",
|
|
28
|
+
radiusMd: "1.15rem",
|
|
29
|
+
radiusLg: "1.5rem",
|
|
30
|
+
radiusPanel: "1.25rem",
|
|
31
|
+
},
|
|
32
|
+
pill: {
|
|
33
|
+
radiusSm: "9999px",
|
|
34
|
+
radiusMd: "9999px",
|
|
35
|
+
radiusLg: "1.5rem",
|
|
36
|
+
radiusPanel: "1.15rem",
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type DeriveResult =
|
|
41
|
+
| { ok: true; pack: ResolvedPack }
|
|
42
|
+
| { ok: false; errors: string[] };
|
|
43
|
+
|
|
44
|
+
export function derivePack(overrides: OverrideMap): DeriveResult {
|
|
45
|
+
const base = BASE_PACKS[overrides.basePackId];
|
|
46
|
+
const modes = supportedModes(overrides.basePackId);
|
|
47
|
+
const adjustments: string[] = [];
|
|
48
|
+
const resolved: Partial<Record<ThemeMode, ResolvedMode>> = {};
|
|
49
|
+
|
|
50
|
+
let structural: StructuralTokens = { ...base.structural };
|
|
51
|
+
if (overrides.radiusPreset && overrides.radiusPreset !== "soft") {
|
|
52
|
+
structural = { ...structural, ...RADIUS_PRESETS[overrides.radiusPreset] };
|
|
53
|
+
}
|
|
54
|
+
structural = applyShape(structural, overrides.shape);
|
|
55
|
+
structural = applyMotion(structural, overrides.motion);
|
|
56
|
+
|
|
57
|
+
for (const mode of modes) {
|
|
58
|
+
const colors = base.modes[mode];
|
|
59
|
+
if (!colors) continue;
|
|
60
|
+
|
|
61
|
+
let next = { ...colors };
|
|
62
|
+
if (overrides.accentSeed) {
|
|
63
|
+
const accent = accentSetFromSeed(overrides.accentSeed, mode);
|
|
64
|
+
if ("error" in accent) {
|
|
65
|
+
return { ok: false, errors: [accent.error] };
|
|
66
|
+
}
|
|
67
|
+
next = {
|
|
68
|
+
...next,
|
|
69
|
+
accent: accent.set.accent,
|
|
70
|
+
accentForeground: accent.set.accentForeground,
|
|
71
|
+
ring: accent.set.ring,
|
|
72
|
+
glassTint: accent.set.glassTint,
|
|
73
|
+
};
|
|
74
|
+
adjustments.push(...accent.adjustments);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
next = applyNeutrals(next, overrides.neutrals, mode, adjustments);
|
|
78
|
+
const semantic = applySemantic(next, overrides.semantic, mode, adjustments);
|
|
79
|
+
if ("error" in semantic) {
|
|
80
|
+
return { ok: false, errors: [semantic.error] };
|
|
81
|
+
}
|
|
82
|
+
next = applyGlass(semantic, overrides.glass);
|
|
83
|
+
|
|
84
|
+
resolved[mode] = {
|
|
85
|
+
...next,
|
|
86
|
+
...structural,
|
|
87
|
+
mode,
|
|
88
|
+
colorScheme: mode,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const packId =
|
|
93
|
+
overrides.packId ??
|
|
94
|
+
`custom-${overrides.basePackId}${overrides.accentSeed ? "-accent" : ""}`;
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
ok: true,
|
|
98
|
+
pack: {
|
|
99
|
+
id: packId,
|
|
100
|
+
basePackId: overrides.basePackId,
|
|
101
|
+
supportedModes: modes,
|
|
102
|
+
modes: resolved,
|
|
103
|
+
adjustments: [...new Set(adjustments)],
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
colorEntries,
|
|
3
|
+
modeOrder,
|
|
4
|
+
primaryMode,
|
|
5
|
+
structuralEntries,
|
|
6
|
+
} from "./token-entries";
|
|
7
|
+
import type { ResolvedMode, ResolvedPack } from "./types";
|
|
8
|
+
|
|
9
|
+
function colorLines(mode: ResolvedMode): string {
|
|
10
|
+
return [
|
|
11
|
+
` color-scheme: ${mode.colorScheme};`,
|
|
12
|
+
...colorEntries(mode).map(
|
|
13
|
+
(entry) => ` --kp-${entry.name}: ${entry.value};`,
|
|
14
|
+
),
|
|
15
|
+
].join("\n");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function structuralLines(mode: ResolvedMode): string {
|
|
19
|
+
return [
|
|
20
|
+
...structuralEntries(mode).map(
|
|
21
|
+
(entry) => ` --kp-${entry.name}: ${entry.value};`,
|
|
22
|
+
),
|
|
23
|
+
` --kp-font-sans: var(--font-plex-sans, "IBM Plex Sans"), ui-sans-serif, system-ui,`,
|
|
24
|
+
` sans-serif;`,
|
|
25
|
+
` --kp-font-mono: var(--font-plex-mono, "IBM Plex Mono"), ui-monospace, monospace;`,
|
|
26
|
+
` --kp-font-display: var(--font-space-grotesk, "Space Grotesk"), var(--kp-font-sans);`,
|
|
27
|
+
].join("\n");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Free-tier CSS pack export — drop-in `[data-theme]` file. */
|
|
31
|
+
export function exportPackCss(pack: ResolvedPack): string {
|
|
32
|
+
const blocks: string[] = [];
|
|
33
|
+
let first = true;
|
|
34
|
+
|
|
35
|
+
for (const modeName of modeOrder(pack)) {
|
|
36
|
+
const mode = pack.modes[modeName];
|
|
37
|
+
if (!mode) continue;
|
|
38
|
+
|
|
39
|
+
const selector = first
|
|
40
|
+
? `:root,\n[data-theme="${pack.id}"][data-mode="${mode.mode}"]`
|
|
41
|
+
: `[data-theme="${pack.id}"][data-mode="${mode.mode}"]`;
|
|
42
|
+
|
|
43
|
+
const body = first
|
|
44
|
+
? `${colorLines(mode)}\n${structuralLines(mode)}`
|
|
45
|
+
: colorLines(mode);
|
|
46
|
+
|
|
47
|
+
blocks.push(`${selector} {\n${body}\n}`);
|
|
48
|
+
first = false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return `${blocks.join("\n\n")}\n`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Free — Tailwind v4 `@theme` block for the primary mode, plus mode overrides
|
|
56
|
+
* that remap the same `--color-*` custom properties.
|
|
57
|
+
*/
|
|
58
|
+
export function exportTailwindTheme(pack: ResolvedPack): string {
|
|
59
|
+
const primary = primaryMode(pack);
|
|
60
|
+
const themeLines = [
|
|
61
|
+
...colorEntries(primary).map(
|
|
62
|
+
(entry) => ` --color-${entry.name}: ${entry.value};`,
|
|
63
|
+
),
|
|
64
|
+
...structuralEntries(primary)
|
|
65
|
+
.filter((entry) => entry.name.startsWith("radius-"))
|
|
66
|
+
.map((entry) => ` --${entry.name}: ${entry.value};`),
|
|
67
|
+
` --font-sans: var(--font-plex-sans, "IBM Plex Sans"), ui-sans-serif, system-ui, sans-serif;`,
|
|
68
|
+
` --font-mono: var(--font-plex-mono, "IBM Plex Mono"), ui-monospace, monospace;`,
|
|
69
|
+
` --font-display: var(--font-space-grotesk, "Space Grotesk"), var(--font-sans);`,
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const blocks = [`@theme {\n${themeLines.join("\n")}\n}`];
|
|
73
|
+
|
|
74
|
+
for (const modeName of modeOrder(pack).slice(1)) {
|
|
75
|
+
const mode = pack.modes[modeName];
|
|
76
|
+
if (!mode) continue;
|
|
77
|
+
const lines = colorEntries(mode).map(
|
|
78
|
+
(entry) => ` --color-${entry.name}: ${entry.value};`,
|
|
79
|
+
);
|
|
80
|
+
blocks.push(
|
|
81
|
+
`[data-theme="${pack.id}"][data-mode="${mode.mode}"] {\n${lines.join("\n")}\n}`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return `/* ${pack.id} — Tailwind v4 @theme */\n${blocks.join("\n\n")}\n`;
|
|
86
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import {
|
|
2
|
+
COLOR_ROLES,
|
|
3
|
+
DESIGN_DO,
|
|
4
|
+
DESIGN_DONT,
|
|
5
|
+
PACK_IDENTITY,
|
|
6
|
+
} from "./pack-meta";
|
|
7
|
+
import { formatOklch } from "./oklch";
|
|
8
|
+
import {
|
|
9
|
+
colorEntries,
|
|
10
|
+
modeOrder,
|
|
11
|
+
primaryMode,
|
|
12
|
+
structuralEntries,
|
|
13
|
+
} from "./token-entries";
|
|
14
|
+
import type { BasePackId, ResolvedPack } from "./types";
|
|
15
|
+
|
|
16
|
+
function identity(pack: ResolvedPack) {
|
|
17
|
+
const meta = PACK_IDENTITY[pack.basePackId as BasePackId];
|
|
18
|
+
return meta ?? { label: pack.id, summary: `Custom pack based on ${pack.basePackId}.` };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function paletteTable(pack: ResolvedPack): string {
|
|
22
|
+
const modes = modeOrder(pack);
|
|
23
|
+
const header =
|
|
24
|
+
modes.length > 1
|
|
25
|
+
? `| Token | Role | ${modes.map((m) => m).join(" | ")} |`
|
|
26
|
+
: `| Token | Role | ${modes[0]} |`;
|
|
27
|
+
const sep =
|
|
28
|
+
modes.length > 1
|
|
29
|
+
? `|---|---|${modes.map(() => "---").join("|")}|`
|
|
30
|
+
: `|---|---|---|`;
|
|
31
|
+
|
|
32
|
+
const primary = primaryMode(pack);
|
|
33
|
+
const rows = colorEntries(primary).map((entry) => {
|
|
34
|
+
const role = COLOR_ROLES[entry.name] ?? entry.name;
|
|
35
|
+
const values = modes.map((modeName) => {
|
|
36
|
+
const mode = pack.modes[modeName];
|
|
37
|
+
if (!mode) return "—";
|
|
38
|
+
const match = colorEntries(mode).find((e) => e.name === entry.name);
|
|
39
|
+
return match ? `\`${match.value}\`` : "—";
|
|
40
|
+
});
|
|
41
|
+
return `| \`${entry.name}\` | ${role} | ${values.join(" | ")} |`;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return [header, sep, ...rows].join("\n");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function structuralBlock(pack: ResolvedPack): string {
|
|
48
|
+
const mode = primaryMode(pack);
|
|
49
|
+
return structuralEntries(mode)
|
|
50
|
+
.map((entry) => `- \`${entry.name}\`: \`${entry.value}\``)
|
|
51
|
+
.join("\n");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function list(items: readonly string[]): string {
|
|
55
|
+
return items.map((item) => `- ${item}`).join("\n");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Free — human- and AI-readable design brief for one pack. */
|
|
59
|
+
export function exportDesignMd(pack: ResolvedPack): string {
|
|
60
|
+
const { label, summary } = identity(pack);
|
|
61
|
+
const modes = modeOrder(pack).join(", ");
|
|
62
|
+
const mode = primaryMode(pack);
|
|
63
|
+
|
|
64
|
+
return `# ${label} — Design brief
|
|
65
|
+
|
|
66
|
+
> Generated from Hewn curated theme packs. Semantic OKLCH tokens; do not edit by hand.
|
|
67
|
+
|
|
68
|
+
## Identity
|
|
69
|
+
|
|
70
|
+
${summary}
|
|
71
|
+
|
|
72
|
+
- **Pack id:** \`${pack.id}\`
|
|
73
|
+
- **Base pack:** \`${pack.basePackId}\`
|
|
74
|
+
- **Supported modes:** ${modes}
|
|
75
|
+
- **Color scheme (primary):** ${mode.colorScheme}
|
|
76
|
+
|
|
77
|
+
## Palette
|
|
78
|
+
|
|
79
|
+
${paletteTable(pack)}
|
|
80
|
+
|
|
81
|
+
## Typography
|
|
82
|
+
|
|
83
|
+
| Role | Stack | Usage |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| Sans | IBM Plex Sans, ui-sans-serif, system-ui | UI chrome, body, headings |
|
|
86
|
+
| Mono | IBM Plex Mono, ui-monospace | Labels, code, tabular metrics |
|
|
87
|
+
| Display | Space Grotesk → sans | Marketing hero H1 and brand wordmark ≥18px only |
|
|
88
|
+
|
|
89
|
+
Body text uses pretty wrapping; headings use balanced wrapping; dynamic numbers use \`tabular-nums\`.
|
|
90
|
+
|
|
91
|
+
## Radius & density
|
|
92
|
+
|
|
93
|
+
${structuralBlock(pack)}
|
|
94
|
+
|
|
95
|
+
Density scales control spacing rhythm. Panel radius (\`radius-panel\`) caps menus and dialogs so they never go full-pill.
|
|
96
|
+
|
|
97
|
+
## Motion
|
|
98
|
+
|
|
99
|
+
- Duration: \`${mode.motionDuration}\`
|
|
100
|
+
- Spring stiffness: \`${mode.motionStiffness}\`
|
|
101
|
+
- Spring damping: \`${mode.motionDamping}\`
|
|
102
|
+
- Reduced motion always wins over global motion toggles.
|
|
103
|
+
- Prefer transform / opacity / filter; never animate layout properties continuously.
|
|
104
|
+
|
|
105
|
+
## Material
|
|
106
|
+
|
|
107
|
+
- \`solid\` — structured product surfaces and separators
|
|
108
|
+
- \`glass\` — accent-tinted frosted surfaces (blur, saturation, refraction, opaque fallback)
|
|
109
|
+
|
|
110
|
+
## Do
|
|
111
|
+
|
|
112
|
+
${list(DESIGN_DO)}
|
|
113
|
+
|
|
114
|
+
## Don't
|
|
115
|
+
|
|
116
|
+
${list(DESIGN_DONT)}
|
|
117
|
+
|
|
118
|
+
## Token reference (primary mode)
|
|
119
|
+
|
|
120
|
+
\`\`\`
|
|
121
|
+
${colorEntries(mode)
|
|
122
|
+
.map((e) => `--kp-${e.name}: ${e.value};`)
|
|
123
|
+
.join("\n")}
|
|
124
|
+
${structuralEntries(mode)
|
|
125
|
+
.map((e) => `--kp-${e.name}: ${e.value};`)
|
|
126
|
+
.join("\n")}
|
|
127
|
+
\`\`\`
|
|
128
|
+
`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Convenience — expose formatted OKLCH for tests/docs samples. */
|
|
132
|
+
export function sampleAccent(pack: ResolvedPack): string {
|
|
133
|
+
return formatOklch(primaryMode(pack).accent);
|
|
134
|
+
}
|