@discourser/design-system 0.25.3 → 0.27.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 +76 -73
- package/dist/{chunk-ZPECW4N2.js → chunk-4XOWPACJ.js} +257 -105
- package/dist/chunk-4XOWPACJ.js.map +1 -0
- package/dist/{chunk-QNCZYFUJ.cjs → chunk-AZ6QU2L2.cjs} +257 -105
- package/dist/chunk-AZ6QU2L2.cjs.map +1 -0
- package/dist/{chunk-TBLDQATQ.cjs → chunk-EBDNCZF6.cjs} +94 -54
- package/dist/chunk-EBDNCZF6.cjs.map +1 -0
- package/dist/{chunk-UHSL4N44.js → chunk-MAVUSE4F.js} +94 -55
- package/dist/chunk-MAVUSE4F.js.map +1 -0
- package/dist/components/Checkbox.d.ts +1 -1
- package/dist/components/Icons/LeftArrowIcon.d.ts +6 -0
- package/dist/components/Icons/LeftArrowIcon.d.ts.map +1 -0
- package/dist/components/Icons/RightArrowIcon.d.ts.map +1 -1
- package/dist/components/Icons/index.d.ts +1 -0
- package/dist/components/Icons/index.d.ts.map +1 -1
- package/dist/components/index.cjs +79 -75
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/contracts/design-language.contract.d.ts +52 -18
- package/dist/contracts/design-language.contract.d.ts.map +1 -1
- package/dist/figma-codex.json +2 -2
- package/dist/index.cjs +83 -79
- package/dist/index.js +2 -2
- package/dist/languages/material3.language.d.ts.map +1 -1
- package/dist/languages/transform.d.ts +5 -5
- package/dist/languages/transform.d.ts.map +1 -1
- package/dist/preset/index.cjs +2 -2
- package/dist/preset/index.js +1 -1
- package/docs/component-catalog.md +469 -0
- package/docs/superpowers/plans/2026-04-03-component-catalog-pipeline.md +667 -0
- package/docs/token-name-mapping.json +614 -42
- package/docs/token-name-mapping.md +117 -29
- package/package.json +3 -2
- package/src/components/Icons/LeftArrowIcon.tsx +28 -0
- package/src/components/Icons/RightArrowIcon.tsx +7 -2
- package/src/components/Icons/index.ts +1 -0
- package/src/components/__tests__/AbsoluteCenter.test.tsx +31 -0
- package/src/components/__tests__/Divider.test.tsx +38 -0
- package/src/components/__tests__/Group.test.tsx +34 -0
- package/src/components/__tests__/Icon.test.tsx +31 -0
- package/src/components/__tests__/SettingsPopover.test.tsx +39 -0
- package/src/components/__tests__/StudioControls.test.tsx +59 -0
- package/src/components/__tests__/Toaster.test.tsx +24 -0
- package/src/components/index.ts +1 -0
- package/src/contracts/design-language.contract.ts +69 -20
- package/src/languages/material3.language.ts +249 -80
- package/src/languages/transform.ts +45 -48
- package/src/preset/__tests__/translation-token-accuracy.test.ts +13 -0
- package/src/stories/foundations/Colors.mdx +9 -1
- package/src/stories/foundations/Elevation.mdx +23 -17
- package/src/stories/foundations/TokenReference.stories.tsx +970 -0
- package/src/stories/foundations/TonalPaletteDerivation.stories.tsx +782 -0
- package/src/stories/foundations/Typography.mdx +125 -25
- package/dist/chunk-QNCZYFUJ.cjs.map +0 -1
- package/dist/chunk-TBLDQATQ.cjs.map +0 -1
- package/dist/chunk-UHSL4N44.js.map +0 -1
- package/dist/chunk-ZPECW4N2.js.map +0 -1
- package/docs/context-share/ELEVATION_FIX_PLAN.md +0 -903
- package/docs/context-share/fix-checkbox-radio-tokens.md +0 -145
- package/docs/context-share/icon-component-prompt.md +0 -154
|
@@ -0,0 +1,970 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Reference — auto-generated from docs/token-name-mapping.json
|
|
3
|
+
*
|
|
4
|
+
* This file imports the JSON directly. It is always current — no manual
|
|
5
|
+
* editing required. To update the tables, run:
|
|
6
|
+
*
|
|
7
|
+
* pnpm figma:export
|
|
8
|
+
*
|
|
9
|
+
* then rebuild Storybook. The JSON is regenerated by
|
|
10
|
+
* scripts/export-figma-tokens.ts as part of that command.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
14
|
+
import type { CSSProperties } from 'react';
|
|
15
|
+
import tokenMap from '../../../docs/token-name-mapping.json';
|
|
16
|
+
|
|
17
|
+
// ── Types inferred from the JSON shape ───────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
interface SemanticEntry {
|
|
20
|
+
figmaPath: string;
|
|
21
|
+
pandaToken: string;
|
|
22
|
+
cssProperty: string;
|
|
23
|
+
exampleUsage: string;
|
|
24
|
+
note?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface SpacingShapeEntry {
|
|
28
|
+
figmaPath: string;
|
|
29
|
+
pandaToken: string;
|
|
30
|
+
pandaCategory: string;
|
|
31
|
+
cssProperty: string;
|
|
32
|
+
exampleUsage: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface EffectStyleEntry {
|
|
36
|
+
figmaEffectStyle: string;
|
|
37
|
+
pandaToken: string;
|
|
38
|
+
pandaCategory: string;
|
|
39
|
+
cssProperty: string;
|
|
40
|
+
description: string;
|
|
41
|
+
exampleUsage: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface PandaOnlyEntry {
|
|
45
|
+
pandaToken: string;
|
|
46
|
+
cssProperty: string;
|
|
47
|
+
notes?: string;
|
|
48
|
+
exampleUsage: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface ShadowAliasEntry {
|
|
52
|
+
pandaToken: string;
|
|
53
|
+
cssProperty: string;
|
|
54
|
+
resolvesTo: string;
|
|
55
|
+
description?: string;
|
|
56
|
+
exampleUsage: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface TextStyleEntry {
|
|
60
|
+
figmaTextStyle: string;
|
|
61
|
+
figmaDescription: string;
|
|
62
|
+
ddsTokenPath: string;
|
|
63
|
+
pandaTextStyle: string;
|
|
64
|
+
fontFamily: string;
|
|
65
|
+
fontStyle: string;
|
|
66
|
+
fontWeight: number;
|
|
67
|
+
fontSize: number;
|
|
68
|
+
lineHeightPx: number;
|
|
69
|
+
letterSpacing: number;
|
|
70
|
+
isDefaultWeight: boolean;
|
|
71
|
+
exampleUsage: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ── Shared style helpers ─────────────────────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
const T: Record<string, CSSProperties> = {
|
|
77
|
+
page: {
|
|
78
|
+
fontFamily: 'Inter, -apple-system, BlinkMacSystemFont, sans-serif',
|
|
79
|
+
fontSize: '14px',
|
|
80
|
+
color: '#1a1a1a',
|
|
81
|
+
maxWidth: '1100px',
|
|
82
|
+
},
|
|
83
|
+
section: {
|
|
84
|
+
marginBottom: '56px',
|
|
85
|
+
},
|
|
86
|
+
h2: {
|
|
87
|
+
fontSize: '20px',
|
|
88
|
+
fontWeight: '600',
|
|
89
|
+
margin: '0 0 4px',
|
|
90
|
+
color: '#111',
|
|
91
|
+
},
|
|
92
|
+
meta: {
|
|
93
|
+
fontSize: '12px',
|
|
94
|
+
color: '#888',
|
|
95
|
+
margin: '0 0 20px',
|
|
96
|
+
fontFamily: 'monospace',
|
|
97
|
+
},
|
|
98
|
+
table: {
|
|
99
|
+
width: '100%',
|
|
100
|
+
borderCollapse: 'collapse' as const,
|
|
101
|
+
fontSize: '13px',
|
|
102
|
+
},
|
|
103
|
+
th: {
|
|
104
|
+
textAlign: 'left' as const,
|
|
105
|
+
padding: '8px 12px',
|
|
106
|
+
background: '#f4f4f4',
|
|
107
|
+
borderBottom: '2px solid #e0e0e0',
|
|
108
|
+
fontWeight: '600',
|
|
109
|
+
fontSize: '12px',
|
|
110
|
+
color: '#444',
|
|
111
|
+
whiteSpace: 'nowrap' as const,
|
|
112
|
+
},
|
|
113
|
+
td: {
|
|
114
|
+
padding: '8px 12px',
|
|
115
|
+
borderBottom: '1px solid #f0f0f0',
|
|
116
|
+
verticalAlign: 'middle' as const,
|
|
117
|
+
},
|
|
118
|
+
mono: {
|
|
119
|
+
fontFamily: 'monospace',
|
|
120
|
+
fontSize: '12px',
|
|
121
|
+
background: '#f5f5f5',
|
|
122
|
+
padding: '2px 5px',
|
|
123
|
+
borderRadius: '3px',
|
|
124
|
+
color: '#333',
|
|
125
|
+
whiteSpace: 'nowrap' as const,
|
|
126
|
+
display: 'inline-block' as const,
|
|
127
|
+
},
|
|
128
|
+
pill: {
|
|
129
|
+
display: 'inline-block' as const,
|
|
130
|
+
fontSize: '10px',
|
|
131
|
+
fontWeight: '600',
|
|
132
|
+
padding: '1px 6px',
|
|
133
|
+
borderRadius: '10px',
|
|
134
|
+
background: '#e8f0e0',
|
|
135
|
+
color: '#3a5a18',
|
|
136
|
+
marginLeft: '6px',
|
|
137
|
+
verticalAlign: 'middle' as const,
|
|
138
|
+
},
|
|
139
|
+
warning: {
|
|
140
|
+
display: 'inline-block' as const,
|
|
141
|
+
fontSize: '10px',
|
|
142
|
+
fontWeight: '600',
|
|
143
|
+
padding: '1px 6px',
|
|
144
|
+
borderRadius: '10px',
|
|
145
|
+
background: '#fff3cd',
|
|
146
|
+
color: '#856404',
|
|
147
|
+
marginLeft: '6px',
|
|
148
|
+
verticalAlign: 'middle' as const,
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
function rowBg(i: number): CSSProperties {
|
|
153
|
+
return { background: i % 2 === 0 ? '#fff' : '#fafafa' };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ── Color swatch using CSS custom property directly ──────────────────────────
|
|
157
|
+
// We use the cssProperty value from the JSON (e.g. --colors-surface-container)
|
|
158
|
+
// to render a live swatch via inline style. This bypasses Panda's static
|
|
159
|
+
// extraction requirement and works with any token at runtime.
|
|
160
|
+
|
|
161
|
+
function Swatch({ cssVar, size = 32 }: { cssVar: string; size?: number }) {
|
|
162
|
+
return (
|
|
163
|
+
<div
|
|
164
|
+
style={{
|
|
165
|
+
display: 'inline-flex',
|
|
166
|
+
gap: '4px',
|
|
167
|
+
alignItems: 'center',
|
|
168
|
+
}}
|
|
169
|
+
>
|
|
170
|
+
{/* Light swatch */}
|
|
171
|
+
<div
|
|
172
|
+
title={`Light: var(${cssVar})`}
|
|
173
|
+
style={{
|
|
174
|
+
width: size,
|
|
175
|
+
height: size,
|
|
176
|
+
borderRadius: '4px',
|
|
177
|
+
border: '1px solid rgba(0,0,0,0.12)',
|
|
178
|
+
background: `var(${cssVar})`,
|
|
179
|
+
flexShrink: 0,
|
|
180
|
+
}}
|
|
181
|
+
/>
|
|
182
|
+
{/* Dark swatch — forced via data-theme attribute */}
|
|
183
|
+
<div
|
|
184
|
+
data-theme="dark"
|
|
185
|
+
title={`Dark: var(${cssVar})`}
|
|
186
|
+
style={{
|
|
187
|
+
width: size,
|
|
188
|
+
height: size,
|
|
189
|
+
borderRadius: '4px',
|
|
190
|
+
border: '1px solid rgba(255,255,255,0.15)',
|
|
191
|
+
background: `var(${cssVar})`,
|
|
192
|
+
flexShrink: 0,
|
|
193
|
+
}}
|
|
194
|
+
/>
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function SpacingSwatch({
|
|
200
|
+
cssVar,
|
|
201
|
+
category,
|
|
202
|
+
}: {
|
|
203
|
+
cssVar: string;
|
|
204
|
+
category: string;
|
|
205
|
+
}) {
|
|
206
|
+
if (category !== 'spacing') {
|
|
207
|
+
// For radii — show a box with the corner radius applied
|
|
208
|
+
return (
|
|
209
|
+
<div
|
|
210
|
+
title={`var(${cssVar})`}
|
|
211
|
+
style={{
|
|
212
|
+
width: 32,
|
|
213
|
+
height: 32,
|
|
214
|
+
background: '#4C662B',
|
|
215
|
+
borderRadius: `var(${cssVar})`,
|
|
216
|
+
flexShrink: 0,
|
|
217
|
+
border: '1px solid rgba(0,0,0,0.1)',
|
|
218
|
+
}}
|
|
219
|
+
/>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
// For spacing — show a bar whose width is the spacing value
|
|
223
|
+
return (
|
|
224
|
+
<div
|
|
225
|
+
style={{
|
|
226
|
+
display: 'flex',
|
|
227
|
+
alignItems: 'center',
|
|
228
|
+
gap: '4px',
|
|
229
|
+
minWidth: '80px',
|
|
230
|
+
}}
|
|
231
|
+
>
|
|
232
|
+
<div
|
|
233
|
+
title={`var(${cssVar})`}
|
|
234
|
+
style={{
|
|
235
|
+
height: '20px',
|
|
236
|
+
width: `var(${cssVar})`,
|
|
237
|
+
minWidth: '2px',
|
|
238
|
+
background: '#4C662B',
|
|
239
|
+
borderRadius: '2px',
|
|
240
|
+
flexShrink: 0,
|
|
241
|
+
}}
|
|
242
|
+
/>
|
|
243
|
+
</div>
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function ShadowSwatch({ cssVar }: { cssVar: string }) {
|
|
248
|
+
return (
|
|
249
|
+
<div
|
|
250
|
+
title={`var(${cssVar})`}
|
|
251
|
+
style={{
|
|
252
|
+
width: 40,
|
|
253
|
+
height: 32,
|
|
254
|
+
borderRadius: '6px',
|
|
255
|
+
background: '#fff',
|
|
256
|
+
boxShadow: `var(${cssVar})`,
|
|
257
|
+
border: '1px solid rgba(0,0,0,0.06)',
|
|
258
|
+
flexShrink: 0,
|
|
259
|
+
}}
|
|
260
|
+
/>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function TypeSwatch({
|
|
265
|
+
fontFamily,
|
|
266
|
+
fontWeight,
|
|
267
|
+
fontSize,
|
|
268
|
+
}: {
|
|
269
|
+
fontFamily: string;
|
|
270
|
+
fontWeight: number;
|
|
271
|
+
fontSize: number;
|
|
272
|
+
}) {
|
|
273
|
+
// Clamp display size so table rows don't get too tall
|
|
274
|
+
const displaySize = Math.min(fontSize, 22);
|
|
275
|
+
return (
|
|
276
|
+
<span
|
|
277
|
+
style={{
|
|
278
|
+
fontFamily,
|
|
279
|
+
fontWeight,
|
|
280
|
+
fontSize: `${displaySize}px`,
|
|
281
|
+
lineHeight: 1,
|
|
282
|
+
color: '#1a1a1a',
|
|
283
|
+
whiteSpace: 'nowrap',
|
|
284
|
+
}}
|
|
285
|
+
>
|
|
286
|
+
Aa
|
|
287
|
+
</span>
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// ── Storybook meta ────────────────────────────────────────────────────────────
|
|
292
|
+
|
|
293
|
+
const meta = {
|
|
294
|
+
title: 'Foundations/Token Reference',
|
|
295
|
+
parameters: { layout: 'padded' },
|
|
296
|
+
} satisfies Meta;
|
|
297
|
+
|
|
298
|
+
export default meta;
|
|
299
|
+
type Story = StoryObj<typeof meta>;
|
|
300
|
+
|
|
301
|
+
// ── Story 1: Semantic Colors ─────────────────────────────────────────────────
|
|
302
|
+
|
|
303
|
+
export const SemanticColors: Story = {
|
|
304
|
+
name: '1 · Semantic Colors',
|
|
305
|
+
render: () => {
|
|
306
|
+
const entries = tokenMap.semantic as SemanticEntry[];
|
|
307
|
+
const pandaOnly = (tokenMap.semanticPandaOnly ?? []) as PandaOnlyEntry[];
|
|
308
|
+
|
|
309
|
+
// Mismatches flagged in token-name-mapping.md
|
|
310
|
+
const mismatches = new Set([
|
|
311
|
+
'surfaceVariant',
|
|
312
|
+
'inverseSurface',
|
|
313
|
+
'inverseOnSurface',
|
|
314
|
+
'inversePrimary',
|
|
315
|
+
]);
|
|
316
|
+
|
|
317
|
+
return (
|
|
318
|
+
<div style={T.page}>
|
|
319
|
+
<div style={T.section}>
|
|
320
|
+
<h2 style={T.h2}>Semantic Colors</h2>
|
|
321
|
+
<p style={T.meta}>
|
|
322
|
+
{entries.length} entries · source: Figma "Semantic"
|
|
323
|
+
collection · auto-generated from docs/token-name-mapping.json v
|
|
324
|
+
{tokenMap.version}
|
|
325
|
+
</p>
|
|
326
|
+
|
|
327
|
+
<table style={T.table}>
|
|
328
|
+
<thead>
|
|
329
|
+
<tr>
|
|
330
|
+
<th style={T.th}>Swatch (L / D)</th>
|
|
331
|
+
<th style={T.th}>Figma Variable Path</th>
|
|
332
|
+
<th style={T.th}>Panda CSS Token</th>
|
|
333
|
+
<th style={T.th}>CSS Custom Property</th>
|
|
334
|
+
<th style={T.th}>Code Usage</th>
|
|
335
|
+
</tr>
|
|
336
|
+
</thead>
|
|
337
|
+
<tbody>
|
|
338
|
+
{entries.map((e, i) => (
|
|
339
|
+
<tr key={e.figmaPath} style={rowBg(i)}>
|
|
340
|
+
<td style={T.td}>
|
|
341
|
+
<Swatch cssVar={e.cssProperty} />
|
|
342
|
+
</td>
|
|
343
|
+
<td style={T.td}>
|
|
344
|
+
<span style={T.mono}>{e.figmaPath}</span>
|
|
345
|
+
</td>
|
|
346
|
+
<td style={T.td}>
|
|
347
|
+
<span style={T.mono}>{e.pandaToken}</span>
|
|
348
|
+
{mismatches.has(e.pandaToken) && (
|
|
349
|
+
<span
|
|
350
|
+
style={T.warning}
|
|
351
|
+
title="Not dot-notation — see mismatch notes"
|
|
352
|
+
>
|
|
353
|
+
⚠ flat
|
|
354
|
+
</span>
|
|
355
|
+
)}
|
|
356
|
+
</td>
|
|
357
|
+
<td style={T.td}>
|
|
358
|
+
<span style={{ ...T.mono, color: '#666' }}>
|
|
359
|
+
{e.cssProperty}
|
|
360
|
+
</span>
|
|
361
|
+
</td>
|
|
362
|
+
<td style={T.td}>
|
|
363
|
+
<span style={{ ...T.mono, background: '#eef4e8' }}>
|
|
364
|
+
{e.exampleUsage}
|
|
365
|
+
</span>
|
|
366
|
+
</td>
|
|
367
|
+
</tr>
|
|
368
|
+
))}
|
|
369
|
+
</tbody>
|
|
370
|
+
</table>
|
|
371
|
+
|
|
372
|
+
{pandaOnly.length > 0 && (
|
|
373
|
+
<>
|
|
374
|
+
<h3
|
|
375
|
+
style={{
|
|
376
|
+
fontSize: '15px',
|
|
377
|
+
fontWeight: '600',
|
|
378
|
+
margin: '32px 0 12px',
|
|
379
|
+
color: '#333',
|
|
380
|
+
}}
|
|
381
|
+
>
|
|
382
|
+
Panda-only tokens (no Figma variable)
|
|
383
|
+
</h3>
|
|
384
|
+
<table style={T.table}>
|
|
385
|
+
<thead>
|
|
386
|
+
<tr>
|
|
387
|
+
<th style={T.th}>Swatch (L / D)</th>
|
|
388
|
+
<th style={T.th}>Panda CSS Token</th>
|
|
389
|
+
<th style={T.th}>CSS Custom Property</th>
|
|
390
|
+
<th style={T.th}>Code Usage</th>
|
|
391
|
+
<th style={T.th}>Notes</th>
|
|
392
|
+
</tr>
|
|
393
|
+
</thead>
|
|
394
|
+
<tbody>
|
|
395
|
+
{pandaOnly.map((e, i) => (
|
|
396
|
+
<tr key={e.pandaToken} style={rowBg(i)}>
|
|
397
|
+
<td style={T.td}>
|
|
398
|
+
<Swatch cssVar={e.cssProperty} />
|
|
399
|
+
</td>
|
|
400
|
+
<td style={T.td}>
|
|
401
|
+
<span style={T.mono}>{e.pandaToken}</span>
|
|
402
|
+
</td>
|
|
403
|
+
<td style={T.td}>
|
|
404
|
+
<span style={{ ...T.mono, color: '#666' }}>
|
|
405
|
+
{e.cssProperty}
|
|
406
|
+
</span>
|
|
407
|
+
</td>
|
|
408
|
+
<td style={T.td}>
|
|
409
|
+
<span style={{ ...T.mono, background: '#eef4e8' }}>
|
|
410
|
+
{e.exampleUsage}
|
|
411
|
+
</span>
|
|
412
|
+
</td>
|
|
413
|
+
<td style={{ ...T.td, color: '#666', fontSize: '12px' }}>
|
|
414
|
+
{e.notes ?? '—'}
|
|
415
|
+
</td>
|
|
416
|
+
</tr>
|
|
417
|
+
))}
|
|
418
|
+
</tbody>
|
|
419
|
+
</table>
|
|
420
|
+
</>
|
|
421
|
+
)}
|
|
422
|
+
|
|
423
|
+
<div
|
|
424
|
+
style={{
|
|
425
|
+
marginTop: '20px',
|
|
426
|
+
padding: '12px 16px',
|
|
427
|
+
background: '#fff8e1',
|
|
428
|
+
borderRadius: '6px',
|
|
429
|
+
fontSize: '12px',
|
|
430
|
+
color: '#555',
|
|
431
|
+
lineHeight: 1.6,
|
|
432
|
+
}}
|
|
433
|
+
>
|
|
434
|
+
<strong>⚠ Mismatch tokens</strong> — five tokens do NOT follow
|
|
435
|
+
dot-notation despite slash-path Figma naming:{' '}
|
|
436
|
+
<code>surfaceVariant</code>, <code>inverseSurface</code>,{' '}
|
|
437
|
+
<code>inverseOnSurface</code>, <code>inversePrimary</code>,{' '}
|
|
438
|
+
<code>inverseSecondary</code>, <code>inverseTertiary</code>. Use the
|
|
439
|
+
Panda CSS token column exactly — never derive it from the Figma path
|
|
440
|
+
by replacing <code>/</code> with <code>.</code>.
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
</div>
|
|
444
|
+
);
|
|
445
|
+
},
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
// ── Story 2: Spacing & Shape ─────────────────────────────────────────────────
|
|
449
|
+
|
|
450
|
+
export const SpacingAndShape: Story = {
|
|
451
|
+
name: '2 · Spacing & Shape',
|
|
452
|
+
render: () => {
|
|
453
|
+
const entries = tokenMap.spacingAndShape as SpacingShapeEntry[];
|
|
454
|
+
|
|
455
|
+
const categories = ['spacing', 'radii', 'borderWidths', 'durations'];
|
|
456
|
+
|
|
457
|
+
return (
|
|
458
|
+
<div style={T.page}>
|
|
459
|
+
{categories.map((cat) => {
|
|
460
|
+
const rows = entries.filter((e) => e.pandaCategory === cat);
|
|
461
|
+
if (rows.length === 0) return null;
|
|
462
|
+
|
|
463
|
+
const catLabel: Record<string, string> = {
|
|
464
|
+
spacing: 'Spacing',
|
|
465
|
+
radii: 'Border Radii (M3 base tokens)',
|
|
466
|
+
borderWidths: 'Border Widths',
|
|
467
|
+
durations: 'Motion Durations',
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
return (
|
|
471
|
+
<div key={cat} style={T.section}>
|
|
472
|
+
<h2 style={T.h2}>{catLabel[cat] ?? cat}</h2>
|
|
473
|
+
<p style={T.meta}>
|
|
474
|
+
{rows.length} entries · Figma "Spacing & Shape"
|
|
475
|
+
collection · v{tokenMap.version}
|
|
476
|
+
</p>
|
|
477
|
+
|
|
478
|
+
<table style={T.table}>
|
|
479
|
+
<thead>
|
|
480
|
+
<tr>
|
|
481
|
+
{cat === 'spacing' || cat === 'radii' ? (
|
|
482
|
+
<th style={T.th}>Visual</th>
|
|
483
|
+
) : null}
|
|
484
|
+
<th style={T.th}>Figma Variable Path</th>
|
|
485
|
+
<th style={T.th}>Panda CSS Token</th>
|
|
486
|
+
<th style={T.th}>CSS Custom Property</th>
|
|
487
|
+
<th style={T.th}>Code Usage</th>
|
|
488
|
+
</tr>
|
|
489
|
+
</thead>
|
|
490
|
+
<tbody>
|
|
491
|
+
{rows.map((e, i) => (
|
|
492
|
+
<tr key={e.figmaPath} style={rowBg(i)}>
|
|
493
|
+
{cat === 'spacing' || cat === 'radii' ? (
|
|
494
|
+
<td style={T.td}>
|
|
495
|
+
<SpacingSwatch
|
|
496
|
+
cssVar={e.cssProperty}
|
|
497
|
+
category={cat}
|
|
498
|
+
/>
|
|
499
|
+
</td>
|
|
500
|
+
) : null}
|
|
501
|
+
<td style={T.td}>
|
|
502
|
+
<span style={T.mono}>{e.figmaPath}</span>
|
|
503
|
+
</td>
|
|
504
|
+
<td style={T.td}>
|
|
505
|
+
<span style={T.mono}>{e.pandaToken}</span>
|
|
506
|
+
{cat === 'radii' && (
|
|
507
|
+
<span
|
|
508
|
+
style={{
|
|
509
|
+
...T.warning,
|
|
510
|
+
background: '#e8f0e0',
|
|
511
|
+
color: '#3a5a18',
|
|
512
|
+
}}
|
|
513
|
+
title="Use l1/l2/l3/full in component code, not this M3 base token"
|
|
514
|
+
>
|
|
515
|
+
base
|
|
516
|
+
</span>
|
|
517
|
+
)}
|
|
518
|
+
</td>
|
|
519
|
+
<td style={T.td}>
|
|
520
|
+
<span style={{ ...T.mono, color: '#666' }}>
|
|
521
|
+
{e.cssProperty}
|
|
522
|
+
</span>
|
|
523
|
+
</td>
|
|
524
|
+
<td style={T.td}>
|
|
525
|
+
<span style={{ ...T.mono, background: '#eef4e8' }}>
|
|
526
|
+
{e.exampleUsage}
|
|
527
|
+
</span>
|
|
528
|
+
</td>
|
|
529
|
+
</tr>
|
|
530
|
+
))}
|
|
531
|
+
</tbody>
|
|
532
|
+
</table>
|
|
533
|
+
|
|
534
|
+
{cat === 'radii' && (
|
|
535
|
+
<div
|
|
536
|
+
style={{
|
|
537
|
+
marginTop: '12px',
|
|
538
|
+
padding: '12px 16px',
|
|
539
|
+
background: '#e8f0e0',
|
|
540
|
+
borderRadius: '6px',
|
|
541
|
+
fontSize: '12px',
|
|
542
|
+
color: '#3a5a18',
|
|
543
|
+
lineHeight: 1.6,
|
|
544
|
+
}}
|
|
545
|
+
>
|
|
546
|
+
<strong>Use DDS canonical radii in component code</strong> —
|
|
547
|
+
not these M3 base tokens. <code>l1</code> = 2px (checkboxes,
|
|
548
|
+
breadcrumbs) · <code>l2</code> = 6px (buttons, inputs, badges)
|
|
549
|
+
· <code>l3</code> = 8px (cards, dialogs, popovers) ·{' '}
|
|
550
|
+
<code>full</code> = 9999px (avatars, pills, switches)
|
|
551
|
+
</div>
|
|
552
|
+
)}
|
|
553
|
+
</div>
|
|
554
|
+
);
|
|
555
|
+
})}
|
|
556
|
+
</div>
|
|
557
|
+
);
|
|
558
|
+
},
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// ── Story 3: Elevation & Shadows ─────────────────────────────────────────────
|
|
562
|
+
|
|
563
|
+
export const ElevationAndShadows: Story = {
|
|
564
|
+
name: '3 · Elevation & Shadows',
|
|
565
|
+
render: () => {
|
|
566
|
+
const baseLevels = tokenMap.effectStyles as EffectStyleEntry[];
|
|
567
|
+
const aliases = (tokenMap.shadowSemanticAliases ??
|
|
568
|
+
[]) as ShadowAliasEntry[];
|
|
569
|
+
|
|
570
|
+
return (
|
|
571
|
+
<div style={T.page}>
|
|
572
|
+
<div style={T.section}>
|
|
573
|
+
<h2 style={T.h2}>Base Elevation Levels (M3)</h2>
|
|
574
|
+
<p style={T.meta}>
|
|
575
|
+
{baseLevels.length} levels · Figma effect styles · v
|
|
576
|
+
{tokenMap.version}
|
|
577
|
+
</p>
|
|
578
|
+
|
|
579
|
+
<table style={T.table}>
|
|
580
|
+
<thead>
|
|
581
|
+
<tr>
|
|
582
|
+
<th style={T.th}>Visual</th>
|
|
583
|
+
<th style={T.th}>Figma Effect Style</th>
|
|
584
|
+
<th style={T.th}>Panda Base Token</th>
|
|
585
|
+
<th style={T.th}>CSS Custom Property</th>
|
|
586
|
+
<th style={T.th}>Description</th>
|
|
587
|
+
<th style={T.th}>Code Usage</th>
|
|
588
|
+
</tr>
|
|
589
|
+
</thead>
|
|
590
|
+
<tbody>
|
|
591
|
+
{baseLevels.map((e, i) => (
|
|
592
|
+
<tr key={e.figmaEffectStyle} style={rowBg(i)}>
|
|
593
|
+
<td style={T.td}>
|
|
594
|
+
<ShadowSwatch cssVar={e.cssProperty} />
|
|
595
|
+
</td>
|
|
596
|
+
<td style={T.td}>
|
|
597
|
+
<span style={T.mono}>{e.figmaEffectStyle}</span>
|
|
598
|
+
</td>
|
|
599
|
+
<td style={T.td}>
|
|
600
|
+
<span style={T.mono}>{e.pandaToken}</span>
|
|
601
|
+
<span
|
|
602
|
+
style={T.warning}
|
|
603
|
+
title="Use semantic alias (xs/sm/md/lg/xl) in component code"
|
|
604
|
+
>
|
|
605
|
+
base
|
|
606
|
+
</span>
|
|
607
|
+
</td>
|
|
608
|
+
<td style={T.td}>
|
|
609
|
+
<span style={{ ...T.mono, color: '#666' }}>
|
|
610
|
+
{e.cssProperty}
|
|
611
|
+
</span>
|
|
612
|
+
</td>
|
|
613
|
+
<td style={{ ...T.td, color: '#555', fontSize: '12px' }}>
|
|
614
|
+
{e.description}
|
|
615
|
+
</td>
|
|
616
|
+
<td style={T.td}>
|
|
617
|
+
<span
|
|
618
|
+
style={{
|
|
619
|
+
...T.mono,
|
|
620
|
+
background: '#fff3cd',
|
|
621
|
+
color: '#856404',
|
|
622
|
+
}}
|
|
623
|
+
>
|
|
624
|
+
{e.exampleUsage}
|
|
625
|
+
</span>
|
|
626
|
+
</td>
|
|
627
|
+
</tr>
|
|
628
|
+
))}
|
|
629
|
+
</tbody>
|
|
630
|
+
</table>
|
|
631
|
+
|
|
632
|
+
<div
|
|
633
|
+
style={{
|
|
634
|
+
marginTop: '12px',
|
|
635
|
+
padding: '12px 16px',
|
|
636
|
+
background: '#fff3cd',
|
|
637
|
+
borderRadius: '6px',
|
|
638
|
+
fontSize: '12px',
|
|
639
|
+
color: '#856404',
|
|
640
|
+
lineHeight: 1.6,
|
|
641
|
+
}}
|
|
642
|
+
>
|
|
643
|
+
<strong>Do not use base level tokens in component code.</strong> Use
|
|
644
|
+
the semantic aliases below (xs/sm/md/lg/xl).
|
|
645
|
+
</div>
|
|
646
|
+
</div>
|
|
647
|
+
|
|
648
|
+
{aliases.length > 0 && (
|
|
649
|
+
<div style={T.section}>
|
|
650
|
+
<h2 style={T.h2}>Semantic Shadow Aliases</h2>
|
|
651
|
+
<p style={T.meta}>
|
|
652
|
+
{aliases.length} aliases · src/preset/shadows.ts · use these in
|
|
653
|
+
components and recipes
|
|
654
|
+
</p>
|
|
655
|
+
|
|
656
|
+
<table style={T.table}>
|
|
657
|
+
<thead>
|
|
658
|
+
<tr>
|
|
659
|
+
<th style={T.th}>Visual</th>
|
|
660
|
+
<th style={T.th}>Panda Token</th>
|
|
661
|
+
<th style={T.th}>CSS Custom Property</th>
|
|
662
|
+
<th style={T.th}>Resolves To</th>
|
|
663
|
+
<th style={T.th}>Description</th>
|
|
664
|
+
<th style={T.th}>Code Usage</th>
|
|
665
|
+
</tr>
|
|
666
|
+
</thead>
|
|
667
|
+
<tbody>
|
|
668
|
+
{aliases.map((e, i) => (
|
|
669
|
+
<tr key={e.pandaToken} style={rowBg(i)}>
|
|
670
|
+
<td style={T.td}>
|
|
671
|
+
<ShadowSwatch cssVar={e.cssProperty} />
|
|
672
|
+
</td>
|
|
673
|
+
<td style={T.td}>
|
|
674
|
+
<span style={{ ...T.mono, fontWeight: '600' }}>
|
|
675
|
+
{e.pandaToken}
|
|
676
|
+
</span>
|
|
677
|
+
</td>
|
|
678
|
+
<td style={T.td}>
|
|
679
|
+
<span style={{ ...T.mono, color: '#666' }}>
|
|
680
|
+
{e.cssProperty}
|
|
681
|
+
</span>
|
|
682
|
+
</td>
|
|
683
|
+
<td style={T.td}>
|
|
684
|
+
<span style={T.mono}>{e.resolvesTo}</span>
|
|
685
|
+
</td>
|
|
686
|
+
<td style={{ ...T.td, color: '#555', fontSize: '12px' }}>
|
|
687
|
+
{e.description ?? '—'}
|
|
688
|
+
</td>
|
|
689
|
+
<td style={T.td}>
|
|
690
|
+
<span style={{ ...T.mono, background: '#eef4e8' }}>
|
|
691
|
+
{e.exampleUsage}
|
|
692
|
+
</span>
|
|
693
|
+
</td>
|
|
694
|
+
</tr>
|
|
695
|
+
))}
|
|
696
|
+
</tbody>
|
|
697
|
+
</table>
|
|
698
|
+
</div>
|
|
699
|
+
)}
|
|
700
|
+
</div>
|
|
701
|
+
);
|
|
702
|
+
},
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
// ── Story 4: Typography ───────────────────────────────────────────────────────
|
|
706
|
+
|
|
707
|
+
export const Typography: Story = {
|
|
708
|
+
name: '4 · Typography',
|
|
709
|
+
render: () => {
|
|
710
|
+
const entries = tokenMap.textStyles as TextStyleEntry[];
|
|
711
|
+
|
|
712
|
+
// Group by pandaTextStyle (scale step)
|
|
713
|
+
const groups = entries.reduce<Record<string, TextStyleEntry[]>>(
|
|
714
|
+
(acc, e) => {
|
|
715
|
+
if (!acc[e.pandaTextStyle]) acc[e.pandaTextStyle] = [];
|
|
716
|
+
acc[e.pandaTextStyle].push(e);
|
|
717
|
+
return acc;
|
|
718
|
+
},
|
|
719
|
+
{},
|
|
720
|
+
);
|
|
721
|
+
|
|
722
|
+
const categoryOrder = [
|
|
723
|
+
'displayLarge',
|
|
724
|
+
'displayMedium',
|
|
725
|
+
'displaySmall',
|
|
726
|
+
'headlineLarge',
|
|
727
|
+
'headlineMedium',
|
|
728
|
+
'headlineSmall',
|
|
729
|
+
'titleLarge',
|
|
730
|
+
'titleMedium',
|
|
731
|
+
'titleSmall',
|
|
732
|
+
'bodyLarge',
|
|
733
|
+
'bodyMedium',
|
|
734
|
+
'bodySmall',
|
|
735
|
+
'labelLarge',
|
|
736
|
+
'labelMedium',
|
|
737
|
+
'labelSmall',
|
|
738
|
+
];
|
|
739
|
+
|
|
740
|
+
const categoryLabel: Record<string, string> = {
|
|
741
|
+
displayLarge: 'Display',
|
|
742
|
+
headlineLarge: 'Headline',
|
|
743
|
+
titleLarge: 'Title',
|
|
744
|
+
bodyLarge: 'Body',
|
|
745
|
+
labelLarge: 'Label',
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
let rowIndex = 0;
|
|
749
|
+
|
|
750
|
+
return (
|
|
751
|
+
<div style={T.page}>
|
|
752
|
+
<h2 style={T.h2}>Typography — All Weight Variants</h2>
|
|
753
|
+
<p style={T.meta}>
|
|
754
|
+
{entries.length} entries ({categoryOrder.length} scale steps × weight
|
|
755
|
+
variants) · auto-generated from docs/token-name-mapping.json v
|
|
756
|
+
{tokenMap.version}
|
|
757
|
+
</p>
|
|
758
|
+
|
|
759
|
+
<table style={T.table}>
|
|
760
|
+
<thead>
|
|
761
|
+
<tr>
|
|
762
|
+
<th style={T.th}>Preview</th>
|
|
763
|
+
<th style={T.th}>Figma Text Style</th>
|
|
764
|
+
<th style={T.th}>DDS Token Path</th>
|
|
765
|
+
<th style={T.th}>Panda textStyle</th>
|
|
766
|
+
<th style={T.th}>Font / Weight</th>
|
|
767
|
+
<th style={T.th}>Size / LH</th>
|
|
768
|
+
<th style={T.th}>Code Usage</th>
|
|
769
|
+
</tr>
|
|
770
|
+
</thead>
|
|
771
|
+
<tbody>
|
|
772
|
+
{categoryOrder.flatMap((step) => {
|
|
773
|
+
const rows = groups[step] ?? [];
|
|
774
|
+
return rows.map((e) => {
|
|
775
|
+
const i = rowIndex++;
|
|
776
|
+
const isDefault = e.isDefaultWeight;
|
|
777
|
+
return (
|
|
778
|
+
<tr key={e.figmaTextStyle} style={rowBg(i)}>
|
|
779
|
+
<td style={T.td}>
|
|
780
|
+
<TypeSwatch
|
|
781
|
+
fontFamily={e.fontFamily}
|
|
782
|
+
fontWeight={e.fontWeight}
|
|
783
|
+
fontSize={e.fontSize}
|
|
784
|
+
/>
|
|
785
|
+
</td>
|
|
786
|
+
<td style={T.td}>
|
|
787
|
+
<span style={T.mono}>{e.figmaTextStyle}</span>
|
|
788
|
+
{/* Section label at first row of each category */}
|
|
789
|
+
{categoryLabel[step] && rows.indexOf(e) === 0 && (
|
|
790
|
+
<span
|
|
791
|
+
style={{
|
|
792
|
+
display: 'block',
|
|
793
|
+
fontSize: '10px',
|
|
794
|
+
fontWeight: '700',
|
|
795
|
+
color: '#4C662B',
|
|
796
|
+
textTransform: 'uppercase',
|
|
797
|
+
letterSpacing: '0.05em',
|
|
798
|
+
marginTop: '2px',
|
|
799
|
+
}}
|
|
800
|
+
>
|
|
801
|
+
── {categoryLabel[step]}
|
|
802
|
+
</span>
|
|
803
|
+
)}
|
|
804
|
+
</td>
|
|
805
|
+
<td style={T.td}>
|
|
806
|
+
<span style={{ ...T.mono, fontSize: '11px' }}>
|
|
807
|
+
{e.ddsTokenPath}
|
|
808
|
+
</span>
|
|
809
|
+
</td>
|
|
810
|
+
<td style={T.td}>
|
|
811
|
+
<span style={T.mono}>{e.pandaTextStyle}</span>
|
|
812
|
+
{isDefault && (
|
|
813
|
+
<span
|
|
814
|
+
style={T.pill}
|
|
815
|
+
title="Default weight for this scale step"
|
|
816
|
+
>
|
|
817
|
+
default
|
|
818
|
+
</span>
|
|
819
|
+
)}
|
|
820
|
+
</td>
|
|
821
|
+
<td style={T.td}>
|
|
822
|
+
<span style={{ ...T.mono, fontSize: '11px' }}>
|
|
823
|
+
{e.fontFamily.split(',')[0].replace(/"/g, '')}
|
|
824
|
+
</span>
|
|
825
|
+
<span
|
|
826
|
+
style={{
|
|
827
|
+
display: 'block',
|
|
828
|
+
fontFamily: 'monospace',
|
|
829
|
+
fontSize: '11px',
|
|
830
|
+
color: '#777',
|
|
831
|
+
}}
|
|
832
|
+
>
|
|
833
|
+
{e.fontStyle} ({e.fontWeight})
|
|
834
|
+
</span>
|
|
835
|
+
</td>
|
|
836
|
+
<td style={T.td}>
|
|
837
|
+
<span
|
|
838
|
+
style={{
|
|
839
|
+
fontFamily: 'monospace',
|
|
840
|
+
fontSize: '11px',
|
|
841
|
+
color: '#444',
|
|
842
|
+
}}
|
|
843
|
+
>
|
|
844
|
+
{e.fontSize}px / {e.lineHeightPx}px
|
|
845
|
+
{e.letterSpacing !== 0 && (
|
|
846
|
+
<span style={{ color: '#999' }}>
|
|
847
|
+
{' '}
|
|
848
|
+
ls:{e.letterSpacing}
|
|
849
|
+
</span>
|
|
850
|
+
)}
|
|
851
|
+
</span>
|
|
852
|
+
</td>
|
|
853
|
+
<td style={T.td}>
|
|
854
|
+
<span
|
|
855
|
+
style={{
|
|
856
|
+
...T.mono,
|
|
857
|
+
background: '#eef4e8',
|
|
858
|
+
fontSize: '11px',
|
|
859
|
+
}}
|
|
860
|
+
>
|
|
861
|
+
{e.exampleUsage}
|
|
862
|
+
</span>
|
|
863
|
+
{!isDefault && (
|
|
864
|
+
<span
|
|
865
|
+
style={{
|
|
866
|
+
display: 'block',
|
|
867
|
+
fontFamily: 'monospace',
|
|
868
|
+
fontSize: '10px',
|
|
869
|
+
color: '#888',
|
|
870
|
+
marginTop: '2px',
|
|
871
|
+
}}
|
|
872
|
+
>
|
|
873
|
+
+ fontWeight="{e.fontStyle.toLowerCase()}"
|
|
874
|
+
</span>
|
|
875
|
+
)}
|
|
876
|
+
</td>
|
|
877
|
+
</tr>
|
|
878
|
+
);
|
|
879
|
+
});
|
|
880
|
+
})}
|
|
881
|
+
</tbody>
|
|
882
|
+
</table>
|
|
883
|
+
|
|
884
|
+
<div
|
|
885
|
+
style={{
|
|
886
|
+
marginTop: '20px',
|
|
887
|
+
padding: '12px 16px',
|
|
888
|
+
background: '#f0f4ff',
|
|
889
|
+
borderRadius: '6px',
|
|
890
|
+
fontSize: '12px',
|
|
891
|
+
color: '#334',
|
|
892
|
+
lineHeight: 1.7,
|
|
893
|
+
}}
|
|
894
|
+
>
|
|
895
|
+
<strong>How to read this table:</strong> The <em>Panda textStyle</em>{' '}
|
|
896
|
+
sets geometry (size, line-height, letter-spacing, font-family). The
|
|
897
|
+
default weight variant is applied automatically. To use a non-default
|
|
898
|
+
weight, add <code>fontWeight</code> separately.
|
|
899
|
+
<br />
|
|
900
|
+
Example:{' '}
|
|
901
|
+
<code>
|
|
902
|
+
<Text textStyle="headlineSmall"
|
|
903
|
+
fontWeight="semibold">
|
|
904
|
+
</code>
|
|
905
|
+
<br />
|
|
906
|
+
The <em>DDS Token Path</em> is what the Figma text style description
|
|
907
|
+
field encodes (
|
|
908
|
+
<code>dds:typography.scale.headlineSmall.weights.semiBold</code>) —
|
|
909
|
+
the most direct resolution path from MCP output.
|
|
910
|
+
</div>
|
|
911
|
+
</div>
|
|
912
|
+
);
|
|
913
|
+
},
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
// ── Story 5: Full Reference (all sections on one page) ───────────────────────
|
|
917
|
+
|
|
918
|
+
export const FullReference: Story = {
|
|
919
|
+
name: '5 · Full Reference',
|
|
920
|
+
render: () => (
|
|
921
|
+
<div style={T.page}>
|
|
922
|
+
<div
|
|
923
|
+
style={{
|
|
924
|
+
padding: '16px 20px',
|
|
925
|
+
background: '#eef4e8',
|
|
926
|
+
borderRadius: '8px',
|
|
927
|
+
marginBottom: '40px',
|
|
928
|
+
fontSize: '13px',
|
|
929
|
+
color: '#3a5a18',
|
|
930
|
+
lineHeight: 1.7,
|
|
931
|
+
}}
|
|
932
|
+
>
|
|
933
|
+
<strong>Token Reference — v{tokenMap.version}</strong>
|
|
934
|
+
<br />
|
|
935
|
+
Generated:{' '}
|
|
936
|
+
{tokenMap.generatedAt
|
|
937
|
+
? new Date(tokenMap.generatedAt).toLocaleString()
|
|
938
|
+
: 'unknown'}
|
|
939
|
+
<br />
|
|
940
|
+
Sources:{' '}
|
|
941
|
+
{(tokenMap.generatedFrom as string[]).map((f, i) => (
|
|
942
|
+
<span key={f}>
|
|
943
|
+
<code
|
|
944
|
+
style={{
|
|
945
|
+
fontSize: '11px',
|
|
946
|
+
background: '#d4e8c4',
|
|
947
|
+
padding: '1px 4px',
|
|
948
|
+
borderRadius: '3px',
|
|
949
|
+
}}
|
|
950
|
+
>
|
|
951
|
+
{f}
|
|
952
|
+
</code>
|
|
953
|
+
{i < tokenMap.generatedFrom.length - 1 ? ' · ' : ''}
|
|
954
|
+
</span>
|
|
955
|
+
))}
|
|
956
|
+
<br />
|
|
957
|
+
<strong>To update:</strong> run <code>pnpm figma:export</code> then
|
|
958
|
+
rebuild Storybook.
|
|
959
|
+
</div>
|
|
960
|
+
|
|
961
|
+
{/* Render all four sections inline */}
|
|
962
|
+
{SemanticColors.render && SemanticColors.render({} as never, {} as never)}
|
|
963
|
+
{SpacingAndShape.render &&
|
|
964
|
+
SpacingAndShape.render({} as never, {} as never)}
|
|
965
|
+
{ElevationAndShadows.render &&
|
|
966
|
+
ElevationAndShadows.render({} as never, {} as never)}
|
|
967
|
+
{Typography.render && Typography.render({} as never, {} as never)}
|
|
968
|
+
</div>
|
|
969
|
+
),
|
|
970
|
+
};
|