@robr0/design-system 0.3.0 → 0.4.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 (45) hide show
  1. package/README.md +30 -27
  2. package/components/AgentStatus/AgentStatus.css +436 -0
  3. package/components/AgentStatus/AgentStatus.d.ts +37 -0
  4. package/components/AgentStatus/AgentStatus.js +53 -0
  5. package/components/AgentStatus/AgentStatusPatterns.d.ts +17 -0
  6. package/components/AgentStatus/AgentStatusPatterns.js +20 -0
  7. package/components/AlertDialog/AlertDialog.css +5 -5
  8. package/components/Button/Button.d.ts +14 -2
  9. package/components/ButtonGroup/ButtonGroup.js +2 -9
  10. package/components/Checkbox/Checkbox.d.ts +17 -3
  11. package/components/CircularButton/CircularButton.d.ts +9 -3
  12. package/components/CircularButton/CircularButton.js +4 -2
  13. package/components/Combobox/Combobox.d.ts +10 -2
  14. package/components/ContextMenu/ContextMenu.css +0 -4
  15. package/components/DateInput/DateInput.d.ts +5 -1
  16. package/components/Dialog/Dialog.css +5 -5
  17. package/components/Dropdown/Dropdown.css +2 -4
  18. package/components/Dropdown/Dropdown.d.ts +10 -2
  19. package/components/DropdownMenu/DropdownMenu.css +2 -4
  20. package/components/FileInput/FileInput.d.ts +5 -1
  21. package/components/Input/Input.d.ts +5 -1
  22. package/components/LinkList/LinkList.d.ts +1 -0
  23. package/components/RadioButton/RadioButton.d.ts +17 -3
  24. package/components/Reasoning/Reasoning.css +152 -0
  25. package/components/Reasoning/Reasoning.d.ts +36 -0
  26. package/components/Reasoning/Reasoning.js +69 -0
  27. package/components/SelectionCard/SelectionCard.d.ts +5 -1
  28. package/components/Slider/Slider.d.ts +5 -1
  29. package/components/Textarea/Textarea.d.ts +5 -1
  30. package/components/Timeline/Timeline.d.ts +2 -0
  31. package/components/ToggleGroup/ToggleGroup.d.ts +10 -2
  32. package/components/ToggleSwitch/ToggleSwitch.d.ts +10 -2
  33. package/components/ToolCall/ToolCall.css +213 -0
  34. package/components/ToolCall/ToolCall.d.ts +43 -0
  35. package/components/ToolCall/ToolCall.js +89 -0
  36. package/components/registry.json +32 -7
  37. package/components/registry.json.d.ts +32 -7
  38. package/components/registry.json.js +2 -2
  39. package/index.d.ts +4 -0
  40. package/index.js +8 -0
  41. package/package.json +8 -4
  42. package/tokens/registry.json +1 -0
  43. package/tokens/registry.json.d.ts +1 -0
  44. package/tokens/registry.json.js +1 -1
  45. package/tokens/tokens-motion.css +3 -1
@@ -0,0 +1,17 @@
1
+ /**
2
+ * AgentStatus's vocabulary, kept out of the component file so that module
3
+ * exports only a component (react-refresh) — and exported rather than kept
4
+ * private so a consumer building a pattern picker, and this repo's own docs
5
+ * gallery, can iterate the list instead of restating it.
6
+ *
7
+ * `.tsx` despite holding no JSX: the barrel generator and the
8
+ * `./components/*` export subpath both address `.tsx`, so that extension is
9
+ * what makes this reachable as `@robr0/design-system/components/AgentStatus/AgentStatusPatterns`.
10
+ */
11
+ /**
12
+ * The dot-matrix animations. Each pattern is a named choreography over the
13
+ * same 4x3 grid, so switching pattern never changes the indicator's footprint.
14
+ */
15
+ export declare const agentStatusPatterns: readonly ["braille", "orbit", "breathe", "snake", "fill-sweep", "pulse", "columns", "checkerboard", "scan", "rain", "cascade", "sparkle", "wave-rows", "helix", "diagonal-swipe"];
16
+ export type AgentStatusPattern = (typeof agentStatusPatterns)[number];
17
+ export type AgentStatusState = 'idle' | 'thinking' | 'working' | 'waiting' | 'done' | 'error';
@@ -0,0 +1,20 @@
1
+ const agentStatusPatterns = [
2
+ "braille",
3
+ "orbit",
4
+ "breathe",
5
+ "snake",
6
+ "fill-sweep",
7
+ "pulse",
8
+ "columns",
9
+ "checkerboard",
10
+ "scan",
11
+ "rain",
12
+ "cascade",
13
+ "sparkle",
14
+ "wave-rows",
15
+ "helix",
16
+ "diagonal-swipe"
17
+ ];
18
+ export {
19
+ agentStatusPatterns
20
+ };
@@ -81,11 +81,11 @@
81
81
  ============================================ */
