@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.
Files changed (61) hide show
  1. package/README.md +76 -73
  2. package/dist/{chunk-ZPECW4N2.js → chunk-4XOWPACJ.js} +257 -105
  3. package/dist/chunk-4XOWPACJ.js.map +1 -0
  4. package/dist/{chunk-QNCZYFUJ.cjs → chunk-AZ6QU2L2.cjs} +257 -105
  5. package/dist/chunk-AZ6QU2L2.cjs.map +1 -0
  6. package/dist/{chunk-TBLDQATQ.cjs → chunk-EBDNCZF6.cjs} +94 -54
  7. package/dist/chunk-EBDNCZF6.cjs.map +1 -0
  8. package/dist/{chunk-UHSL4N44.js → chunk-MAVUSE4F.js} +94 -55
  9. package/dist/chunk-MAVUSE4F.js.map +1 -0
  10. package/dist/components/Checkbox.d.ts +1 -1
  11. package/dist/components/Icons/LeftArrowIcon.d.ts +6 -0
  12. package/dist/components/Icons/LeftArrowIcon.d.ts.map +1 -0
  13. package/dist/components/Icons/RightArrowIcon.d.ts.map +1 -1
  14. package/dist/components/Icons/index.d.ts +1 -0
  15. package/dist/components/Icons/index.d.ts.map +1 -1
  16. package/dist/components/index.cjs +79 -75
  17. package/dist/components/index.d.ts +1 -0
  18. package/dist/components/index.d.ts.map +1 -1
  19. package/dist/components/index.js +1 -1
  20. package/dist/contracts/design-language.contract.d.ts +52 -18
  21. package/dist/contracts/design-language.contract.d.ts.map +1 -1
  22. package/dist/figma-codex.json +2 -2
  23. package/dist/index.cjs +83 -79
  24. package/dist/index.js +2 -2
  25. package/dist/languages/material3.language.d.ts.map +1 -1
  26. package/dist/languages/transform.d.ts +5 -5
  27. package/dist/languages/transform.d.ts.map +1 -1
  28. package/dist/preset/index.cjs +2 -2
  29. package/dist/preset/index.js +1 -1
  30. package/docs/component-catalog.md +469 -0
  31. package/docs/superpowers/plans/2026-04-03-component-catalog-pipeline.md +667 -0
  32. package/docs/token-name-mapping.json +614 -42
  33. package/docs/token-name-mapping.md +117 -29
  34. package/package.json +3 -2
  35. package/src/components/Icons/LeftArrowIcon.tsx +28 -0
  36. package/src/components/Icons/RightArrowIcon.tsx +7 -2
  37. package/src/components/Icons/index.ts +1 -0
  38. package/src/components/__tests__/AbsoluteCenter.test.tsx +31 -0
  39. package/src/components/__tests__/Divider.test.tsx +38 -0
  40. package/src/components/__tests__/Group.test.tsx +34 -0
  41. package/src/components/__tests__/Icon.test.tsx +31 -0
  42. package/src/components/__tests__/SettingsPopover.test.tsx +39 -0
  43. package/src/components/__tests__/StudioControls.test.tsx +59 -0
  44. package/src/components/__tests__/Toaster.test.tsx +24 -0
  45. package/src/components/index.ts +1 -0
  46. package/src/contracts/design-language.contract.ts +69 -20
  47. package/src/languages/material3.language.ts +249 -80
  48. package/src/languages/transform.ts +45 -48
  49. package/src/preset/__tests__/translation-token-accuracy.test.ts +13 -0
  50. package/src/stories/foundations/Colors.mdx +9 -1
  51. package/src/stories/foundations/Elevation.mdx +23 -17
  52. package/src/stories/foundations/TokenReference.stories.tsx +970 -0
  53. package/src/stories/foundations/TonalPaletteDerivation.stories.tsx +782 -0
  54. package/src/stories/foundations/Typography.mdx +125 -25
  55. package/dist/chunk-QNCZYFUJ.cjs.map +0 -1
  56. package/dist/chunk-TBLDQATQ.cjs.map +0 -1
  57. package/dist/chunk-UHSL4N44.js.map +0 -1
  58. package/dist/chunk-ZPECW4N2.js.map +0 -1
  59. package/docs/context-share/ELEVATION_FIX_PLAN.md +0 -903
  60. package/docs/context-share/fix-checkbox-radio-tokens.md +0 -145
  61. package/docs/context-share/icon-component-prompt.md +0 -154
