@discourser/design-system 0.27.0 → 0.28.1

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 (39) hide show
  1. package/dist/{chunk-AZ6QU2L2.cjs → chunk-5H764SHY.cjs} +251 -4
  2. package/dist/chunk-5H764SHY.cjs.map +1 -0
  3. package/dist/{chunk-MAVUSE4F.js → chunk-JDERS7J6.js} +21 -20
  4. package/dist/chunk-JDERS7J6.js.map +1 -0
  5. package/dist/{chunk-4XOWPACJ.js → chunk-WMHVCIDI.js} +251 -4
  6. package/dist/chunk-WMHVCIDI.js.map +1 -0
  7. package/dist/{chunk-EBDNCZF6.cjs → chunk-X3W33YGV.cjs} +21 -20
  8. package/dist/chunk-X3W33YGV.cjs.map +1 -0
  9. package/dist/components/Breadcrumb.d.ts.map +1 -1
  10. package/dist/components/SettingsPopover/SettingsPopover.d.ts.map +1 -1
  11. package/dist/components/StudioControls/StudioControls.d.ts +1 -1
  12. package/dist/components/StudioControls/StudioControls.d.ts.map +1 -1
  13. package/dist/components/StudioControls/types.d.ts +3 -0
  14. package/dist/components/StudioControls/types.d.ts.map +1 -1
  15. package/dist/components/index.cjs +76 -76
  16. package/dist/components/index.js +1 -1
  17. package/dist/figma-codex.json +9 -3
  18. package/dist/index.cjs +80 -80
  19. package/dist/index.js +2 -2
  20. package/dist/panda.buildinfo.json +856 -0
  21. package/dist/preset/index.cjs +2 -2
  22. package/dist/preset/index.d.ts.map +1 -1
  23. package/dist/preset/index.js +1 -1
  24. package/dist/preset/recipes/studio-controls.d.ts.map +1 -1
  25. package/docs/component-catalog.md +2 -2
  26. package/package.json +3 -2
  27. package/src/components/Breadcrumb.figma.tsx +68 -17
  28. package/src/components/Breadcrumb.tsx +4 -3
  29. package/src/components/SettingsPopover/SettingsPopover.tsx +1 -3
  30. package/src/components/StudioControls/StudioControls.tsx +15 -13
  31. package/src/components/StudioControls/types.ts +4 -0
  32. package/src/preset/index.ts +2 -0
  33. package/src/preset/recipes/breadcrumb.ts +1 -1
  34. package/src/preset/recipes/studio-controls.ts +8 -11
  35. package/src/test/setup.ts +17 -3
  36. package/dist/chunk-4XOWPACJ.js.map +0 -1
  37. package/dist/chunk-AZ6QU2L2.cjs.map +0 -1
  38. package/dist/chunk-EBDNCZF6.cjs.map +0 -1
  39. package/dist/chunk-MAVUSE4F.js.map +0 -1
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkAZ6QU2L2_cjs = require('../chunk-AZ6QU2L2.cjs');
3
+ var chunk5H764SHY_cjs = require('../chunk-5H764SHY.cjs');
4
4
  require('../chunk-EARF7VDF.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "discourserPandaPreset", {
9
9
  enumerable: true,
10
- get: function () { return chunkAZ6QU2L2_cjs.discourserPandaPreset; }
10
+ get: function () { return chunk5H764SHY_cjs.discourserPandaPreset; }
11
11
  });
12
12
  //# sourceMappingURL=index.cjs.map
13
13
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/preset/index.ts"],"names":[],"mappings":"AA8DA,eAAO,MAAM,qBAAqB,gCA2JhC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/preset/index.ts"],"names":[],"mappings":"AA+DA,eAAO,MAAM,qBAAqB,gCA4JhC,CAAC"}
@@ -1,4 +1,4 @@
1
- export { discourserPandaPreset } from '../chunk-4XOWPACJ.js';
1
+ export { discourserPandaPreset } from '../chunk-WMHVCIDI.js';
2
2
  import '../chunk-WR5Z5QMQ.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"studio-controls.d.ts","sourceRoot":"","sources":["../../../src/preset/recipes/studio-controls.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,0CAyPzB,CAAC"}
