@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
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Token Name Mapping
|
|
2
2
|
|
|
3
|
-
> Generated from `
|
|
4
|
-
> `
|
|
5
|
-
> `src/preset/colors/create-palette-bridge.ts`.
|
|
3
|
+
> Generated from `tokens/export-to-figma/figma-variables.json`, `tokens/export-to-figma/figma-effect-styles.json`,
|
|
4
|
+
> `tokens/export-to-figma/figma-text-styles.json`, `src/preset/semantic-tokens.ts`,
|
|
5
|
+
> `src/preset/colors/create-palette-bridge.ts`, and `src/languages/material3.language.ts`.
|
|
6
6
|
>
|
|
7
|
-
> Version: 0.
|
|
7
|
+
> Version: 0.25.3
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -195,7 +195,7 @@ Defined in `src/preset/index.ts:144–147` as semantic tokens:
|
|
|
195
195
|
|
|
196
196
|
## Section 4: Shadows (Effect Styles)
|
|
197
197
|
|
|
198
|
-
6 base elevation tokens from `
|
|
198
|
+
6 base elevation tokens from `tokens/export-to-figma/figma-effect-styles.json`, plus semantic
|
|
199
199
|
aliases defined in `src/preset/shadows.ts`.
|
|
200
200
|
|
|
201
201
|
### Base Elevation Tokens
|
|
@@ -225,27 +225,115 @@ aliases defined in `src/preset/shadows.ts`.
|
|
|
225
225
|
|
|
226
226
|
## Section 5: Typography (Text Styles)
|
|
227
227
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
|
246
|
-
|
|
|
247
|
-
| `
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
228
|
+
51 entries from `tokens/export-to-figma/figma-text-styles.json`. The system
|
|
229
|
+
uses slash-hierarchy naming (`Category/Size/Weight`) with all weight variants
|
|
230
|
+
per scale step — upgraded from 15 flat styles (one per scale step, default
|
|
231
|
+
weight only) to 51 styles covering all variants.
|
|
232
|
+
|
|
233
|
+
**Description field convention:** Each Figma text style carries a description
|
|
234
|
+
field in the format `dds:typography.scale.{scaleName}.weights.{weightName}`.
|
|
235
|
+
This is the semantic bridge the Figma MCP reads to resolve back to the DDS token.
|
|
236
|
+
|
|
237
|
+
> **pandaTextStyle uses the scale step name, not the weight variant.** Panda
|
|
238
|
+
> `textStyle` tokens are geometry-only (size, line height, letter spacing, font
|
|
239
|
+
> family). Font weight is applied separately via the `fontWeight` utility.
|
|
240
|
+
> For example: `textStyle: 'headlineSmall'` sets geometry; add
|
|
241
|
+
> `fontWeight: 600` (or `'semiBold'`) separately for the SemiBold variant.
|
|
242
|
+
|
|
243
|
+
### Display (Fraunces)
|
|
244
|
+
|
|
245
|
+
| Figma Text Style | Font | Weight | Size | Line Height | Letter Spacing | DDS Token Path | Panda textStyle | Default? |
|
|
246
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
247
|
+
| `Display/Large/Regular` | Fraunces | Regular (400) | 57px | 64px | -0.25 | `typography.scale.displayLarge.weights.regular` | `displayLarge` | ✓ |
|
|
248
|
+
| `Display/Large/SemiBold` | Fraunces | SemiBold (600) | 57px | 64px | -0.25 | `typography.scale.displayLarge.weights.semiBold` | `displayLarge` | |
|
|
249
|
+
| `Display/Medium/Regular` | Fraunces | Regular (400) | 45px | 52px | 0 | `typography.scale.displayMedium.weights.regular` | `displayMedium` | ✓ |
|
|
250
|
+
| `Display/Medium/SemiBold` | Fraunces | SemiBold (600) | 45px | 52px | 0 | `typography.scale.displayMedium.weights.semiBold` | `displayMedium` | |
|
|
251
|
+
| `Display/Small/Regular` | Fraunces | Regular (400) | 36px | 44px | 0 | `typography.scale.displaySmall.weights.regular` | `displaySmall` | ✓ |
|
|
252
|
+
| `Display/Small/SemiBold` | Fraunces | SemiBold (600) | 36px | 44px | 0 | `typography.scale.displaySmall.weights.semiBold` | `displaySmall` | |
|
|
253
|
+
|
|
254
|
+
### Headline (Fraunces)
|
|
255
|
+
|
|
256
|
+
| Figma Text Style | Font | Weight | Size | Line Height | Letter Spacing | DDS Token Path | Panda textStyle | Default? |
|
|
257
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
258
|
+
| `Headline/Large/Light` | Fraunces | Light (300) | 32px | 40px | 0 | `typography.scale.headlineLarge.weights.light` | `headlineLarge` | |
|
|
259
|
+
| `Headline/Large/Regular` | Fraunces | Regular (400) | 32px | 40px | 0 | `typography.scale.headlineLarge.weights.regular` | `headlineLarge` | ✓ |
|
|
260
|
+
| `Headline/Large/SemiBold` | Fraunces | SemiBold (600) | 32px | 40px | 0 | `typography.scale.headlineLarge.weights.semiBold` | `headlineLarge` | |
|
|
261
|
+
| `Headline/Medium/Light` | Fraunces | Light (300) | 28px | 36px | 0 | `typography.scale.headlineMedium.weights.light` | `headlineMedium` | |
|
|
262
|
+
| `Headline/Medium/Regular` | Fraunces | Regular (400) | 28px | 36px | 0 | `typography.scale.headlineMedium.weights.regular` | `headlineMedium` | ✓ |
|
|
263
|
+
| `Headline/Medium/SemiBold` | Fraunces | SemiBold (600) | 28px | 36px | 0 | `typography.scale.headlineMedium.weights.semiBold` | `headlineMedium` | |
|
|
264
|
+
| `Headline/Small/Light` | Fraunces | Light (300) | 24px | 32px | 0 | `typography.scale.headlineSmall.weights.light` | `headlineSmall` | |
|
|
265
|
+
| `Headline/Small/Regular` | Fraunces | Regular (400) | 24px | 32px | 0 | `typography.scale.headlineSmall.weights.regular` | `headlineSmall` | ✓ |
|
|
266
|
+
| `Headline/Small/SemiBold` | Fraunces | SemiBold (600) | 24px | 32px | 0 | `typography.scale.headlineSmall.weights.semiBold` | `headlineSmall` | |
|
|
267
|
+
|
|
268
|
+
### Title (Poppins)
|
|
269
|
+
|
|
270
|
+
| Figma Text Style | Font | Weight | Size | Line Height | Letter Spacing | DDS Token Path | Panda textStyle | Default? |
|
|
271
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
272
|
+
| `Title/Large/Regular` | Poppins | Regular (400) | 22px | 28px | 0 | `typography.scale.titleLarge.weights.regular` | `titleLarge` | |
|
|
273
|
+
| `Title/Large/Medium` | Poppins | Medium (500) | 22px | 28px | 0 | `typography.scale.titleLarge.weights.medium` | `titleLarge` | ✓ |
|
|
274
|
+
| `Title/Large/SemiBold` | Poppins | SemiBold (600) | 22px | 28px | 0 | `typography.scale.titleLarge.weights.semiBold` | `titleLarge` | |
|
|
275
|
+
| `Title/Large/Bold` | Poppins | Bold (700) | 22px | 28px | 0 | `typography.scale.titleLarge.weights.bold` | `titleLarge` | |
|
|
276
|
+
| `Title/Medium/Regular` | Poppins | Regular (400) | 16px | 24px | 0.15 | `typography.scale.titleMedium.weights.regular` | `titleMedium` | |
|
|
277
|
+
| `Title/Medium/Medium` | Poppins | Medium (500) | 16px | 24px | 0.15 | `typography.scale.titleMedium.weights.medium` | `titleMedium` | ✓ |
|
|
278
|
+
| `Title/Medium/SemiBold` | Poppins | SemiBold (600) | 16px | 24px | 0.15 | `typography.scale.titleMedium.weights.semiBold` | `titleMedium` | |
|
|
279
|
+
| `Title/Medium/Bold` | Poppins | Bold (700) | 16px | 24px | 0.15 | `typography.scale.titleMedium.weights.bold` | `titleMedium` | |
|
|
280
|
+
| `Title/Small/Regular` | Poppins | Regular (400) | 14px | 20px | 0.1 | `typography.scale.titleSmall.weights.regular` | `titleSmall` | |
|
|
281
|
+
| `Title/Small/Medium` | Poppins | Medium (500) | 14px | 20px | 0.1 | `typography.scale.titleSmall.weights.medium` | `titleSmall` | ✓ |
|
|
282
|
+
| `Title/Small/SemiBold` | Poppins | SemiBold (600) | 14px | 20px | 0.1 | `typography.scale.titleSmall.weights.semiBold` | `titleSmall` | |
|
|
283
|
+
| `Title/Small/Bold` | Poppins | Bold (700) | 14px | 20px | 0.1 | `typography.scale.titleSmall.weights.bold` | `titleSmall` | |
|
|
284
|
+
|
|
285
|
+
### Body (Poppins)
|
|
286
|
+
|
|
287
|
+
| Figma Text Style | Font | Weight | Size | Line Height | Letter Spacing | DDS Token Path | Panda textStyle | Default? |
|
|
288
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
289
|
+
| `Body/Large/Light` | Poppins | Light (300) | 18px | 28px | 0.5 | `typography.scale.bodyLarge.weights.light` | `bodyLarge` | |
|
|
290
|
+
| `Body/Large/Regular` | Poppins | Regular (400) | 18px | 28px | 0.5 | `typography.scale.bodyLarge.weights.regular` | `bodyLarge` | ✓ |
|
|
291
|
+
| `Body/Large/Medium` | Poppins | Medium (500) | 18px | 28px | 0.5 | `typography.scale.bodyLarge.weights.medium` | `bodyLarge` | |
|
|
292
|
+
| `Body/Large/SemiBold` | Poppins | SemiBold (600) | 18px | 28px | 0.5 | `typography.scale.bodyLarge.weights.semiBold` | `bodyLarge` | |
|
|
293
|
+
| `Body/Medium/Light` | Poppins | Light (300) | 14px | 20px | 0.25 | `typography.scale.bodyMedium.weights.light` | `bodyMedium` | |
|
|
294
|
+
| `Body/Medium/Regular` | Poppins | Regular (400) | 14px | 20px | 0.25 | `typography.scale.bodyMedium.weights.regular` | `bodyMedium` | ✓ |
|
|
295
|
+
| `Body/Medium/Medium` | Poppins | Medium (500) | 14px | 20px | 0.25 | `typography.scale.bodyMedium.weights.medium` | `bodyMedium` | |
|
|
296
|
+
| `Body/Medium/SemiBold` | Poppins | SemiBold (600) | 14px | 20px | 0.25 | `typography.scale.bodyMedium.weights.semiBold` | `bodyMedium` | |
|
|
297
|
+
| `Body/Small/Light` | Poppins | Light (300) | 12px | 16px | 0.4 | `typography.scale.bodySmall.weights.light` | `bodySmall` | |
|
|
298
|
+
| `Body/Small/Regular` | Poppins | Regular (400) | 12px | 16px | 0.4 | `typography.scale.bodySmall.weights.regular` | `bodySmall` | ✓ |
|
|
299
|
+
| `Body/Small/Medium` | Poppins | Medium (500) | 12px | 16px | 0.4 | `typography.scale.bodySmall.weights.medium` | `bodySmall` | |
|
|
300
|
+
| `Body/Small/SemiBold` | Poppins | SemiBold (600) | 12px | 16px | 0.4 | `typography.scale.bodySmall.weights.semiBold` | `bodySmall` | |
|
|
301
|
+
|
|
302
|
+
### Label (Poppins)
|
|
303
|
+
|
|
304
|
+
| Figma Text Style | Font | Weight | Size | Line Height | Letter Spacing | DDS Token Path | Panda textStyle | Default? |
|
|
305
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
306
|
+
| `Label/Large/Light` | Poppins | Light (300) | 14px | 20px | 0.1 | `typography.scale.labelLarge.weights.light` | `labelLarge` | |
|
|
307
|
+
| `Label/Large/Medium` | Poppins | Medium (500) | 14px | 20px | 0.1 | `typography.scale.labelLarge.weights.medium` | `labelLarge` | ✓ |
|
|
308
|
+
| `Label/Large/SemiBold` | Poppins | SemiBold (600) | 14px | 20px | 0.1 | `typography.scale.labelLarge.weights.semiBold` | `labelLarge` | |
|
|
309
|
+
| `Label/Large/Bold` | Poppins | Bold (700) | 14px | 20px | 0.1 | `typography.scale.labelLarge.weights.bold` | `labelLarge` | |
|
|
310
|
+
| `Label/Medium/Light` | Poppins | Light (300) | 12px | 16px | 0.5 | `typography.scale.labelMedium.weights.light` | `labelMedium` | |
|
|
311
|
+
| `Label/Medium/Medium` | Poppins | Medium (500) | 12px | 16px | 0.5 | `typography.scale.labelMedium.weights.medium` | `labelMedium` | ✓ |
|
|
312
|
+
| `Label/Medium/SemiBold` | Poppins | SemiBold (600) | 12px | 16px | 0.5 | `typography.scale.labelMedium.weights.semiBold` | `labelMedium` | |
|
|
313
|
+
| `Label/Medium/Bold` | Poppins | Bold (700) | 12px | 16px | 0.5 | `typography.scale.labelMedium.weights.bold` | `labelMedium` | |
|
|
314
|
+
| `Label/Small/Light` | Poppins | Light (300) | 11px | 16px | 0.5 | `typography.scale.labelSmall.weights.light` | `labelSmall` | |
|
|
315
|
+
| `Label/Small/Medium` | Poppins | Medium (500) | 11px | 16px | 0.5 | `typography.scale.labelSmall.weights.medium` | `labelSmall` | ✓ |
|
|
316
|
+
| `Label/Small/SemiBold` | Poppins | SemiBold (600) | 11px | 16px | 0.5 | `typography.scale.labelSmall.weights.semiBold` | `labelSmall` | |
|
|
317
|
+
| `Label/Small/Bold` | Poppins | Bold (700) | 11px | 16px | 0.5 | `typography.scale.labelSmall.weights.bold` | `labelSmall` | |
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Section 6: Figma MCP Resolution — What the AI Sees
|
|
322
|
+
|
|
323
|
+
When the Figma Desktop MCP reads a node via `get_design_context`, it returns
|
|
324
|
+
structured data. This table shows what each token type looks like in MCP
|
|
325
|
+
output and how it resolves to a DDS token.
|
|
326
|
+
|
|
327
|
+
| Token Type | What MCP Returns | How to Resolve to DDS Token |
|
|
328
|
+
| --- | --- | --- |
|
|
329
|
+
| Color fill | `boundVariables.fills[].id` → variable name e.g. `"Semantic/primary"` | Look up `figmaPath` in `token-name-mapping.json` `semantic` array → `pandaToken` |
|
|
330
|
+
| Spacing/padding | `boundVariables.paddingLeft.id` → variable name e.g. `"Spacing & Shape/spacing/md"` | Look up `figmaPath` in `spacingAndShape` array → `pandaToken` + `pandaCategory` |
|
|
331
|
+
| Border radius | `boundVariables.cornerRadius.id` → variable name e.g. `"Spacing & Shape/radii/medium"` | Look up `figmaPath` in `spacingAndShape` array |
|
|
332
|
+
| Shadow/elevation | `effects[].styleId` → effect style name e.g. `"elevation/level2"` | Look up `figmaEffectStyle` in `effectStyles` array → `pandaToken` |
|
|
333
|
+
| Text style | `style.textStyleId` → text style name e.g. `"Headline/Small/SemiBold"` | Look up `figmaTextStyle` in `textStyles` array → `ddsTokenPath` and `pandaTextStyle` |
|
|
334
|
+
| Text style description | `style.description` = `"dds:typography.scale.headlineSmall.weights.semiBold"` | Parse after `"dds:"` → direct DDS token path |
|
|
335
|
+
|
|
336
|
+
> **The text style description field is the most direct resolution path for
|
|
337
|
+
> typography** — no lookup table needed. The MCP returns it as part of the
|
|
338
|
+
> style metadata and it maps directly to the `DesignLanguageContract` token
|
|
339
|
+
> path (strip the `dds:` prefix to get `typography.scale.{step}.weights.{weight}`).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@discourser/design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Aesthetic-agnostic design system with Panda CSS and Ark UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -198,7 +198,7 @@
|
|
|
198
198
|
],
|
|
199
199
|
"scripts": {
|
|
200
200
|
"dev": "pnpm build:css && pnpm docs:generate && storybook dev -p 6006",
|
|
201
|
-
"build": "pnpm build:panda && pnpm typecheck && pnpm build:lib && pnpm build:types && pnpm exports:validate && pnpm codex:generate",
|
|
201
|
+
"build": "pnpm build:panda && pnpm typecheck && pnpm build:lib && pnpm build:types && pnpm exports:validate && pnpm catalog:generate && pnpm codex:generate",
|
|
202
202
|
"build:panda": "panda codegen",
|
|
203
203
|
"build:css": "panda cssgen --outfile dist/styles.css",
|
|
204
204
|
"build:lib": "tsup",
|
|
@@ -233,6 +233,7 @@
|
|
|
233
233
|
"version": "changeset version",
|
|
234
234
|
"ci:version": "pnpm exec changeset version",
|
|
235
235
|
"release": "pnpm build && changeset publish --access public",
|
|
236
|
+
"catalog:generate": "tsx scripts/generate-component-catalog.ts",
|
|
236
237
|
"exports:validate": "tsx scripts/validate-exports.ts"
|
|
237
238
|
},
|
|
238
239
|
"peerDependencies": {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ark } from '@ark-ui/react/factory';
|
|
2
|
+
import type { ComponentProps } from 'react';
|
|
3
|
+
import { styled } from 'styled-system/jsx';
|
|
4
|
+
|
|
5
|
+
const StyledSvg = styled(ark.svg);
|
|
6
|
+
|
|
7
|
+
export type LeftArrowIconProps = ComponentProps<typeof StyledSvg>;
|
|
8
|
+
|
|
9
|
+
export const LeftArrowIcon = (props: LeftArrowIconProps) => (
|
|
10
|
+
<StyledSvg
|
|
11
|
+
viewBox="0 0 21 17"
|
|
12
|
+
fill="none"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
width="1em"
|
|
15
|
+
height="1em"
|
|
16
|
+
{...props}
|
|
17
|
+
>
|
|
18
|
+
<path
|
|
19
|
+
d="M9.10036 11.988C9.33515 12.2116 9.34422 12.5831 9.12063 12.8178C8.89704 13.0526 8.52554 13.0617 8.29083 12.8381L9.10036 11.988ZM4.18214 8.92503C3.94736 8.70144 3.93828 8.32993 4.16187 8.09523C4.38546 7.86045 4.75697 7.85137 4.99167 8.07496L4.18214 8.92503ZM4.99167 8.92503C4.75697 9.14862 4.38546 9.13954 4.16187 8.90476C3.93828 8.67006 3.94736 8.29855 4.18214 8.07496L4.99167 8.92503ZM8.29083 4.16192C8.52554 3.93836 8.89704 3.94742 9.12063 4.18216C9.34422 4.4169 9.33515 4.78843 9.10036 5.01199L8.29083 4.16192ZM4.58691 9.08695C4.26275 9.08695 3.99995 8.82415 3.99995 8.5C3.99995 8.17584 4.26275 7.91304 4.58691 7.91304V9.08695ZM15.5434 7.91304C15.8676 7.91304 16.1304 8.17584 16.1304 8.5C16.1304 8.82415 15.8676 9.08695 15.5434 9.08695V7.91304ZM8.29083 12.8381L4.18214 8.92503L4.99167 8.07496L9.10036 11.988L8.29083 12.8381ZM4.18214 8.07496L8.29083 4.16192L9.10036 5.01199L4.99167 8.92503L4.18214 8.07496ZM4.58691 7.91304H15.5434V9.08695H4.58691V7.91304Z"
|
|
20
|
+
fill="currentColor"
|
|
21
|
+
/>
|
|
22
|
+
<path
|
|
23
|
+
d="M9.10036 11.988C9.33515 12.2116 9.34422 12.5831 9.12063 12.8178C8.89704 13.0526 8.52554 13.0617 8.29083 12.8381M9.10036 11.988L8.29083 12.8381M9.10036 11.988L4.99167 8.07496M8.29083 12.8381L4.18214 8.92503M4.18214 8.92503C3.94736 8.70144 3.93828 8.32993 4.16187 8.09523C4.38546 7.86045 4.75697 7.85137 4.99167 8.07496M4.18214 8.92503L4.99167 8.07496M4.99167 8.92503C4.75697 9.14862 4.38546 9.13954 4.16187 8.90476C3.93828 8.67006 3.94736 8.29855 4.18214 8.07496M4.99167 8.92503L4.18214 8.07496M4.99167 8.92503L9.10036 5.01199M4.18214 8.07496L8.29083 4.16192M8.29083 4.16192C8.52554 3.93836 8.89704 3.94742 9.12063 4.18216C9.34422 4.4169 9.33515 4.78843 9.10036 5.01199M8.29083 4.16192L9.10036 5.01199M4.58691 9.08695C4.26275 9.08695 3.99995 8.82415 3.99995 8.5C3.99995 8.17584 4.26275 7.91304 4.58691 7.91304M4.58691 9.08695V7.91304M4.58691 9.08695H15.5434M4.58691 7.91304H15.5434M15.5434 7.91304C15.8676 7.91304 16.1304 8.17584 16.1304 8.5C16.1304 8.82415 15.8676 9.08695 15.5434 9.08695M15.5434 7.91304V9.08695"
|
|
24
|
+
stroke="currentColor"
|
|
25
|
+
strokeWidth="0.75"
|
|
26
|
+
/>
|
|
27
|
+
</StyledSvg>
|
|
28
|
+
);
|
|
@@ -8,7 +8,7 @@ export type RightArrowIconProps = ComponentProps<typeof StyledSvg>;
|
|
|
8
8
|
|
|
9
9
|
export const RightArrowIcon = (props: RightArrowIconProps) => (
|
|
10
10
|
<StyledSvg
|
|
11
|
-
viewBox="0 0
|
|
11
|
+
viewBox="0 0 21 17"
|
|
12
12
|
fill="none"
|
|
13
13
|
xmlns="http://www.w3.org/2000/svg"
|
|
14
14
|
width="1em"
|
|
@@ -16,8 +16,13 @@ export const RightArrowIcon = (props: RightArrowIconProps) => (
|
|
|
16
16
|
{...props}
|
|
17
17
|
>
|
|
18
18
|
<path
|
|
19
|
-
d="
|
|
19
|
+
d="M11.03 11.988C10.7952 12.2116 10.7861 12.5831 11.0097 12.8178C11.2333 13.0526 11.6048 13.0617 11.8395 12.8381L11.03 11.988ZM15.9482 8.92503C16.183 8.70144 16.1921 8.32993 15.9685 8.09523C15.7449 7.86045 15.3734 7.85137 15.1387 8.07496L15.9482 8.92503ZM15.1387 8.92503C15.3734 9.14862 15.7449 9.13954 15.9685 8.90476C16.1921 8.67006 16.183 8.29855 15.9482 8.07496L15.1387 8.92503ZM11.8395 4.16192C11.6048 3.93836 11.2333 3.94742 11.0097 4.18216C10.7861 4.4169 10.7952 4.78843 11.03 5.01199L11.8395 4.16192ZM15.5435 9.08695C15.8676 9.08695 16.1304 8.82415 16.1304 8.5C16.1304 8.17584 15.8676 7.91304 15.5435 7.91304V9.08695ZM4.58696 7.91304C4.26279 7.91304 4 8.17584 4 8.5C4 8.82415 4.26279 9.08695 4.58696 9.08695V7.91304ZM11.8395 12.8381L15.9482 8.92503L15.1387 8.07496L11.03 11.988L11.8395 12.8381ZM15.9482 8.07496L11.8395 4.16192L11.03 5.01199L15.1387 8.92503L15.9482 8.07496ZM15.5435 7.91304H4.58696V9.08695H15.5435V7.91304Z"
|
|
20
20
|
fill="currentColor"
|
|
21
21
|
/>
|
|
22
|
+
<path
|
|
23
|
+
d="M11.03 11.988C10.7952 12.2116 10.7861 12.5831 11.0097 12.8178C11.2333 13.0526 11.6048 13.0617 11.8395 12.8381M11.03 11.988L11.8395 12.8381M11.03 11.988L15.1387 8.07496M11.8395 12.8381L15.9482 8.92503M15.9482 8.92503C16.183 8.70144 16.1921 8.32993 15.9685 8.09523C15.7449 7.86045 15.3734 7.85137 15.1387 8.07496M15.9482 8.92503L15.1387 8.07496M15.1387 8.92503C15.3734 9.14862 15.7449 9.13954 15.9685 8.90476C16.1921 8.67006 16.183 8.29855 15.9482 8.07496M15.1387 8.92503L15.9482 8.07496M15.1387 8.92503L11.03 5.01199M15.9482 8.07496L11.8395 4.16192M11.8395 4.16192C11.6048 3.93836 11.2333 3.94742 11.0097 4.18216C10.7861 4.4169 10.7952 4.78843 11.03 5.01199M11.8395 4.16192L11.03 5.01199M15.5435 9.08695C15.8676 9.08695 16.1304 8.82415 16.1304 8.5C16.1304 8.17584 15.8676 7.91304 15.5435 7.91304M15.5435 9.08695V7.91304M15.5435 9.08695H4.58696M15.5435 7.91304H4.58696M4.58696 7.91304C4.26279 7.91304 4 8.17584 4 8.5C4 8.82415 4.26279 9.08695 4.58696 9.08695M4.58696 7.91304V9.08695"
|
|
24
|
+
stroke="currentColor"
|
|
25
|
+
strokeWidth="0.75"
|
|
26
|
+
/>
|
|
22
27
|
</StyledSvg>
|
|
23
28
|
);
|
|
@@ -9,6 +9,7 @@ export { ScenarioIcon, type ScenarioIconProps } from './ScenarioIcon';
|
|
|
9
9
|
export { HelpIcon, type HelpIconProps } from './HelpIcon';
|
|
10
10
|
export { AccountIcon, type AccountIconProps } from './AccountIcon';
|
|
11
11
|
export { RightArrowIcon, type RightArrowIconProps } from './RightArrowIcon';
|
|
12
|
+
export { LeftArrowIcon, type LeftArrowIconProps } from './LeftArrowIcon';
|
|
12
13
|
export { ChevronUpIcon, type ChevronUpIconProps } from './ChevronUpIcon';
|
|
13
14
|
export { DiscourserLogo, type DiscourserLogoProps } from './DiscourserLogo';
|
|
14
15
|
export { TimerIcon, type TimerIconProps } from './TimerIcon';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* global describe, it, expect */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { AbsoluteCenter } from '../AbsoluteCenter';
|
|
5
|
+
|
|
6
|
+
describe('AbsoluteCenter', () => {
|
|
7
|
+
it('renders children', () => {
|
|
8
|
+
render(<AbsoluteCenter>Centered content</AbsoluteCenter>);
|
|
9
|
+
expect(screen.getByText('Centered content')).toBeDefined();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('renders as a div element', () => {
|
|
13
|
+
const { container } = render(<AbsoluteCenter>Content</AbsoluteCenter>);
|
|
14
|
+
expect(container.querySelector('div')).toBeDefined();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('accepts and passes through className', () => {
|
|
18
|
+
const { container } = render(
|
|
19
|
+
<AbsoluteCenter className="custom-class">Content</AbsoluteCenter>,
|
|
20
|
+
);
|
|
21
|
+
const el = container.querySelector('.custom-class');
|
|
22
|
+
expect(el).toBeDefined();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('accepts and forwards arbitrary HTML attributes', () => {
|
|
26
|
+
render(
|
|
27
|
+
<AbsoluteCenter data-testid="absolute-center">Content</AbsoluteCenter>,
|
|
28
|
+
);
|
|
29
|
+
expect(screen.getByTestId('absolute-center')).toBeDefined();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* global describe, it, expect */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { Divider } from '../divider';
|
|
5
|
+
|
|
6
|
+
describe('Divider', () => {
|
|
7
|
+
it('renders a div with role="separator" by default', () => {
|
|
8
|
+
render(<Divider />);
|
|
9
|
+
expect(screen.getByRole('separator')).toBeDefined();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('has aria-orientation="horizontal" by default', () => {
|
|
13
|
+
render(<Divider />);
|
|
14
|
+
const el = screen.getByRole('separator');
|
|
15
|
+
expect(el.getAttribute('aria-orientation')).toBe('horizontal');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('renders label text when label prop is provided', () => {
|
|
19
|
+
render(<Divider label="OR" />);
|
|
20
|
+
expect(screen.getByText('OR')).toBeDefined();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('renders aria-orientation="vertical" when orientation="vertical"', () => {
|
|
24
|
+
render(<Divider orientation="vertical" />);
|
|
25
|
+
const el = screen.getByRole('separator');
|
|
26
|
+
expect(el.getAttribute('aria-orientation')).toBe('vertical');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('renders without label when no label prop provided', () => {
|
|
30
|
+
const { container } = render(<Divider />);
|
|
31
|
+
expect(container.querySelector('span')).toBeNull();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('accepts className passthrough', () => {
|
|
35
|
+
const { container } = render(<Divider className="my-divider" />);
|
|
36
|
+
expect(container.querySelector('.my-divider')).toBeDefined();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* global describe, it, expect */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { Group } from '../Group';
|
|
5
|
+
|
|
6
|
+
describe('Group', () => {
|
|
7
|
+
it('renders children', () => {
|
|
8
|
+
render(<Group>Child content</Group>);
|
|
9
|
+
expect(screen.getByText('Child content')).toBeDefined();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('renders as a div', () => {
|
|
13
|
+
const { container } = render(<Group>Content</Group>);
|
|
14
|
+
expect(container.querySelector('div')).toBeDefined();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('accepts data-testid', () => {
|
|
18
|
+
render(<Group data-testid="my-group">Content</Group>);
|
|
19
|
+
expect(screen.getByTestId('my-group')).toBeDefined();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('renders all children', () => {
|
|
23
|
+
render(
|
|
24
|
+
<Group>
|
|
25
|
+
<span>First</span>
|
|
26
|
+
<span>Second</span>
|
|
27
|
+
<span>Third</span>
|
|
28
|
+
</Group>,
|
|
29
|
+
);
|
|
30
|
+
expect(screen.getByText('First')).toBeDefined();
|
|
31
|
+
expect(screen.getByText('Second')).toBeDefined();
|
|
32
|
+
expect(screen.getByText('Third')).toBeDefined();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* global describe, it, expect */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { Icon } from '../Icon';
|
|
5
|
+
|
|
6
|
+
describe('Icon', () => {
|
|
7
|
+
it('renders as an svg element', () => {
|
|
8
|
+
const { container } = render(<Icon />);
|
|
9
|
+
expect(container.querySelector('svg')).toBeDefined();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('renders children (inner SVG content)', () => {
|
|
13
|
+
const { container } = render(
|
|
14
|
+
<Icon>
|
|
15
|
+
<circle cx="12" cy="12" r="10" />
|
|
16
|
+
</Icon>,
|
|
17
|
+
);
|
|
18
|
+
expect(container.querySelector('circle')).toBeDefined();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('accepts className passthrough', () => {
|
|
22
|
+
const { container } = render(<Icon className="custom-icon" />);
|
|
23
|
+
expect(container.querySelector('.custom-icon')).toBeDefined();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('accepts aria-label for accessibility', () => {
|
|
27
|
+
const { container } = render(<Icon aria-label="circle icon" />);
|
|
28
|
+
const svg = container.querySelector('svg');
|
|
29
|
+
expect(svg?.getAttribute('aria-label')).toBe('circle icon');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* global describe, it, expect */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { SettingsPopover } from '../SettingsPopover';
|
|
5
|
+
|
|
6
|
+
const defaultProps = {
|
|
7
|
+
userName: 'Jane Doe',
|
|
8
|
+
userTier: 'Pro',
|
|
9
|
+
userEmail: 'jane@example.com',
|
|
10
|
+
actions: [{ key: 'logout', label: 'Logout', onClick: () => {} }],
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
describe('SettingsPopover', () => {
|
|
14
|
+
it('renders the trigger button with userName', () => {
|
|
15
|
+
render(<SettingsPopover {...defaultProps} />);
|
|
16
|
+
expect(screen.getByText('Jane Doe')).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('renders userTier in the trigger', () => {
|
|
20
|
+
render(<SettingsPopover {...defaultProps} />);
|
|
21
|
+
expect(screen.getByText('Pro')).toBeDefined();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('trigger button has correct aria-label (default: "User settings")', () => {
|
|
25
|
+
render(<SettingsPopover {...defaultProps} />);
|
|
26
|
+
expect(screen.getByRole('button', { name: 'User settings' })).toBeDefined();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('accepts custom ariaLabel prop', () => {
|
|
30
|
+
render(<SettingsPopover {...defaultProps} ariaLabel="Account menu" />);
|
|
31
|
+
expect(screen.getByRole('button', { name: 'Account menu' })).toBeDefined();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('renders the trigger as a button element', () => {
|
|
35
|
+
render(<SettingsPopover {...defaultProps} />);
|
|
36
|
+
const btn = screen.getByRole('button', { name: 'User settings' });
|
|
37
|
+
expect(btn.tagName.toLowerCase()).toBe('button');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/* global describe, it, expect */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { StudioControls } from '../StudioControls';
|
|
5
|
+
|
|
6
|
+
const defaultProps = {
|
|
7
|
+
scenarioName: 'UX Interview Practice',
|
|
8
|
+
scenarioFocus: 'Technical Communication',
|
|
9
|
+
scenarioLevel: 'beginner' as const,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
describe('StudioControls', () => {
|
|
13
|
+
it('renders the component without crashing', () => {
|
|
14
|
+
const { container } = render(<StudioControls {...defaultProps} />);
|
|
15
|
+
expect(container.firstChild).toBeDefined();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('renders scenarioName text in the document', () => {
|
|
19
|
+
render(<StudioControls {...defaultProps} />);
|
|
20
|
+
expect(screen.getByText('UX Interview Practice')).toBeDefined();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('renders scenarioFocus text in the document', () => {
|
|
24
|
+
render(<StudioControls {...defaultProps} />);
|
|
25
|
+
expect(screen.getByText(/Technical Communication/)).toBeDefined();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('renders "Scenario Settings" accordion trigger text', () => {
|
|
29
|
+
render(<StudioControls {...defaultProps} />);
|
|
30
|
+
// "Scenario Settings" appears in both the accordion trigger and the settings card heading
|
|
31
|
+
const matches = screen.getAllByText('Scenario Settings');
|
|
32
|
+
expect(matches.length).toBeGreaterThan(0);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('renders "Audio Output" accordion trigger text', () => {
|
|
36
|
+
render(<StudioControls {...defaultProps} />);
|
|
37
|
+
expect(screen.getByText('Audio Output')).toBeDefined();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('renders "Microphone Input" accordion trigger text', () => {
|
|
41
|
+
render(<StudioControls {...defaultProps} />);
|
|
42
|
+
expect(screen.getByText('Microphone Input')).toBeDefined();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('renders "A/V Recording" accordion trigger text', () => {
|
|
46
|
+
render(<StudioControls {...defaultProps} />);
|
|
47
|
+
expect(screen.getByText('A/V Recording')).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('renders "Display Timer" accordion trigger text', () => {
|
|
51
|
+
render(<StudioControls {...defaultProps} />);
|
|
52
|
+
expect(screen.getByText('Display Timer')).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('renders "Hide Interviewers" accordion trigger text', () => {
|
|
56
|
+
render(<StudioControls {...defaultProps} />);
|
|
57
|
+
expect(screen.getByText('Hide Interviewers')).toBeDefined();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* global describe, it, expect */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { Toaster, toaster } from '../Toast';
|
|
5
|
+
|
|
6
|
+
describe('Toaster', () => {
|
|
7
|
+
it('toaster imperative API exists and is not null', () => {
|
|
8
|
+
expect(toaster).toBeDefined();
|
|
9
|
+
expect(toaster).not.toBeNull();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('toaster has a create method', () => {
|
|
13
|
+
expect(typeof toaster.create).toBe('function');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('Toaster is a function (renderable component)', () => {
|
|
17
|
+
expect(typeof Toaster).toBe('function');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('renders without crashing', () => {
|
|
21
|
+
const { container } = render(<Toaster />);
|
|
22
|
+
expect(container).toBeDefined();
|
|
23
|
+
});
|
|
24
|
+
});
|
package/src/components/index.ts
CHANGED
|
@@ -65,6 +65,7 @@ export {
|
|
|
65
65
|
RightArrowIcon,
|
|
66
66
|
type RightArrowIconProps,
|
|
67
67
|
} from './Icons/RightArrowIcon';
|
|
68
|
+
export { LeftArrowIcon, type LeftArrowIconProps } from './Icons/LeftArrowIcon';
|
|
68
69
|
export { ChevronUpIcon, type ChevronUpIconProps } from './Icons/ChevronUpIcon';
|
|
69
70
|
export {
|
|
70
71
|
DiscourserLogo,
|
|
@@ -83,33 +83,82 @@ export interface SemanticColors {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// Typography Types
|
|
86
|
+
|
|
87
|
+
export type WeightName =
|
|
88
|
+
| 'thin'
|
|
89
|
+
| 'light'
|
|
90
|
+
| 'regular'
|
|
91
|
+
| 'medium'
|
|
92
|
+
| 'semiBold'
|
|
93
|
+
| 'bold'
|
|
94
|
+
| 'extraBold';
|
|
95
|
+
|
|
96
|
+
export interface FontWeightMap {
|
|
97
|
+
'100'?: string;
|
|
98
|
+
'200'?: string;
|
|
99
|
+
'300'?: string;
|
|
100
|
+
'400'?: string;
|
|
101
|
+
'500'?: string;
|
|
102
|
+
'600'?: string;
|
|
103
|
+
'700'?: string;
|
|
104
|
+
'800'?: string;
|
|
105
|
+
'900'?: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface FontConfig {
|
|
109
|
+
family: string;
|
|
110
|
+
figmaName: string;
|
|
111
|
+
weightMap: FontWeightMap;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface TypeGeometry {
|
|
115
|
+
fontSize: string;
|
|
116
|
+
lineHeight: string;
|
|
117
|
+
letterSpacing: string;
|
|
118
|
+
fontFamily: 'display' | 'body' | 'mono';
|
|
119
|
+
fontVariationSettings?: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface WeightVariant {
|
|
123
|
+
name: WeightName;
|
|
124
|
+
fontWeight: string;
|
|
125
|
+
fontVariationSettings?: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface TypeScaleStep {
|
|
129
|
+
geometry: TypeGeometry;
|
|
130
|
+
defaultWeight: WeightName;
|
|
131
|
+
weights: Partial<Record<WeightName, WeightVariant>>;
|
|
132
|
+
}
|
|
133
|
+
|
|
86
134
|
export interface TypographyConfig {
|
|
87
135
|
fonts: {
|
|
88
|
-
display:
|
|
89
|
-
body:
|
|
90
|
-
mono:
|
|
136
|
+
display: FontConfig;
|
|
137
|
+
body: FontConfig;
|
|
138
|
+
mono: FontConfig;
|
|
91
139
|
};
|
|
92
140
|
scale: TypographyScale;
|
|
93
141
|
}
|
|
94
142
|
|
|
95
143
|
export interface TypographyScale {
|
|
96
|
-
displayLarge:
|
|
97
|
-
displayMedium:
|
|
98
|
-
displaySmall:
|
|
99
|
-
headlineLarge:
|
|
100
|
-
headlineMedium:
|
|
101
|
-
headlineSmall:
|
|
102
|
-
titleLarge:
|
|
103
|
-
titleMedium:
|
|
104
|
-
titleSmall:
|
|
105
|
-
bodyLarge:
|
|
106
|
-
bodyMedium:
|
|
107
|
-
bodySmall:
|
|
108
|
-
labelLarge:
|
|
109
|
-
labelMedium:
|
|
110
|
-
labelSmall:
|
|
111
|
-
}
|
|
112
|
-
|
|
144
|
+
displayLarge: TypeScaleStep;
|
|
145
|
+
displayMedium: TypeScaleStep;
|
|
146
|
+
displaySmall: TypeScaleStep;
|
|
147
|
+
headlineLarge: TypeScaleStep;
|
|
148
|
+
headlineMedium: TypeScaleStep;
|
|
149
|
+
headlineSmall: TypeScaleStep;
|
|
150
|
+
titleLarge: TypeScaleStep;
|
|
151
|
+
titleMedium: TypeScaleStep;
|
|
152
|
+
titleSmall: TypeScaleStep;
|
|
153
|
+
bodyLarge: TypeScaleStep;
|
|
154
|
+
bodyMedium: TypeScaleStep;
|
|
155
|
+
bodySmall: TypeScaleStep;
|
|
156
|
+
labelLarge: TypeScaleStep;
|
|
157
|
+
labelMedium: TypeScaleStep;
|
|
158
|
+
labelSmall: TypeScaleStep;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Kept unchanged — used by Panda recipes and the resolveTypeStyle() shim.
|
|
113
162
|
export interface TypeStyle {
|
|
114
163
|
fontSize: string;
|
|
115
164
|
lineHeight: string;
|