@@ -1,145 +0,0 @@
1
- # Fix: Checkbox, Radio Button, and Input Error State Token Resolution
2
-
3
- ## Problem Summary
4
-
5
- Multiple Park UI recipes reference semantic color tokens (`border`, `error`) as shorthand strings like `borderColor: 'border'` and `borderColor: 'error'`. In Park UI's upstream preset, these are **flat** semantic tokens with a direct `value` property. In the Discourser Design System, they were defined as **nested** tokens (with `default`/`muted` children but no root `value`), which causes Panda CSS to pass the literal string through to CSS instead of resolving it to a CSS variable.
6
-
7
- **Affected CSS output (broken):**
8
- ```css
9
- .checkbox__control { border-color: border; } /* literal string, not a color */
10
- .input--variant_outline:is(:invalid) { border-color: error; } /* same problem */
11
- ```
12
-
13
- **Expected CSS output (working):**
14
- ```css
15
- .checkbox__control { border-color: var(--colors-border); }
16
- .input--variant_outline:is(:invalid) { border-color: var(--colors-error); }
17
- ```
18
-
19
- ## Root Cause
20
-
21
- In `panda.config.ts`, the semantic token aliases section defines:
22
-
23
- ```ts
24
- border: {
25
- default: { value: { base: '{colors.gray.6}', _dark: '{colors.gray.6}' } },
26
- muted: { value: { base: '{colors.gray.4}', _dark: '{colors.gray.4}' } },
27
- },
28
- ```
29
-
30
- Park UI upstream (`park-ui/packages/preset/src/index.ts`) defines:
31
-
32
- ```ts
33
- border: { value: { _light: '{colors.gray.4}', _dark: '{colors.gray.4}' } },
34
- error: { value: { _light: '{colors.red.9}', _dark: '{colors.red.9}' } },
35
- ```
36
-
37
- When Panda CSS encounters `borderColor: 'border'` in a recipe, it looks for a token with a `value` at the `colors.border` path. The Discourser config has no `value` at that level — only `colors.border.default` and `colors.border.muted` exist. Panda falls through and emits the literal string.
38
-
39
- The `error` token is **completely missing** from the Discourser config.
40
-
41
- ## Fix Instructions
42
-
43
- ### File: `panda.config.ts`
44
-
45
- Location: Inside `theme.extend.semanticTokens.colors`, the `border` definition (around line ~130).
46
-
47
- **Change the `border` token from:**
48
- ```ts
49
- border: {
50
- default: {
51
- value: { base: '{colors.gray.6}', _dark: '{colors.gray.6}' },
52
- },
53
- muted: {
54
- value: { base: '{colors.gray.4}', _dark: '{colors.gray.4}' },
55
- },
56
- },
57
- ```
58
-
59
- **To:**
60
- ```ts
61
- border: {
62
- value: { base: '{colors.gray.6}', _dark: '{colors.gray.6}' },
63
- default: {
64
- value: { base: '{colors.gray.6}', _dark: '{colors.gray.6}' },
65
- },
66
- muted: {
67
- value: { base: '{colors.gray.4}', _dark: '{colors.gray.4}' },
68
- },
69
- },
70
- ```
71
-
72
- This adds a root-level `value` that generates `--colors-border` as a CSS variable, while preserving the nested `border.default` and `border.muted` sub-tokens. The root `value` matches `border.default` because that is the semantic equivalent — when recipes say `borderColor: 'border'` they mean the default border color.
73
-
74
- **Then add the missing `error` token.** Place it right after the `border` block, before `...m3SemanticTokens`:
75
-
76
- ```ts
77
- error: {
78
- value: { base: '{colors.red.9}', _dark: '{colors.red.9}' },
79
- },
80
- ```
81
-
82
- This matches Park UI upstream exactly. The `error` token is referenced by Input, Textarea, Select, and other form component recipes for invalid/error states.
83
-
84
- ### No recipe file changes needed
85
-
86
- Do NOT modify any recipe files (`checkbox.ts`, `radio-group.ts`, `input.ts`, etc.). They are character-identical to Park UI upstream and are correct. The fix is entirely in the token definitions.
87
-
88
- ### No story file changes needed for this fix
89
-
90
- The checkbox stories may benefit from adding `colorPalette="primary"` to demonstrate the solid variant's checked state properly, but that is a story improvement, not a bug fix. The rendering fix is the token change above.
91
-
92
- ## Verification Steps
93
-
94
- After making the change:
95
-
96
- 1. **Rebuild Panda CSS:**
97
- ```bash
98
- pnpm panda codegen
99
- ```
100
-
101
- 2. **Check that `--colors-border` now exists in the generated CSS.** Look in `styled-system/styles.css` or rebuild Storybook and check the output CSS. You should see:
102
- ```css
103
- --colors-border: var(--colors-gray-6);
104
- --colors-border-default: var(--colors-gray-6);
105
- --colors-border-muted: var(--colors-gray-4);
106
- --colors-error: var(--colors-red-9);
107
- ```
108
-
109
- 3. **Check checkbox renders with visible border.** The `.checkbox__control` rule should now show:
110
- ```css
111
- border-color: var(--colors-border);
112
- ```
113
-
114
- 4. **Check input error states work.** The `.input--variant_outline:is(:invalid)` rule should show:
115
- ```css
116
- border-color: var(--colors-error);
117
- ```
118
-
119
- 5. **Run Storybook** and visually confirm:
120
- - Checkbox: unchecked state shows a visible border (gray ring around the box)
121
- - Checkbox solid variant: checked state fills with `colorPalette` color
122
- - Radio: unchecked state shows a visible circle border (this already works via the `boxShadow` pattern using `gray.surface.border`, but verify no regression)
123
- - Input: invalid states show red border
124
-
125
- ## Scope of Impact
126
-
127
- This fix affects every component recipe that references the bare `'border'` or `'error'` token strings. Based on CSS analysis, these components currently have broken token resolution:
128
-
129
- **`border` literal (fixed by adding root `value`):**
130
- - Checkbox (base `control` + solid variant `control`)
131
- - Stepper (`indicator` border-color)
132
- - Slider (`track` background — uses `background: border`)
133
- - Tabs enclosed variant (`--shadow-color: border`)
134
-
135
- **`error` literal (fixed by adding `error` token):**
136
- - Input (outline, surface, subtle, flushed variants — invalid state `border-color`)
137
- - Textarea (outline, surface, subtle, flushed variants — invalid state)
138
- - Input flushed variant (`--shadow-color: error` on focus+invalid)
139
- - Textarea flushed variant (`--shadow-color: error` on focus+invalid)
140
-
141
- ## Why Radio Buttons Already Work
142
-
143
- The radio button recipe uses a different pattern: `boxShadow: 'inset 0 0 0 1px {colors.gray.surface.border}'` with `--shadow-color` set to the fully-qualified token path `gray.surface.border`. This resolves correctly because `gray.surface.border` has a direct `value` in the color palette definitions. No fix needed for radio unchecked state visibility.
144
-
145
- If radio buttons appear invisible in Storybook, the issue is likely CSS specificity or a missing `colorPalette` prop on the story — not a token resolution problem. The CSS output for radio is correct: `--shadow-color: var(--colors-gray-surface-border)` which resolves to `var(--colors-neutral-6)` → `#91918B`.
@@ -1,154 +0,0 @@
1
- # Icon Component Creation Prompt
2
- # Target: Claude Code in Discourser-Design-System repo
3
-
4
- ---
5
-
6
- ## Task
7
-
8
- Create 17 new icon components in the DDS, add them all to the Icons story gallery, add each one to the index, and create a Figma Code Connect file for each.
9
-
10
- ---
11
-
12
- ## Reference Pattern
13
-
14
- Before writing any code, read these files to understand the exact pattern to follow:
15
-
16
- - `src/components/Icons/AccountIcon.tsx` — icon component pattern
17
- - `src/components/Icons/DiscourserLogo.figma.tsx` — Code Connect file pattern
18
- - `stories/Icons.stories.tsx` — existing story to extend (Gallery story)
19
- - `src/components/Icons/index.ts` — barrel export to extend
20
-
21
- **Component pattern summary:**
22
- ```typescript
23
- import { ark } from '@ark-ui/react/factory';
24
- import type { ComponentProps } from 'react';
25
- import { styled } from 'styled-system/jsx';
26
-
27
- const StyledSvg = styled(ark.svg);
28
-
29
- export type {ComponentName}Props = ComponentProps<typeof StyledSvg>;
30
-
31
- export const {ComponentName} = (props: {ComponentName}Props) => (
32
- <StyledSvg
33
- viewBox="{viewBox from SVG}"
34
- fill="none"
35
- xmlns="http://www.w3.org/2000/svg"
36
- width="1em"
37
- height="1em"
38
- {...props}
39
- >
40
- {/* paths here */}
41
- </StyledSvg>
42
- );
43
- ```
44
-
45
- **⚠️ CRITICAL — currentColor rule:**
46
- Every SVG has hardcoded color values (`#6B7A1F`, `#518500`, `#FFFDFA`, `#F2F2F2`, `#D9E57A`, etc.). These MUST ALL be replaced with `currentColor` so icons inherit color from their parent via the token system. No hardcoded color values anywhere in any component.
47
-
48
- - `stroke="#6B7A1F"` → `stroke="currentColor"`
49
- - `fill="#6B7A1F"` → `fill="currentColor"`
50
- - `stroke="#FFFDFA"` → `stroke="currentColor"`
51
- - `fill="#FFFDFA"` → `fill="currentColor"`
52
- - Any other hardcoded hex → `currentColor`
53
-
54
- For icons that use BOTH `fill` and `stroke` on the same path (mixed rendering), use `fill="currentColor"` where fill is the primary visual and `stroke="none"`, or `stroke="currentColor"` and `fill="none"` — match the visual intent of the original. When in doubt, prefer `stroke="currentColor"` with `fill="none"` as that matches the majority of existing icons.
55
-
56
- **Code Connect pattern:**
57
- ```typescript
58
- import figma from '@figma/code-connect';
59
- import { {ComponentName} } from './{ComponentName}';
60
-
61
- figma.connect(
62
- {ComponentName},
63
- 'https://www.figma.com/design/GaHmFfmvO4loUzuZS4TgEz/Discourser.AI--V1?node-id={NODE_ID}',
64
- {
65
- example: () => <{ComponentName} />,
66
- },
67
- );
68
- ```
69
-
70
- ---
71
-
72
- ## Icons to Create
73
-
74
- All SVG source files are in `docs/context-share/icons/`. Create each component in `src/components/Icons/`.
75
-
76
- | SVG File | Component Name | viewBox | Node ID |
77
- |----------|---------------|---------|---------|
78
- | `Timer.svg` | `TimerIcon` | `0 0 35 39` | `38-9817` |
79
- | `ClipBoard.svg` | `ClipBoardIcon` | `0 0 40 39` | `38-9804` |
80
- | `Microphone.svg` | `MicrophoneIcon` | `0 0 40 45` | `38-9821` |
81
- | `Audience.svg` | `AudienceIcon` | `0 0 40 44` | `38-9825` |
82
- | `Record.svg` | `RecordIcon` | `0 0 36 39` | `38-9843` |
83
- | `NotebookPen.svg` | `NotebookPenIcon` | `0 0 42 42` | `38-9871` |
84
- | `Sparkles.svg` | `SparklesIcon` | `0 0 24 27` | `38-9872` |
85
- | `ScrollText.svg` | `ScrollTextIcon` | `0 0 42 42` | `38-9873` |
86
- | `RepeatQuestion.svg` | `RepeatQuestionIcon` | `0 0 64 63` | `38-9863` |
87
- | `ExitStudio.svg` | `ExitStudioIcon` | `0 0 64 64` | `38-9853` |
88
- | `PausePlay.svg` | `PausePlayIcon` | `0 0 64 64` | `38-9849` |
89
- | `StopPlay.svg` | `StopPlayIcon` | `0 0 64 64` | `38-9857` |
90
- | `BookmarkPlus.svg` | `BookmarkPlusIcon` | `0 0 42 42` | `38-9870` |
91
- | `AudioSpeaker.svg` | `AudioSpeakerIcon` | `0 0 40 28` | `38-9812` |
92
- | `UserProfile.svg` | `UserProfileIcon` | `0 0 42 42` | `38-9874` |
93
- | `Play.svg` | `PlayIcon` | `0 0 63 63` | `38-9861` |
94
- | `Speech.svg` | `SpeechIcon` | `0 0 60 60` | `618-5193` |
95
-
96
- ---
97
-
98
- ## Files to CREATE (per icon — 17 × 2 = 34 files)
99
-
100
- For each icon in the table above:
101
-
102
- 1. `src/components/Icons/{ComponentName}.tsx` — the component
103
- 2. `src/components/Icons/{ComponentName}.figma.tsx` — the Code Connect file
104
-
105
- ---
106
-
107
- ## Files to UPDATE (2 files)
108
-
109
- ### 1. `src/components/Icons/index.ts`
110
- Add an export for every new component:
111
- ```typescript
112
- export { TimerIcon, type TimerIconProps } from './TimerIcon';
113
- export { ClipBoardIcon, type ClipBoardIconProps } from './ClipBoardIcon';
114
- // ... all 17
115
- ```
116
-
117
- ### 2. `stories/Icons.stories.tsx`
118
- - Add an import for every new component at the top
119
- - Add every new icon to the existing `Gallery` story's `HStack` — same pattern as existing icons:
120
- ```tsx
121
- <VStack gap="2" alignItems="center">
122
- <TimerIcon w="6" h="6" color="fg.default" />
123
- <span className={label}>TimerIcon</span>
124
- </VStack>
125
- ```
126
-
127
- ---
128
-
129
- ## Special Notes Per Icon
130
-
131
- **StopPlay** — has a `<rect>` element with `fill="#FFFDFA"`. Replace with `fill="currentColor"`. Keep the `rx="8"` attribute.
132
-
133
- **ExitStudio** — has a `<circle>` element with `stroke="#FFFDFA"`. Replace with `stroke="currentColor"` and `fill="none"`.
134
-
135
- **PausePlay** — has a `<circle>` with `stroke="#FFFDFA"`. Replace with `stroke="currentColor"` and `fill="none"`.
136
-
137
- **Play** — has a `<circle>` outline and triangle path, both `stroke="white"`. Replace both with `stroke="currentColor"` and `fill="none"`.
138
-
139
- **Audience** — uses `fill="#6B7A1F"` (not stroke) on all paths. Replace with `fill="currentColor"`. Remove any `stroke` attributes if present. Set top-level `fill` prop to `"currentColor"` instead of `"none"` for this component only.
140
-
141
- **ClipBoard** — has two different hardcoded stroke colors (`#6B7A1F` and `#54643F`) on different paths. Replace both with `currentColor` — they should unify to a single color when tokenized.
142
-
143
- **RepeatQuestion** — uses `stroke="#F2F2F2"`. Replace with `currentColor`.
144
-
145
- **Speech** — uses `stroke="#D9E57A"`. Replace with `currentColor`.
146
-
147
- ---
148
-
149
- ## Quality Gate
150
-
151
- After creating all files, verify:
152
- - `pnpm type-check` — 0 errors
153
- - `pnpm build` — builds cleanly
154
- - No hardcoded hex color values remain in any new component file (grep check: `grep -r "#[0-9A-Fa-f]" src/components/Icons/` should return no new files)