1
+ {"version":3,"file":"studio-controls.d.ts","sourceRoot":"","sources":["../../../src/preset/recipes/studio-controls.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,0CAsPzB,CAAC"}
@@ -2,8 +2,8 @@
2
2
 
3
3
  > **Status:** Generated — auto-produced by `scripts/generate-component-catalog.ts`
4
4
  > **Source:** `stories/ComponentCatalog.stories.tsx` + `src/components/index.ts`
5
- > **Design System Version:** 0.27.0
6
- > **Generated:** 2026-04-04
5
+ > **Design System Version:** 0.28.1
6
+ > **Generated:** 2026-04-08
7
7
  > **Do not hand-edit** — this file is overwritten on every build
8
8
 
9
9
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@discourser/design-system",
3
- "version": "0.27.0",
3
+ "version": "0.28.1",
4
4
  "description": "Aesthetic-agnostic design system with Panda CSS and Ark UI",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -198,9 +198,10 @@
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 catalog:generate && 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 && pnpm build:buildinfo",
202
202
  "build:panda": "panda codegen",
203
203
  "build:css": "panda cssgen --outfile dist/styles.css",
204
+ "build:buildinfo": "panda ship --outfile dist/panda.buildinfo.json",
204
205
  "build:lib": "tsup",
205
206
  "build:types": "tsc --project tsconfig.build.json",
206
207
  "build:storybook": "pnpm build:css && pnpm docs:generate && storybook build",
@@ -1,18 +1,69 @@
1
- import figma from '@figma/code-connect'
2
- import * as Breadcrumb from './Breadcrumb'
1
+ import figma from '@figma/code-connect';
2
+ import * as Breadcrumb from './Breadcrumb';
3
3
 
4
- figma.connect(Breadcrumb.Root, 'https://www.figma.com/design/GaHmFfmvO4loUzuZS4TgEz/Discourser.AI--V1?node-id=38-7978', {
5
- example: () => (
6
- <Breadcrumb.Root>
7
- <Breadcrumb.List>
8
- <Breadcrumb.Item>
9
- <Breadcrumb.Link href="#">Home</Breadcrumb.Link>
10
- </Breadcrumb.Item>
11
- <Breadcrumb.Separator />
12
- <Breadcrumb.Item>
13
- <Breadcrumb.CurrentLink>Current</Breadcrumb.CurrentLink>
14
- </Breadcrumb.Item>
15
- </Breadcrumb.List>
16
- </Breadcrumb.Root>
17
- ),
18
- })
4
+ // Basic breadcrumb — standard navigation trail
5
+ figma.connect(
6
+ Breadcrumb.Root,
7
+ 'https://www.figma.com/design/GaHmFfmvO4loUzuZS4TgEz/Discourser.AI--V1?node-id=38-7978',
8
+ {
9
+ example: () => (
10
+ <Breadcrumb.Root>
11
+ <Breadcrumb.List>
12
+ <Breadcrumb.Item>
13
+ <Breadcrumb.Link href="/home">Home</Breadcrumb.Link>
14
+ </Breadcrumb.Item>
15
+ <Breadcrumb.Separator />
16
+ <Breadcrumb.Item>
17
+ <Breadcrumb.CurrentLink>Current Page</Breadcrumb.CurrentLink>
18
+ </Breadcrumb.Item>
19
+ </Breadcrumb.List>
20
+ </Breadcrumb.Root>
21
+ ),
22
+ },
23
+ );
24
+
25
+ // Two-row wizard breadcrumb — used for multi-step flows (e.g. Conversation Studio)
26
+ // Pattern: TwoRowProgressiveDisclosureStep2
27
+ // - ParentRow shows the static parent context (hidden on first step)
28
+ // - Inner Breadcrumb.Root shows the current wizard progress
29
+ // - Protected steps (conversation, results) render as disabled spans, not links
30
+ figma.connect(
31
+ Breadcrumb.TwoRowRoot,
32
+ 'https://www.figma.com/design/GaHmFfmvO4loUzuZS4TgEz/Discourser.AI--V1?node-id=38-7978',
33
+ {
34
+ example: () => (
35
+ <Breadcrumb.TwoRowRoot aria-label="Conversation Studio steps">
36
+ <Breadcrumb.ParentRow show={true}>
37
+ <Breadcrumb.ParentItem href="/scenarios">
38
+ Scenarios
39
+ </Breadcrumb.ParentItem>
40
+ <Breadcrumb.ParentSeparator />
41
+ <Breadcrumb.ParentItem>Conversation Studio</Breadcrumb.ParentItem>
42
+ </Breadcrumb.ParentRow>
43
+ <Breadcrumb.Root>
44
+ <Breadcrumb.List>
45
+ <Breadcrumb.Item>
46
+ <Breadcrumb.Link href="/scenarios/conversation-studio/settings">
47
+ Level Setting
48
+ </Breadcrumb.Link>
49
+ </Breadcrumb.Item>
50
+ <Breadcrumb.Separator />
51
+ <Breadcrumb.Item>
52
+ <Breadcrumb.CurrentLink>Lobby</Breadcrumb.CurrentLink>
53
+ </Breadcrumb.Item>
54
+ <Breadcrumb.Separator />
55
+ <Breadcrumb.Item>
56
+ {/* Protected step — renders as disabled span, not a link */}
57
+ <Breadcrumb.Link disabled>In Conversation</Breadcrumb.Link>
58
+ </Breadcrumb.Item>
59
+ <Breadcrumb.Separator />
60
+ <Breadcrumb.Item>
61
+ {/* Protected step — renders as disabled span, not a link */}
62
+ <Breadcrumb.Link disabled>Results</Breadcrumb.Link>
63
+ </Breadcrumb.Item>
64
+ </Breadcrumb.List>
65
+ </Breadcrumb.Root>
66
+ </Breadcrumb.TwoRowRoot>
67
+ ),
68
+ },
69
+ );
@@ -122,8 +122,8 @@ export const ParentItem = ({
122
122
  }) => {
123
123
  const styles = css({
124
124
  color: 'fg.subtle',
125
- textStyle: 'sm',
126
- fontWeight: 'normal',
125
+ textStyle: 'bodyMedium',
126
+ fontWeight: 'light',
127
127
  textDecoration: 'none',
128
128
  _hover: href
129
129
  ? { color: 'fg.default', textDecoration: 'underline' }
@@ -145,7 +145,8 @@ export const ParentSeparator = () => (
145
145
  aria-hidden="true"
146
146
  className={css({
147
147
  color: 'fg.subtle',
148
- textStyle: 'sm',
148
+ textStyle: 'bodyMedium',
149
+ fontWeight: 'light',
149
150
  mx: '0.5',
150
151
  })}
151
152
  >
@@ -35,8 +35,6 @@ export function SettingsPopover({
35
35
  borderTopStyle: 'solid',
36
36
  borderTopColor: 'neutral.3',
37
37
  borderRadius: '0',
38
- boxShadow:
39
- '0px -1px 2px rgba(0, 0, 0, 0.3), 0px -2px 6px 2px rgba(0, 0, 0, 0.15)',
40
38
  cursor: 'pointer',
41
39
  transition: 'background 0.2s',
42
40
  _hover: {
@@ -87,7 +85,7 @@ export function SettingsPopover({
87
85
  p: '0',
88
86
  w: '275px',
89
87
  borderRadius: 'l3',
90
- boxShadow: 'level2',
88
+ boxShadow: 'md',
91
89
  overflow: 'hidden',
92
90
  })}
93
91
  >
@@ -47,6 +47,11 @@ const ALL_SECTION_IDS = [
47
47
 
48
48
  // ── Component ─────────────────────────────────────────────────────────────────
49
49
 
50
+ const DEFAULT_TRIGGER_CSS = {
51
+ fontSize: 'sm',
52
+ fontWeight: 'semibold',
53
+ } as const;
54
+
50
55
  export function StudioControls({
51
56
  scenarioName,
52
57
  scenarioFocus,
@@ -56,12 +61,14 @@ export function StudioControls({
56
61
  defaultRecordingMode = 'no-recording',
57
62
  defaultShowTimer = true,
58
63
  defaultHideInterviewers = false,
64
+ triggerCss,
59
65
  onAudioLevelChange,
60
66
  onMicLevelChange,
61
67
  onRecordingModeChange,
62
68
  onTimerChange,
63
69
  onInterviewersChange,
64
70
  }: StudioControlsProps) {
71
+ const resolvedTriggerCss = { ...DEFAULT_TRIGGER_CSS, ...triggerCss };
65
72
  const styles = studioControls();
66
73
 
67
74
  const [audioLevel, setAudioLevel] = useState(defaultAudioLevel);
@@ -78,8 +85,7 @@ export function StudioControls({
78
85
  <Accordion.ItemTrigger
79
86
  className={styles.sectionTrigger}
80
87
  css={{
81
- fontSize: 'lg',
82
- fontWeight: 'medium',
88
+ ...resolvedTriggerCss,
83
89
  borderRadius: '0',
84
90
  py: '4',
85
91
  bg: 'neutral.1',
@@ -132,8 +138,7 @@ export function StudioControls({
132
138
  <Accordion.ItemTrigger
133
139
  className={styles.sectionTrigger}
134
140
  css={{
135
- fontSize: 'lg',
136
- fontWeight: 'medium',
141
+ ...resolvedTriggerCss,
137
142
  borderRadius: '0',
138
143
  py: '4',
139
144
  bg: 'neutral.1',
@@ -183,8 +188,7 @@ export function StudioControls({
183
188
  <Accordion.ItemTrigger
184
189
  className={styles.sectionTrigger}
185
190
  css={{
186
- fontSize: 'lg',
187
- fontWeight: 'medium',
191
+ ...resolvedTriggerCss,
188
192
  borderRadius: '0',
189
193
  py: '4',
190
194
  bg: 'neutral.1',
@@ -234,8 +238,7 @@ export function StudioControls({
234
238
  <Accordion.ItemTrigger
235
239
  className={styles.sectionTrigger}
236
240
  css={{
237
- fontSize: 'lg',
238
- fontWeight: 'medium',
241
+ ...resolvedTriggerCss,
239
242
  borderRadius: '0',
240
243
  py: '4',
241
244
  bg: 'neutral.1',
@@ -279,7 +282,8 @@ export function StudioControls({
279
282
  }}
280
283
  />
281
284
  <RadioGroup.ItemText
282
- css={{ fontSize: 'md', fontWeight: 'medium' }}
285
+ css={{ textStyle: 'bodyMedium' }}
286
+ style={{ fontWeight: 'var(--font-weights-normal)' }}
283
287
  >
284
288
  {option.label}
285
289
  </RadioGroup.ItemText>
@@ -296,8 +300,7 @@ export function StudioControls({
296
300
  <Accordion.ItemTrigger
297
301
  className={styles.sectionTrigger}
298
302
  css={{
299
- fontSize: 'lg',
300
- fontWeight: 'medium',
303
+ ...resolvedTriggerCss,
301
304
  borderRadius: '0',
302
305
  py: '4',
303
306
  bg: 'neutral.1',
@@ -338,8 +341,7 @@ export function StudioControls({
338
341
  <Accordion.ItemTrigger
339
342
  className={styles.sectionTrigger}
340
343
  css={{
341
- fontSize: 'lg',
342
- fontWeight: 'medium',
344
+ ...resolvedTriggerCss,
343
345
  borderRadius: '0',
344
346
  py: '4',
345
347
  bg: 'neutral.1',
@@ -1,6 +1,10 @@
1
+ import type { SystemStyleObject } from 'styled-system/types';
2
+
1
3
  export type RecordingMode = 'no-recording' | 'audio-only' | 'video-audio';
2
4
 
3
5
  export interface StudioControlsProps {
6
+ /** Override CSS for every accordion trigger label — customize font, size, weight from the consuming app */
7
+ triggerCss?: SystemStyleObject;
4
8
  scenarioName: string;
5
9
  scenarioFocus: string;
6
10
  scenarioLevel: 'beginner' | 'intermediate' | 'advanced';
@@ -52,6 +52,7 @@ import { contentCard } from './recipes/content-card';
52
52
  import { scenarioCard } from './recipes/scenario-card';
53
53
  import { scenarioQueue } from './recipes/scenario-queue';
54
54
  import { scenarioSettings } from './recipes/scenario-settings';
55
+ import { studioControls } from './recipes/studio-controls';
55
56
 
56
57
  // Park UI theme extensions
57
58
  import { layerStyles } from './layer-styles';
@@ -195,6 +196,7 @@ export const discourserPandaPreset = definePreset({
195
196
  scenarioCard,
196
197
  scenarioQueue,
197
198
  scenarioSettings,
199
+ studioControls,
198
200
  },
199
201
  },
200
202
  },
@@ -83,8 +83,8 @@ export const breadcrumb = defineSlotRecipe({
83
83
  },
84
84
  link: {
85
85
  color: 'fg.subtle',
86
+ textStyle: 'bodyMedium',
86
87
  fontWeight: 'medium',
87
- fontSize: 'lg',
88
88
  _hover: { color: 'fg.default' },
89
89
  _currentPage: { color: 'fg.default', fontWeight: 'semibold' },
90
90
  },
@@ -105,16 +105,14 @@ export const studioControls = defineSlotRecipe({
105
105
  gap: '1',
106
106
  },
107
107
  scenarioName: {
108
- fontSize: 'lg',
108
+ textStyle: 'bodyMedium',
109
109
  fontWeight: 'semibold',
110
110
  color: 'onSurface',
111
- lineHeight: '1.2',
112
111
  },
113
112
  scenarioFocus: {
114
- fontSize: 'sm',
113
+ textStyle: 'bodyMedium',
115
114
  fontWeight: 'medium',
116
115
  color: 'onSurface',
117
- lineHeight: '1.4',
118
116
  },
119
117
  // Stone-bg inner card — Figma: #F5F1EB ≈ surface.container
120
118
  settingsCard: {
@@ -127,7 +125,7 @@ export const studioControls = defineSlotRecipe({
127
125
  py: '2.5',
128
126
  },
129
127
  settingsCardHeading: {
130
- fontSize: 'md',
128
+ textStyle: 'bodyMedium',
131
129
  fontWeight: 'medium',
132
130
  color: 'onSurface',
133
131
  },
@@ -143,7 +141,7 @@ export const studioControls = defineSlotRecipe({
143
141
  width: 'full',
144
142
  },
145
143
  settingsRowLabel: {
146
- fontSize: 'sm',
144
+ textStyle: 'bodyMedium',
147
145
  fontWeight: 'medium',
148
146
  color: 'onSurface',
149
147
  flex: 1,
@@ -198,8 +196,8 @@ export const studioControls = defineSlotRecipe({
198
196
  width: 'full',
199
197
  },
200
198
  sliderLabelText: {
201
- fontSize: 'md',
202
- fontWeight: 'semibold',
199
+ textStyle: 'bodyMedium',
200
+ fontWeight: 'medium',
203
201
  color: 'onSurface',
204
202
  },
205
203
  levelBadge: {
@@ -242,10 +240,9 @@ export const studioControls = defineSlotRecipe({
242
240
  width: 'full',
243
241
  },
244
242
  toggleDescription: {
245
- fontSize: 'sm',
246
- fontWeight: 'normal',
243
+ textStyle: 'bodyMedium',
244
+ fontWeight: 'medium',
247
245
  color: 'onSurface',
248
- lineHeight: '1.4',
249
246
  flex: 1,
250
247
  },
251
248
  },
package/src/test/setup.ts CHANGED
@@ -6,15 +6,29 @@ import { toHaveNoViolations } from 'jest-axe';
6
6
  // Extend Vitest's expect with jest-axe matchers
7
7
  expect.extend(toHaveNoViolations);
8
8
 
9
- // Mock ResizeObserver — JSDOM does not implement it, but @zag-js/tabs requires
10
- // it to sync the active tab indicator rectangle position.
9
+ // Mock ResizeObserver — JSDOM does not implement it, but @zag-js components
10
+ // (tabs, accordion, etc.) require it to measure content dimensions.
11
+ // The mock calls back immediately on observe() so that accordion content panels
12
+ // receive their height measurement and remove their `hidden` attribute, making
13
+ // links/content accessible to RTL after a click interaction.
11
14
  // Guard for Node.js environment (e.g. figma-codex tests with @vitest-environment node)
12
15
  if (typeof window !== 'undefined') {
13
16
  Object.defineProperty(window, 'ResizeObserver', {
14
17
  writable: true,
15
18
  configurable: true,
16
19
  value: class ResizeObserver {
17
- observe() {}
20
+ private callback: (entries: object[], observer: object) => void;
21
+ constructor(callback: (entries: object[], observer: object) => void) {
22
+ this.callback = callback;
23
+ }
24
+ observe(target: Element) {
25
+ // Call back synchronously with a mock entry so zag-js state machines
26
+ // receive content dimensions and proceed to unhide animated content.
27
+ this.callback(
28
+ [{ contentRect: target.getBoundingClientRect(), target }],
29
+ this,
30
+ );
31
+ }
18
32
  unobserve() {}
19
33
  disconnect() {}
20
34
  },