82
82
 
83
83
  .ds-alert-dialog__title {
84
- font-family: var(--font-heading-6-family);
85
- font-size: var(--font-heading-6-size);
86
- font-weight: var(--font-heading-6-weight);
87
- line-height: var(--font-heading-6-line-height);
88
- letter-spacing: var(--font-heading-6-letter-spacing);
84
+ font-family: var(--font-heading-3-family);
85
+ font-size: var(--font-heading-3-size);
86
+ font-weight: var(--font-heading-3-weight);
87
+ line-height: var(--font-heading-3-line-height);
88
+ letter-spacing: var(--font-heading-3-letter-spacing);
89
89
  color: var(--color-text-primary);
90
90
  margin: 0;
91
91
  }
@@ -29,9 +29,15 @@ type ButtonOwnProps = {
29
29
  ariaCurrent?: boolean;
30
30
  /** Additional CSS classes */
31
31
  className?: string;
32
- /** @deprecated Use `variant` instead. */
32
+ /**
33
+ * Legacy alias for `variant`.
34
+ *
35
+ * @deprecated Use `variant` instead.
36
+ */
33
37
  priority?: 'primary' | 'secondary' | 'tertiary' | 'destructive';
34
38
  /**
39
+ * Documentation-only interaction state.
40
+ *
35
41
  * @deprecated Use `disabled` for the disabled state.
36
42
  *
37
43
  * Documentation-only affordance for rendering a *static* interaction state in
@@ -39,9 +45,15 @@ type ButtonOwnProps = {
39
45
  * pseudo-classes and needs no prop — for docs, prefer `className="ds-button--hover"`.
40
46
  */
41
47
  state?: 'default' | 'hover' | 'active' | 'disabled';
42
- /** @deprecated Use `iconLeft` instead. */
48
+ /**
49
+ * Legacy alias for `iconLeft`.
50
+ *
51
+ * @deprecated Use `iconLeft` instead.
52
+ */
43
53
  icon?: string;
44
54
  /**
55
+ * Legacy toggle for showing the text label.
56
+ *
45
57
  * @deprecated Will be removed once `label` loses its default in the next major;
46
58
  * an icon-only button will simply omit `label`.
47
59
  */
@@ -17,15 +17,8 @@ const ButtonGroup = ({
17
17
  children: buttons.map((button, index) => /* @__PURE__ */ jsx(
18
18
  Button,
19
19
  {
20
- priority: button.priority || "tertiary",
21
- state: button.state || "default",
22
- label: button.label,
23
- iconLeft: button.iconLeft,
24
- iconRight: button.iconRight,
25
- icon: button.icon,
26
- onClick: button.onClick,
27
- href: button.href,
28
- ariaCurrent: button.ariaCurrent
20
+ ...button,
21
+ variant: button.variant ?? button.priority ?? "tertiary"
29
22
  },
30
23
  index
31
24
  ))
@@ -15,11 +15,21 @@ type CheckboxOwnProps = {
15
15
  onCheckedChange?: (checked: boolean) => void;
16
16
  /** Additional CSS classes */
17
17
  className?: string;
18
- /** @deprecated Use `onCheckedChange` instead. */
18
+ /**
19
+ * Legacy change handler, kept for backwards compatibility.
20
+ *
21
+ * @deprecated Use `onCheckedChange` instead.
22
+ */
19
23
  onChange?: (checked: boolean) => void;
20
- /** @deprecated Pass the native `aria-label` attribute instead. */
24
+ /**
25
+ * Legacy accessible-name prop.
26
+ *
27
+ * @deprecated Pass the native `aria-label` attribute instead.
28
+ */
21
29
  ariaLabel?: string;
22
30
  /**
31
+ * Legacy form-field name.
32
+ *
23
33
  * @deprecated No-op. This component renders a `<div role="checkbox">`, not a
24
34
  * native `<input>`, so it cannot participate in native form submission.
25
35
  * Declared only so the attribute is not forwarded to an element that rejects it.
@@ -48,7 +58,11 @@ type CheckboxGroupOwnProps = {
48
58
  onValuesChange?: (values: string[]) => void;
49
59
  /** Additional CSS classes */
50
60
  className?: string;
51
- /** @deprecated Use `onValuesChange` instead. */
61
+ /**
62
+ * Legacy change handler, kept for backwards compatibility.
63
+ *
64
+ * @deprecated Use `onValuesChange` instead.
65
+ */
52
66
  onChange?: (values: string[]) => void;
53
67
  };
54
68
  export interface CheckboxGroupProps extends CheckboxGroupOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof CheckboxGroupOwnProps> {
@@ -1,7 +1,13 @@
1
1
  export interface CircularButtonProps {
2
2
  /** Material Symbol icon name */
3
3
  icon: string;
4
- /** Button priority/variant */
4
+ /** Visual treatment */
5
+ variant?: 'primary' | 'secondary' | 'tertiary';
6
+ /**
7
+ * Legacy alias for `variant`.
8
+ *
9
+ * @deprecated Use `variant` instead.
10
+ */
5
11
  priority?: 'primary' | 'secondary' | 'tertiary';
6
12
  /** Button state */
7
13
  state?: 'default' | 'hover' | 'active' | 'disabled';
@@ -31,6 +37,6 @@ export interface CircularButtonProps {
31
37
  /**
32
38
  * Circular icon button component.
33
39
  * A round button containing a single icon, available in
34
- * primary and secondary variants with default and compact sizes.
40
+ * primary, secondary and tertiary variants with default and compact sizes.
35
41
  */
36
- export declare const CircularButton: ({ icon, priority, state, size, loading, ariaLabel, onClick, href, target, rel, "aria-describedby": ariaDescribedby, className, }: CircularButtonProps) => import("react").JSX.Element;
42
+ export declare const CircularButton: ({ icon, variant, priority, state, size, loading, ariaLabel, onClick, href, target, rel, "aria-describedby": ariaDescribedby, className, }: CircularButtonProps) => import("react").JSX.Element;
@@ -4,7 +4,8 @@ import "./CircularButton.css";
4
4
  import "../../fonts/material-symbols.css";
5
5
  const CircularButton = ({
6
6
  icon,
7
- priority = "primary",
7
+ variant,
8
+ priority,
8
9
  state = "default",
9
10
  size = "default",
10
11
  loading,
@@ -17,7 +18,8 @@ const CircularButton = ({
17
18
  className = ""
18
19
  }) => {
19
20
  const baseClass = "ds-circular-button";
20
- const variantClass = `${baseClass}--${priority}`;
21
+ const resolvedVariant = variant ?? priority ?? "primary";
22
+ const variantClass = `${baseClass}--${resolvedVariant}`;
21
23
  const stateClass = `${baseClass}--${state}`;
22
24
  const sizeClass = `${baseClass}--${size}`;
23
25
  const isLoading = Boolean(loading);
@@ -59,9 +59,17 @@ type ComboboxOwnProps = {
59
59
  manualFiltering?: boolean;
60
60
  /** Additional CSS classes */
61
61
  className?: string;
62
- /** @deprecated Use `onValueChange` instead. */
62
+ /**
63
+ * Legacy change handler, kept for backwards compatibility.
64
+ *
65
+ * @deprecated Use `onValueChange` instead.
66
+ */
63
67
  onChange?: (value: string | string[]) => void;
64
- /** @deprecated Pass the native `aria-label` attribute instead. */
68
+ /**
69
+ * Legacy accessible-name prop.
70
+ *
71
+ * @deprecated Pass the native `aria-label` attribute instead.
72
+ */
65
73
  ariaLabel?: string;
66
74
  /**
67
75
  * Used only as a fallback for deriving the element id (`id || name || generated`).
@@ -71,10 +71,6 @@
71
71
  margin: var(--padding-xxs) var(--padding-sm-md);
72
72
  }
73
73
 
74
- .ds-context-menu__panel--compact .ds-context-menu__shortcut {
75
- font-size: var(--font-caption-size);
76
- }
77
-
78
74
  /* ============================================
79
75
  SUB-MENU PANEL
80
76
  Positioned relative to its parent item.
@@ -23,7 +23,11 @@ type DateInputOwnProps = {
23
23
  onValueChange?: (value: string) => void;
24
24
  /** Additional CSS classes — applied to the wrapper, not the <input> */
25
25
  className?: string;
26
- /** @deprecated Pass the native `aria-label` attribute instead. */
26
+ /**
27
+ * Legacy accessible-name prop.
28
+ *
29
+ * @deprecated Pass the native `aria-label` attribute instead.
30
+ */
27
31
  ariaLabel?: string;
28
32
  };
29
33
  export interface DateInputProps extends DateInputOwnProps, Omit<React.ComponentPropsWithoutRef<'input'>, keyof DateInputOwnProps | 'type'> {
@@ -88,11 +88,11 @@
88
88
  }
89
89
 
90
90
  .ds-dialog__title {
91
- font-family: var(--font-heading-6-family);
92
- font-size: var(--font-heading-6-size);
93
- font-weight: var(--font-heading-6-weight);
94
- line-height: var(--font-heading-6-line-height);
95
- letter-spacing: var(--font-heading-6-letter-spacing);
91
+ font-family: var(--font-heading-3-family);
92
+ font-size: var(--font-heading-3-size);
93
+ font-weight: var(--font-heading-3-weight);
94
+ line-height: var(--font-heading-3-line-height);
95
+ letter-spacing: var(--font-heading-3-letter-spacing);
96
96
  color: var(--color-text-primary);
97
97
  margin: 0;
98
98
  }
@@ -254,10 +254,8 @@
254
254
  letter-spacing: var(--font-paragraph-sm-em-letter-spacing);
255
255
  }
256
256
 
257
- .ds-dropdown--compact .ds-dropdown__group-label {
258
- font-size: var(--font-caption-size);
259
- line-height: var(--font-caption-line-height);
260
- }
257
+ /* Compact group labels keep the base --font-paragraph-sm-* type — the
258
+ scale has no smaller step. */
261
259
 
262
260
  .ds-dropdown--compact .ds-dropdown__check {
263
261
  --icon-size: var(--icon-size-sm);
@@ -39,9 +39,17 @@ type DropdownOwnProps = {
39
39
  onValueChange?: (value: string) => void;
40
40
  /** Additional CSS classes */
41
41
  className?: string;
42
- /** @deprecated Use `onValueChange` instead. */
42
+ /**
43
+ * Legacy change handler, kept for backwards compatibility.
44
+ *
45
+ * @deprecated Use `onValueChange` instead.
46
+ */
43
47
  onChange?: (value: string) => void;
44
- /** @deprecated Pass the native `aria-label` attribute instead. */
48
+ /**
49
+ * Legacy accessible-name prop.
50
+ *
51
+ * @deprecated Pass the native `aria-label` attribute instead.
52
+ */
45
53
  ariaLabel?: string;
46
54
  /**
47
55
  * Used only as a fallback for deriving the element id (`id || name || label`).
@@ -96,10 +96,8 @@
96
96
  margin: var(--padding-xxs) var(--padding-sm-md);
97
97
  }
98
98
 
99
- /* Compact shortcuts */
100
- .ds-dropdown-menu__panel--compact .ds-dropdown-menu__shortcut {
101
- font-size: var(--font-caption-size);
102
- }
99
+ /* Compact shortcuts keep the base --font-paragraph-sm-* size — the scale
100
+ has no smaller step. */
103
101
 
104
102
  /* ============================================
105
103
  SUB-MENU PANEL
@@ -31,7 +31,11 @@ type FileInputOwnProps = {
31
31
  onFileRemove?: (id: string) => void;
32
32
  /** Additional CSS classes — applied to the wrapper, not the <input> */
33
33
  className?: string;
34
- /** @deprecated Pass the native `aria-label` attribute instead. */
34
+ /**
35
+ * Legacy accessible-name prop.
36
+ *
37
+ * @deprecated Pass the native `aria-label` attribute instead.
38
+ */
35
39
  ariaLabel?: string;
36
40
  };
37
41
  export interface FileInputProps extends FileInputOwnProps, Omit<React.ComponentPropsWithoutRef<'input'>, keyof FileInputOwnProps | 'type'> {
@@ -25,7 +25,11 @@ type InputOwnProps = {
25
25
  onValueChange?: (value: string) => void;
26
26
  /** Additional CSS classes — applied to the wrapper, not the <input> */
27
27
  className?: string;
28
- /** @deprecated Pass the native `aria-label` attribute instead. */
28
+ /**
29
+ * Legacy accessible-name prop.
30
+ *
31
+ * @deprecated Pass the native `aria-label` attribute instead.
32
+ */
29
33
  ariaLabel?: string;
30
34
  };
31
35
  export interface InputProps extends InputOwnProps, Omit<React.ComponentPropsWithoutRef<'input'>, keyof InputOwnProps> {
@@ -13,6 +13,7 @@ export interface LinkListItem {
13
13
  icon?: string;
14
14
  }
15
15
  export interface LinkListProps {
16
+ /** Links to render, in display order — each opens in a new tab */
16
17
  items: LinkListItem[];
17
18
  /** Additional CSS classes */
18
19
  className?: string;
@@ -13,11 +13,21 @@ type RadioButtonOwnProps = {
13
13
  onValueChange?: (value: string) => void;
14
14
  /** Additional CSS classes */
15
15
  className?: string;
16
- /** @deprecated Use `onValueChange` instead. */
16
+ /**
17
+ * Legacy change handler, kept for backwards compatibility.
18
+ *
19
+ * @deprecated Use `onValueChange` instead.
20
+ */
17
21
  onChange?: (value: string) => void;
18
- /** @deprecated Pass the native `aria-label` attribute instead. */
22
+ /**
23
+ * Legacy accessible-name prop.
24
+ *
25
+ * @deprecated Pass the native `aria-label` attribute instead.
26
+ */
19
27
  ariaLabel?: string;
20
28
  /**
29
+ * Legacy form-field name.
30
+ *
21
31
  * @deprecated No-op. This component renders a `<div role="radio">`, not a
22
32
  * native `<input type="radio">`, so it does not group by name or participate
23
33
  * in native form submission — `RadioGroup` handles grouping in React state.
@@ -47,7 +57,11 @@ type RadioGroupOwnProps = {
47
57
  onValueChange?: (value: string) => void;
48
58
  /** Additional CSS classes */
49
59
  className?: string;
50
- /** @deprecated Use `onValueChange` instead. */
60
+ /**
61
+ * Legacy change handler, kept for backwards compatibility.
62
+ *
63
+ * @deprecated Use `onValueChange` instead.
64
+ */
51
65
  onChange?: (value: string) => void;
52
66
  };
53
67
  export interface RadioGroupProps extends RadioGroupOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof RadioGroupOwnProps> {
@@ -0,0 +1,152 @@
1
+ /* ============================================
2
+ REASONING COMPONENT
3
+ A model's thinking, disclosed behind a
4
+ one-line summary. Quiet by construction: the
5
+ trace is secondary text on a rail, never
6
+ competing with the answer beside it.
7
+ ============================================ */
8
+
9
+ .ds-reasoning {
10
+ display: flex;
11
+ flex-direction: column;
12
+ width: 100%;
13
+ }
14
+
15
+ /* ============================================
16
+ TRIGGER
17
+ ============================================ */
18
+
19
+ .ds-reasoning__trigger {
20
+ display: inline-flex;
21
+ align-items: center;
22
+ gap: var(--gap-xs);
23
+ align-self: flex-start;
24
+ padding: var(--padding-xxs) var(--padding-xs);
25
+ margin-left: calc(var(--padding-xs) * -1);
26
+ background: none;
27
+ border: none;
28
+ border-radius: var(--radius-sm);
29
+ color: var(--color-text-tertiary);
30
+ font-family: var(--font-paragraph-sm-family);
31
+ font-size: var(--font-paragraph-sm-size);
32
+ font-weight: var(--font-paragraph-sm-weight);
33
+ line-height: var(--font-paragraph-sm-line-height);
34
+ letter-spacing: var(--font-paragraph-sm-letter-spacing);
35
+ cursor: pointer;
36
+ transition: color var(--motion-duration-fast) var(--motion-ease-standard);
37
+ }
38
+
39
+ .ds-reasoning__trigger:hover {
40
+ color: var(--color-text-secondary);
41
+ }
42
+
43
+ .ds-reasoning__trigger:focus-visible {
44
+ outline: 2px solid var(--color-action-primary-bg);
45
+ outline-offset: -2px;
46
+ }
47
+
48
+ .ds-reasoning__chevron {
49
+ --icon-size: var(--icon-size-sm);
50
+
51
+ flex: none;
52
+ transition: transform var(--motion-duration-slow) var(--motion-ease-standard);
53
+ }
54
+
55
+ .ds-reasoning--open .ds-reasoning__chevron {
56
+ transform: rotate(180deg);
57
+ }
58
+
59
+ /* ============================================
60
+ SUMMARY
61
+ While the trace streams, a highlight sweeps
62
+ the summary left to right — the same treatment
63
+ AgentStatus uses, so "the model is working"
64
+ looks the same wherever it appears.
65
+ ============================================ */
66
+
67
+ .ds-reasoning__summary {
68
+ white-space: nowrap;
69
+ }
70
+
71
+ .ds-reasoning--streaming .ds-reasoning__summary {
72
+ background-image: linear-gradient(
73
+ 100deg,
74
+ var(--color-text-tertiary) 40%,
75
+ var(--color-text-primary) 50%,
76
+ var(--color-text-tertiary) 60%
77
+ );
78
+ background-size: 250% 100%;
79
+ background-clip: text;
80
+ -webkit-background-clip: text;
81
+ color: transparent;
82
+ animation: ds-reasoning-shimmer var(--motion-duration-loop-shimmer)
83
+ var(--motion-ease-linear) infinite;
84
+ }
85
+
86
+ @keyframes ds-reasoning-shimmer {
87
+ from {
88
+ background-position-x: 100%;
89
+ }
90
+
91
+ to {
92
+ background-position-x: 0%;
93
+ }
94
+ }
95
+
96
+ /* ============================================
97
+ PANEL
98
+ ============================================ */
99
+
100
+ .ds-reasoning__panel {
101
+ display: grid;
102
+ grid-template-rows: 0fr;
103
+ visibility: hidden;
104
+ transition:
105
+ grid-template-rows var(--motion-duration-slow) var(--motion-ease-standard),
106
+ visibility var(--motion-duration-slow) var(--motion-ease-standard);
107
+ }
108
+
109
+ .ds-reasoning--open .ds-reasoning__panel {
110
+ grid-template-rows: 1fr;
111
+ visibility: visible;
112
+ }
113
+
114
+ .ds-reasoning__content {
115
+ overflow: hidden;
116
+ min-height: 0;
117
+ transition: padding-block var(--motion-duration-slow) var(--motion-ease-standard);
118
+ padding-left: var(--padding-sm-md);
119
+ /* The rail sits flush with the summary's left edge — the trigger's own
120
+ padding is cancelled by its negative margin, so both start at zero */
121
+ border-left: var(--border-md) solid var(--color-divider);
122
+ color: var(--color-text-secondary);
123
+ font-family: var(--font-paragraph-sm-family);
124
+ font-size: var(--font-paragraph-sm-size);
125
+ font-weight: var(--font-paragraph-sm-weight);
126
+ line-height: var(--font-paragraph-sm-line-height);
127
+ letter-spacing: var(--font-paragraph-sm-letter-spacing);
128
+ }
129
+
130
+ .ds-reasoning--open .ds-reasoning__content {
131
+ padding-block: var(--padding-xs);
132
+ }
133
+
134
+ .ds-reasoning__content > :first-child {
135
+ margin-top: 0;
136
+ }
137
+
138
+ .ds-reasoning__content > :last-child {
139
+ margin-bottom: 0;
140
+ }
141
+
142
+ /* ============================================
143
+ REDUCED MOTION
144
+ ============================================ */
145
+
146
+ @media (prefers-reduced-motion: reduce) {
147
+ .ds-reasoning--streaming .ds-reasoning__summary {
148
+ background-image: none;
149
+ color: var(--color-text-tertiary);
150
+ animation: none;
151
+ }
152
+ }
@@ -0,0 +1,36 @@
1
+ import { default as React } from 'react';
2
+ /** Props owned by Reasoning itself — everything else falls through to the root element. */
3
+ type ReasoningOwnProps = {
4
+ /** The model is still producing the trace. Opens the panel and shimmers the summary. */
5
+ streaming?: boolean;
6
+ /** Seconds spent reasoning, shown in the summary once complete. */
7
+ duration?: number;
8
+ /** Override the summary line. By default it reports the streaming state and the duration. */
9
+ label?: string;
10
+ /** Open state for controlled use. Pair with `onOpenChange`. */
11
+ open?: boolean;
12
+ /** Open state for uncontrolled use. Defaults to open while `streaming`. */
13
+ defaultOpen?: boolean;
14
+ /** Fires whenever the panel opens or closes, from a click or from the stream ending. */
15
+ onOpenChange?: (open: boolean) => void;
16
+ /** Additional CSS classes */
17
+ className?: string;
18
+ /** The reasoning trace. */
19
+ children?: React.ReactNode;
20
+ };
21
+ export interface ReasoningProps extends ReasoningOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof ReasoningOwnProps> {
22
+ }
23
+ /**
24
+ * Reasoning discloses a model's thinking without letting it dominate the
25
+ * response: open while the trace streams in, collapsed to a one-line summary
26
+ * once it finishes.
27
+ *
28
+ * The auto-collapse yields to the reader — once someone has toggled the panel
29
+ * themselves, the stream ending no longer closes it.
30
+ *
31
+ * Only the summary line is a live region. A trace announced token by token
32
+ * floods a screen reader, so the body is ordinary expandable content and the
33
+ * announcement covers the boundaries: thinking, then thought for so long.
34
+ */
35
+ export declare const Reasoning: React.ForwardRefExoticComponent<ReasoningProps & React.RefAttributes<HTMLDivElement>>;
36
+ export {};
@@ -0,0 +1,69 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import React, { useId, useState, useRef, useEffect, useCallback } from "react";
3
+ import "./Reasoning.css";
4
+ import "../../fonts/material-symbols.css";
5
+ const Reasoning = React.forwardRef(
6
+ ({
7
+ streaming = false,
8
+ duration,
9
+ label,
10
+ open,
11
+ defaultOpen,
12
+ onOpenChange,
13
+ className = "",
14
+ children,
15
+ ...rest
16
+ }, ref) => {
17
+ const baseClass = "ds-reasoning";
18
+ const id = useId();
19
+ const panelId = `${id}-panel`;
20
+ const triggerId = `${id}-trigger`;
21
+ const isControlled = open !== void 0;
22
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen ?? streaming);
23
+ const isOpen = isControlled ? open : uncontrolledOpen;
24
+ const readerDecided = useRef(false);
25
+ const wasStreaming = useRef(streaming);
26
+ useEffect(() => {
27
+ if (streaming === wasStreaming.current) return;
28
+ wasStreaming.current = streaming;
29
+ if (readerDecided.current) return;
30
+ if (!isControlled) setUncontrolledOpen(streaming);
31
+ onOpenChange?.(streaming);
32
+ }, [streaming, isControlled, onOpenChange]);
33
+ const toggle = useCallback(() => {
34
+ readerDecided.current = true;
35
+ const next = !isOpen;
36
+ if (!isControlled) setUncontrolledOpen(next);
37
+ onOpenChange?.(next);
38
+ }, [isOpen, isControlled, onOpenChange]);
39
+ const summary = label ?? (streaming ? "Thinking" : duration !== void 0 ? `Thought for ${duration}s` : "Thought process");
40
+ const classes = [
41
+ baseClass,
42
+ isOpen ? `${baseClass}--open` : "",
43
+ streaming ? `${baseClass}--streaming` : "",
44
+ className
45
+ ].filter(Boolean).join(" ");
46
+ return /* @__PURE__ */ jsxs("div", { ...rest, ref, className: classes, children: [
47
+ /* @__PURE__ */ jsxs(
48
+ "button",
49
+ {
50
+ type: "button",
51
+ id: triggerId,
52
+ className: `${baseClass}__trigger`,
53
+ "aria-expanded": isOpen,
54
+ "aria-controls": panelId,
55
+ onClick: toggle,
56
+ children: [
57
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__summary`, role: "status", children: summary }),
58
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__chevron material-symbols-rounded`, "aria-hidden": "true", children: "expand_more" })
59
+ ]
60
+ }
61
+ ),
62
+ /* @__PURE__ */ jsx("div", { className: `${baseClass}__panel`, id: panelId, role: "region", "aria-labelledby": triggerId, children: /* @__PURE__ */ jsx("div", { className: `${baseClass}__content`, children }) })
63
+ ] });
64
+ }
65
+ );
66
+ Reasoning.displayName = "Reasoning";
67
+ export {
68
+ Reasoning
69
+ };
@@ -23,7 +23,11 @@ type SelectionCardOwnProps = {
23
23
  name?: string;
24
24
  /** Additional CSS classes */
25
25
  className?: string;
26
- /** @deprecated Use `onValueChange` instead. */
26
+ /**
27
+ * Legacy change handler, kept for backwards compatibility.
28
+ *
29
+ * @deprecated Use `onValueChange` instead.
30
+ */
27
31
  onChange?: (value: string | string[]) => void;
28
32
  };
29
33
  export interface SelectionCardProps extends SelectionCardOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof SelectionCardOwnProps> {
@@ -19,7 +19,11 @@ type SliderOwnProps = {
19
19
  onValueChange?: (value: number) => void;
20
20
  /** Additional CSS classes — applied to the wrapper, not the <input> */
21
21
  className?: string;
22
- /** @deprecated Pass the native `aria-label` attribute instead. */
22
+ /**
23
+ * Legacy accessible-name prop.
24
+ *
25
+ * @deprecated Pass the native `aria-label` attribute instead.
26
+ */
23
27
  ariaLabel?: string;
24
28
  };
25
29
  export interface SliderProps extends SliderOwnProps, Omit<React.ComponentPropsWithoutRef<'input'>, keyof SliderOwnProps | 'type'> {