designlang 6.0.0 → 7.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/.github/FUNDING.yml +1 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +62 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +28 -0
- package/.vercel/README.txt +11 -0
- package/.vercel/project.json +1 -0
- package/CHANGELOG.md +58 -0
- package/CONTRIBUTING.md +25 -0
- package/README.md +120 -8
- package/bin/design-extract.js +106 -3
- package/chrome-extension/README.md +41 -0
- package/chrome-extension/icons/favicon.svg +7 -0
- package/chrome-extension/icons/icon-128.png +0 -0
- package/chrome-extension/icons/icon-16.png +0 -0
- package/chrome-extension/icons/icon-32.png +0 -0
- package/chrome-extension/icons/icon-48.png +0 -0
- package/chrome-extension/manifest.json +26 -0
- package/chrome-extension/popup.html +167 -0
- package/chrome-extension/popup.js +59 -0
- package/docs/superpowers/plans/2026-04-18-designlang-v7.md +1121 -0
- package/docs/superpowers/specs/2026-04-18-designlang-v7-design.md +150 -0
- package/docs/superpowers/specs/2026-04-18-website-redesign-design.md +120 -0
- package/docs/superpowers/specs/2026-04-19-designlang-v7-1-design.md +111 -0
- package/package.json +5 -4
- package/src/config.js +26 -0
- package/src/crawler.js +136 -2
- package/src/extractors/a11y-remediation.js +47 -0
- package/src/extractors/component-clusters.js +39 -0
- package/src/extractors/css-health.js +151 -0
- package/src/extractors/scoring.js +20 -1
- package/src/extractors/semantic-regions.js +44 -0
- package/src/extractors/stack-fingerprint.js +88 -0
- package/src/formatters/_token-ref.js +44 -0
- package/src/formatters/agent-rules.js +116 -0
- package/src/formatters/android-compose.js +164 -0
- package/src/formatters/dtcg-tokens.js +175 -0
- package/src/formatters/flutter-dart.js +130 -0
- package/src/formatters/ios-swiftui.js +161 -0
- package/src/formatters/markdown.js +25 -0
- package/src/formatters/wordpress.js +183 -0
- package/src/index.js +30 -0
- package/src/mcp/resources.js +64 -0
- package/src/mcp/server.js +110 -0
- package/src/mcp/tools.js +149 -0
- package/src/utils-cookies.js +73 -0
- package/tests/cli.test.js +50 -0
- package/tests/cookies.test.js +98 -0
- package/tests/extractors.test.js +131 -0
- package/tests/formatters.test.js +232 -0
- package/tests/mcp.test.js +68 -0
- package/website/app/api/extract/route.js +216 -56
- package/website/app/components/A11ySlider.js +369 -0
- package/website/app/components/Comparison.js +286 -0
- package/website/app/components/CssHealth.js +243 -0
- package/website/app/components/HeroExtractor.js +455 -0
- package/website/app/components/Marginalia.js +3 -0
- package/website/app/components/McpSection.js +223 -0
- package/website/app/components/PlatformTabs.js +250 -0
- package/website/app/components/RegionsComponents.js +429 -0
- package/website/app/components/Rule.js +13 -0
- package/website/app/components/Specimens.js +237 -0
- package/website/app/components/StructuredData.js +144 -0
- package/website/app/components/TokenBrowser.js +344 -0
- package/website/app/components/token-browser-sample.js +65 -0
- package/website/app/globals.css +415 -633
- package/website/app/icon.svg +7 -0
- package/website/app/layout.js +113 -6
- package/website/app/opengraph-image.js +170 -0
- package/website/app/page.js +325 -148
- package/website/app/robots.js +15 -0
- package/website/app/seo-config.js +82 -0
- package/website/app/sitemap.js +18 -0
- package/website/lib/cache.js +73 -0
- package/website/lib/rate-limit.js +30 -0
- package/website/lib/rate-limit.test.js +55 -0
- package/website/lib/specimens.json +86 -0
- package/website/lib/token-helpers.js +70 -0
- package/website/lib/url-safety.js +103 -0
- package/website/lib/url-safety.test.js +116 -0
- package/website/lib/zip-files.js +15 -0
- package/website/package-lock.json +85 -0
- package/website/package.json +1 -0
- package/website/public/favicon.svg +7 -0
- package/website/public/logo-specimen.svg +76 -0
- package/website/public/mark.svg +12 -0
- package/website/public/site.webmanifest +13 -0
- package/website/app/favicon.ico +0 -0
- package/website/public/file.svg +0 -1
- package/website/public/globe.svg +0 -1
- package/website/public/next.svg +0 -1
- package/website/public/vercel.svg +0 -1
- package/website/public/window.svg +0 -1
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { resolveRef, flattenTokens } from '../../lib/token-helpers';
|
|
5
|
+
import { sampleTokens, sampleCommand } from './token-browser-sample';
|
|
6
|
+
import Marginalia from './Marginalia';
|
|
7
|
+
|
|
8
|
+
const REF_PATTERN = /^\{([^}]+)\}$/;
|
|
9
|
+
function refTarget(value) {
|
|
10
|
+
if (typeof value !== 'string') return null;
|
|
11
|
+
const m = value.match(REF_PATTERN);
|
|
12
|
+
return m ? m[1] : null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function Swatch({ value }) {
|
|
16
|
+
return (
|
|
17
|
+
<span
|
|
18
|
+
aria-hidden="true"
|
|
19
|
+
style={{
|
|
20
|
+
display: 'inline-block',
|
|
21
|
+
width: 14,
|
|
22
|
+
height: 14,
|
|
23
|
+
border: '1px solid var(--ink)',
|
|
24
|
+
background: value,
|
|
25
|
+
verticalAlign: 'middle',
|
|
26
|
+
marginRight: 8,
|
|
27
|
+
}}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function ValueSample({ row, resolvedHex, highlighted }) {
|
|
33
|
+
const { $type, $value } = row;
|
|
34
|
+
if ($type === 'color') {
|
|
35
|
+
const display = typeof $value === 'string' && $value.startsWith('{')
|
|
36
|
+
? (resolvedHex || $value)
|
|
37
|
+
: $value;
|
|
38
|
+
return (
|
|
39
|
+
<span className="mono" style={{ fontSize: 12, display: 'inline-flex', alignItems: 'center' }}>
|
|
40
|
+
{typeof display === 'string' && display.startsWith('#') ? <Swatch value={display} /> : null}
|
|
41
|
+
<span style={{ color: highlighted ? 'var(--accent)' : 'var(--ink)' }}>{display}</span>
|
|
42
|
+
</span>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
if ($type === 'dimension') {
|
|
46
|
+
return <span className="mono" style={{ fontSize: 12 }}>{String(resolvedHex || $value)}</span>;
|
|
47
|
+
}
|
|
48
|
+
if ($type === 'typography' && typeof $value === 'object' && $value) {
|
|
49
|
+
const { fontFamily, fontSize, lineHeight, fontWeight } = $value;
|
|
50
|
+
const label = `${String(fontFamily).split(',')[0]} ${fontSize}/${lineHeight} ${fontWeight}`;
|
|
51
|
+
return (
|
|
52
|
+
<span
|
|
53
|
+
style={{
|
|
54
|
+
fontFamily: String(fontFamily),
|
|
55
|
+
fontSize: 13,
|
|
56
|
+
lineHeight: 1.3,
|
|
57
|
+
fontWeight: Number(fontWeight) || 400,
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
{label}
|
|
61
|
+
</span>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return <span className="mono" style={{ fontSize: 12 }}>{JSON.stringify($value)}</span>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default function TokenBrowser() {
|
|
68
|
+
const tokens = sampleTokens;
|
|
69
|
+
const semanticRows = useMemo(() => flattenTokens(tokens, { layer: 'semantic' }), [tokens]);
|
|
70
|
+
const primitiveRows = useMemo(() => flattenTokens(tokens, { layer: 'primitive' }), [tokens]);
|
|
71
|
+
|
|
72
|
+
const [activeIdx, setActiveIdx] = useState(-1);
|
|
73
|
+
const [reduced, setReduced] = useState(false);
|
|
74
|
+
const semanticRefs = useRef([]);
|
|
75
|
+
const primitiveRefs = useRef([]);
|
|
76
|
+
const containerRef = useRef(null);
|
|
77
|
+
const [lineGeom, setLineGeom] = useState(null); // { x1, y1, x2, y2, targetPrimitivePath }
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
81
|
+
const update = () => setReduced(mq.matches);
|
|
82
|
+
update();
|
|
83
|
+
mq.addEventListener?.('change', update);
|
|
84
|
+
return () => mq.removeEventListener?.('change', update);
|
|
85
|
+
}, []);
|
|
86
|
+
|
|
87
|
+
// Compute line geometry when activeIdx changes.
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (activeIdx < 0 || !containerRef.current) {
|
|
90
|
+
setLineGeom(null);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const row = semanticRows[activeIdx];
|
|
94
|
+
if (!row) return setLineGeom(null);
|
|
95
|
+
const target = refTarget(row.$value);
|
|
96
|
+
if (!target) return setLineGeom(null);
|
|
97
|
+
|
|
98
|
+
const primitiveIdx = primitiveRows.findIndex((p) => p.path === target);
|
|
99
|
+
if (primitiveIdx < 0) return setLineGeom(null);
|
|
100
|
+
|
|
101
|
+
const semEl = semanticRefs.current[activeIdx];
|
|
102
|
+
const primEl = primitiveRefs.current[primitiveIdx];
|
|
103
|
+
const box = containerRef.current.getBoundingClientRect();
|
|
104
|
+
if (!semEl || !primEl) return setLineGeom(null);
|
|
105
|
+
const a = semEl.getBoundingClientRect();
|
|
106
|
+
const b = primEl.getBoundingClientRect();
|
|
107
|
+
|
|
108
|
+
setLineGeom({
|
|
109
|
+
x1: a.right - box.left,
|
|
110
|
+
y1: a.top + a.height / 2 - box.top,
|
|
111
|
+
x2: b.left - box.left,
|
|
112
|
+
y2: b.top + b.height / 2 - box.top,
|
|
113
|
+
targetPrimitivePath: target,
|
|
114
|
+
width: box.width,
|
|
115
|
+
height: box.height,
|
|
116
|
+
});
|
|
117
|
+
}, [activeIdx, semanticRows, primitiveRows]);
|
|
118
|
+
|
|
119
|
+
// Recompute on resize.
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
const onResize = () => setActiveIdx((i) => i); // re-trigger
|
|
122
|
+
window.addEventListener('resize', onResize);
|
|
123
|
+
return () => window.removeEventListener('resize', onResize);
|
|
124
|
+
}, []);
|
|
125
|
+
|
|
126
|
+
const activeRow = activeIdx >= 0 ? semanticRows[activeIdx] : null;
|
|
127
|
+
const activeResolved = activeRow ? resolveRef(tokens, activeRow.path) : null;
|
|
128
|
+
const activeTargetPath = activeRow ? refTarget(activeRow.$value) : null;
|
|
129
|
+
|
|
130
|
+
const handleKey = (e) => {
|
|
131
|
+
if (e.key === 'ArrowDown') {
|
|
132
|
+
e.preventDefault();
|
|
133
|
+
setActiveIdx((i) => Math.min(semanticRows.length - 1, i < 0 ? 0 : i + 1));
|
|
134
|
+
} else if (e.key === 'ArrowUp') {
|
|
135
|
+
e.preventDefault();
|
|
136
|
+
setActiveIdx((i) => Math.max(0, i < 0 ? 0 : i - 1));
|
|
137
|
+
} else if (e.key === 'Escape') {
|
|
138
|
+
setActiveIdx(-1);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<div className="with-margin">
|
|
144
|
+
<div>
|
|
145
|
+
<h2 className="display" style={{ marginBottom: 'var(--r3)' }}>Aliases, not values.</h2>
|
|
146
|
+
<p className="prose" style={{ fontSize: 18, marginBottom: 'var(--r6)' }}>
|
|
147
|
+
v7.0 writes tokens in W3C DTCG. Hover a semantic row on the left and watch the
|
|
148
|
+
alias resolve through to its primitive on the right.
|
|
149
|
+
</p>
|
|
150
|
+
|
|
151
|
+
<div
|
|
152
|
+
ref={containerRef}
|
|
153
|
+
role="group"
|
|
154
|
+
aria-label="DTCG token browser"
|
|
155
|
+
tabIndex={0}
|
|
156
|
+
onKeyDown={handleKey}
|
|
157
|
+
style={{
|
|
158
|
+
position: 'relative',
|
|
159
|
+
display: 'grid',
|
|
160
|
+
gridTemplateColumns: '5fr 2fr 5fr',
|
|
161
|
+
columnGap: 0,
|
|
162
|
+
border: 'var(--hair)',
|
|
163
|
+
background: 'var(--paper-2)',
|
|
164
|
+
}}
|
|
165
|
+
>
|
|
166
|
+
{/* Left: semantic */}
|
|
167
|
+
<div>
|
|
168
|
+
<div
|
|
169
|
+
className="mono"
|
|
170
|
+
style={{
|
|
171
|
+
fontSize: 11,
|
|
172
|
+
letterSpacing: '0.12em',
|
|
173
|
+
textTransform: 'uppercase',
|
|
174
|
+
color: 'var(--ink-2)',
|
|
175
|
+
padding: '10px 14px',
|
|
176
|
+
borderBottom: 'var(--hair)',
|
|
177
|
+
}}
|
|
178
|
+
>
|
|
179
|
+
semantic
|
|
180
|
+
</div>
|
|
181
|
+
{semanticRows.map((row, i) => {
|
|
182
|
+
const isActive = i === activeIdx;
|
|
183
|
+
return (
|
|
184
|
+
<div
|
|
185
|
+
key={row.path}
|
|
186
|
+
ref={(el) => (semanticRefs.current[i] = el)}
|
|
187
|
+
onMouseEnter={() => setActiveIdx(i)}
|
|
188
|
+
onFocus={() => setActiveIdx(i)}
|
|
189
|
+
tabIndex={-1}
|
|
190
|
+
role="row"
|
|
191
|
+
aria-selected={isActive}
|
|
192
|
+
style={{
|
|
193
|
+
display: 'grid',
|
|
194
|
+
gridTemplateColumns: '1fr auto',
|
|
195
|
+
alignItems: 'center',
|
|
196
|
+
gap: 12,
|
|
197
|
+
padding: '10px 14px',
|
|
198
|
+
borderBottom: i === semanticRows.length - 1 ? 0 : '1px solid var(--ink-3)',
|
|
199
|
+
background: isActive ? 'var(--paper)' : 'transparent',
|
|
200
|
+
cursor: 'pointer',
|
|
201
|
+
}}
|
|
202
|
+
>
|
|
203
|
+
<span className="mono" style={{ fontSize: 12, color: 'var(--ink)' }}>
|
|
204
|
+
{row.path.replace(/^semantic\./, '')}
|
|
205
|
+
</span>
|
|
206
|
+
<ValueSample row={row} resolvedHex={isActive ? activeResolved : null} highlighted={isActive} />
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
})}
|
|
210
|
+
</div>
|
|
211
|
+
|
|
212
|
+
{/* Middle: flight-path */}
|
|
213
|
+
<div style={{ position: 'relative', borderLeft: '1px solid var(--ink-3)', borderRight: '1px solid var(--ink-3)' }}>
|
|
214
|
+
{lineGeom && (
|
|
215
|
+
<svg
|
|
216
|
+
aria-hidden="true"
|
|
217
|
+
style={{
|
|
218
|
+
position: 'absolute',
|
|
219
|
+
inset: 0,
|
|
220
|
+
width: '100%',
|
|
221
|
+
height: '100%',
|
|
222
|
+
pointerEvents: 'none',
|
|
223
|
+
overflow: 'visible',
|
|
224
|
+
}}
|
|
225
|
+
viewBox={`0 0 ${lineGeom.width} ${lineGeom.height}`}
|
|
226
|
+
preserveAspectRatio="none"
|
|
227
|
+
>
|
|
228
|
+
<FlightLine geom={lineGeom} reduced={reduced} />
|
|
229
|
+
</svg>
|
|
230
|
+
)}
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
{/* Right: primitive */}
|
|
234
|
+
<div>
|
|
235
|
+
<div
|
|
236
|
+
className="mono"
|
|
237
|
+
style={{
|
|
238
|
+
fontSize: 11,
|
|
239
|
+
letterSpacing: '0.12em',
|
|
240
|
+
textTransform: 'uppercase',
|
|
241
|
+
color: 'var(--ink-2)',
|
|
242
|
+
padding: '10px 14px',
|
|
243
|
+
borderBottom: 'var(--hair)',
|
|
244
|
+
}}
|
|
245
|
+
>
|
|
246
|
+
primitive
|
|
247
|
+
</div>
|
|
248
|
+
{primitiveRows.map((row, i) => {
|
|
249
|
+
const isTarget = activeTargetPath === row.path;
|
|
250
|
+
return (
|
|
251
|
+
<div
|
|
252
|
+
key={row.path}
|
|
253
|
+
ref={(el) => (primitiveRefs.current[i] = el)}
|
|
254
|
+
role="row"
|
|
255
|
+
style={{
|
|
256
|
+
display: 'grid',
|
|
257
|
+
gridTemplateColumns: '1fr auto',
|
|
258
|
+
alignItems: 'center',
|
|
259
|
+
gap: 12,
|
|
260
|
+
padding: '10px 14px',
|
|
261
|
+
borderBottom: i === primitiveRows.length - 1 ? 0 : '1px solid var(--ink-3)',
|
|
262
|
+
background: isTarget ? 'var(--paper)' : 'transparent',
|
|
263
|
+
boxShadow: isTarget ? 'inset 3px 0 0 var(--accent)' : 'none',
|
|
264
|
+
}}
|
|
265
|
+
>
|
|
266
|
+
<span className="mono" style={{ fontSize: 12 }}>
|
|
267
|
+
{row.path.replace(/^primitive\./, '')}
|
|
268
|
+
</span>
|
|
269
|
+
<ValueSample row={row} highlighted={isTarget} />
|
|
270
|
+
</div>
|
|
271
|
+
);
|
|
272
|
+
})}
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
{/* Live region for screen readers */}
|
|
277
|
+
<div
|
|
278
|
+
aria-live="polite"
|
|
279
|
+
style={{
|
|
280
|
+
position: 'absolute',
|
|
281
|
+
width: 1,
|
|
282
|
+
height: 1,
|
|
283
|
+
overflow: 'hidden',
|
|
284
|
+
clip: 'rect(0 0 0 0)',
|
|
285
|
+
}}
|
|
286
|
+
>
|
|
287
|
+
{activeRow
|
|
288
|
+
? `${activeRow.path} resolves to ${activeTargetPath || activeRow.$value} — ${activeResolved || ''}`
|
|
289
|
+
: ''}
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
|
|
293
|
+
<Marginalia>
|
|
294
|
+
<div>taxonomy</div>
|
|
295
|
+
<div>
|
|
296
|
+
Semantic tokens describe intent. Primitive tokens describe values.
|
|
297
|
+
designlang writes both in W3C DTCG so your consumer can choose which layer to bind to.
|
|
298
|
+
</div>
|
|
299
|
+
<hr style={{ margin: '12px 0', border: 0, borderTop: '1px solid var(--ink-3)' }} />
|
|
300
|
+
<div>produced by</div>
|
|
301
|
+
<div><code>{sampleCommand}</code></div>
|
|
302
|
+
</Marginalia>
|
|
303
|
+
</div>
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function FlightLine({ geom, reduced }) {
|
|
308
|
+
const { x1, y1, x2, y2 } = geom;
|
|
309
|
+
// Curve control points for a smooth horizontal flight path.
|
|
310
|
+
const midX = (x1 + x2) / 2;
|
|
311
|
+
const d = `M ${x1} ${y1} C ${midX} ${y1}, ${midX} ${y2}, ${x2} ${y2}`;
|
|
312
|
+
|
|
313
|
+
const pathRef = useRef(null);
|
|
314
|
+
const [len, setLen] = useState(0);
|
|
315
|
+
useEffect(() => {
|
|
316
|
+
if (pathRef.current) setLen(pathRef.current.getTotalLength());
|
|
317
|
+
}, [x1, y1, x2, y2]);
|
|
318
|
+
|
|
319
|
+
return (
|
|
320
|
+
<>
|
|
321
|
+
<path
|
|
322
|
+
ref={pathRef}
|
|
323
|
+
d={d}
|
|
324
|
+
fill="none"
|
|
325
|
+
stroke="var(--accent)"
|
|
326
|
+
strokeWidth="1.5"
|
|
327
|
+
strokeDasharray={reduced ? '0' : len}
|
|
328
|
+
strokeDashoffset={reduced ? 0 : len}
|
|
329
|
+
style={{
|
|
330
|
+
animation: reduced ? 'none' : 'designlang-flight 320ms ease-out forwards',
|
|
331
|
+
}}
|
|
332
|
+
/>
|
|
333
|
+
<circle cx={x2} cy={y2} r="3" fill="var(--accent)" />
|
|
334
|
+
<style>{`
|
|
335
|
+
@keyframes designlang-flight {
|
|
336
|
+
to { stroke-dashoffset: 0; }
|
|
337
|
+
}
|
|
338
|
+
@media (prefers-reduced-motion: reduce) {
|
|
339
|
+
@keyframes designlang-flight { to { stroke-dashoffset: 0; } }
|
|
340
|
+
}
|
|
341
|
+
`}</style>
|
|
342
|
+
</>
|
|
343
|
+
);
|
|
344
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Hand-curated DTCG sample shaped exactly like formatDtcgTokens() output.
|
|
2
|
+
// Derived from the Stripe PR B smoke run; used as seed data for <TokenBrowser />.
|
|
3
|
+
|
|
4
|
+
export const sampleTokens = {
|
|
5
|
+
$metadata: {
|
|
6
|
+
generator: 'designlang',
|
|
7
|
+
version: '7.0.0',
|
|
8
|
+
spec: 'https://design-tokens.github.io/community-group/format/',
|
|
9
|
+
source: 'https://stripe.com',
|
|
10
|
+
},
|
|
11
|
+
primitive: {
|
|
12
|
+
color: {
|
|
13
|
+
brand: {
|
|
14
|
+
primary: { $value: '#533afd', $type: 'color' },
|
|
15
|
+
secondary: { $value: '#0a2540', $type: 'color' },
|
|
16
|
+
},
|
|
17
|
+
neutral: {
|
|
18
|
+
n100: { $value: '#f6f9fc', $type: 'color' },
|
|
19
|
+
n500: { $value: '#8792a2', $type: 'color' },
|
|
20
|
+
n900: { $value: '#0a2540', $type: 'color' },
|
|
21
|
+
},
|
|
22
|
+
background: {
|
|
23
|
+
bg0: { $value: '#ffffff', $type: 'color' },
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
radius: {
|
|
27
|
+
r0: { $value: '4px', $type: 'dimension' },
|
|
28
|
+
r1: { $value: '8px', $type: 'dimension' },
|
|
29
|
+
},
|
|
30
|
+
spacing: {
|
|
31
|
+
s2: { $value: '8px', $type: 'dimension' },
|
|
32
|
+
s4: { $value: '16px', $type: 'dimension' },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
semantic: {
|
|
36
|
+
color: {
|
|
37
|
+
action: {
|
|
38
|
+
primary: { $value: '{primitive.color.brand.primary}', $type: 'color' },
|
|
39
|
+
},
|
|
40
|
+
surface: {
|
|
41
|
+
default: { $value: '{primitive.color.background.bg0}', $type: 'color' },
|
|
42
|
+
},
|
|
43
|
+
text: {
|
|
44
|
+
body: { $value: '{primitive.color.neutral.n900}', $type: 'color' },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
radius: {
|
|
48
|
+
control: { $value: '{primitive.radius.r1}', $type: 'dimension' },
|
|
49
|
+
},
|
|
50
|
+
typography: {
|
|
51
|
+
body: {
|
|
52
|
+
$value: {
|
|
53
|
+
fontFamily: 'sohne-var, Helvetica Neue, Arial, sans-serif',
|
|
54
|
+
fontSize: '16px',
|
|
55
|
+
fontWeight: '400',
|
|
56
|
+
lineHeight: '1.5',
|
|
57
|
+
},
|
|
58
|
+
$type: 'typography',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// The CLI invocation that produced the sample.
|
|
65
|
+
export const sampleCommand = '$ npx designlang https://stripe.com --format dtcg';
|