@robr0/design-system 0.3.0 → 0.5.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 (94) hide show
  1. package/README.md +30 -27
  2. package/components/AgentStatus/AgentStatus.css +496 -0
  3. package/components/AgentStatus/AgentStatus.d.ts +41 -0
  4. package/components/AgentStatus/AgentStatus.js +85 -0
  5. package/components/AgentStatus/AgentStatusPatterns.d.ts +17 -0
  6. package/components/AgentStatus/AgentStatusPatterns.js +20 -0
  7. package/components/AiButton/AiButton.css +163 -0
  8. package/components/AiButton/AiButton.d.ts +36 -0
  9. package/components/AiButton/AiButton.js +58 -0
  10. package/components/AlertDialog/AlertDialog.css +5 -5
  11. package/components/Button/Button.d.ts +14 -2
  12. package/components/ButtonGroup/ButtonGroup.js +2 -9
  13. package/components/ChatHeader/ChatHeader.css +35 -0
  14. package/components/ChatHeader/ChatHeader.d.ts +30 -0
  15. package/components/ChatHeader/ChatHeader.js +17 -0
  16. package/components/ChatMarker/ChatMarker.css +52 -0
  17. package/components/ChatMarker/ChatMarker.d.ts +22 -0
  18. package/components/ChatMarker/ChatMarker.js +18 -0
  19. package/components/ChatMessage/ChatMessage.css +304 -0
  20. package/components/ChatMessage/ChatMessage.d.ts +68 -0
  21. package/components/ChatMessage/ChatMessage.js +69 -0
  22. package/components/ChatThread/ChatThread.css +171 -0
  23. package/components/ChatThread/ChatThread.d.ts +41 -0
  24. package/components/ChatThread/ChatThread.js +174 -0
  25. package/components/Checkbox/Checkbox.d.ts +17 -3
  26. package/components/Chip/Chip.css +27 -0
  27. package/components/Chip/Chip.d.ts +2 -2
  28. package/components/CircularButton/CircularButton.d.ts +31 -10
  29. package/components/CircularButton/CircularButton.js +54 -50
  30. package/components/CodeBlock/CodeBlock.css +2 -2
  31. package/components/Combobox/Combobox.d.ts +10 -2
  32. package/components/Composer/Composer.css +164 -0
  33. package/components/Composer/Composer.d.ts +67 -0
  34. package/components/Composer/Composer.js +120 -0
  35. package/components/ContextMenu/ContextMenu.css +0 -4
  36. package/components/DateInput/DateInput.d.ts +5 -1
  37. package/components/Dialog/Dialog.css +5 -5
  38. package/components/DocumentChip/DocumentChip.css +181 -0
  39. package/components/DocumentChip/DocumentChip.d.ts +41 -0
  40. package/components/DocumentChip/DocumentChip.js +78 -0
  41. package/components/Dropdown/Dropdown.css +2 -4
  42. package/components/Dropdown/Dropdown.d.ts +10 -2
  43. package/components/DropdownMenu/DropdownMenu.css +2 -4
  44. package/components/FileInput/FileInput.d.ts +5 -1
  45. package/components/Input/Input.d.ts +5 -1
  46. package/components/InterruptCard/InterruptCard.css +164 -0
  47. package/components/InterruptCard/InterruptCard.d.ts +55 -0
  48. package/components/InterruptCard/InterruptCard.js +57 -0
  49. package/components/LinkList/LinkList.d.ts +1 -0
  50. package/components/MessageActions/MessageActions.css +76 -0
  51. package/components/MessageActions/MessageActions.d.ts +38 -0
  52. package/components/MessageActions/MessageActions.js +33 -0
  53. package/components/MessageCard/MessageCard.css +112 -0
  54. package/components/MessageCard/MessageCard.d.ts +35 -0
  55. package/components/MessageCard/MessageCard.js +28 -0
  56. package/components/NavList/NavList.css +155 -0
  57. package/components/NavList/NavList.d.ts +56 -0
  58. package/components/NavList/NavList.js +99 -0
  59. package/components/PromptSuggestions/PromptSuggestions.css +87 -0
  60. package/components/PromptSuggestions/PromptSuggestions.d.ts +51 -0
  61. package/components/PromptSuggestions/PromptSuggestions.js +34 -0
  62. package/components/Prose/Prose.css +252 -0
  63. package/components/Prose/Prose.d.ts +21 -0
  64. package/components/Prose/Prose.js +14 -0
  65. package/components/RadioButton/RadioButton.d.ts +17 -3
  66. package/components/Reasoning/Reasoning.css +276 -0
  67. package/components/Reasoning/Reasoning.d.ts +55 -0
  68. package/components/Reasoning/Reasoning.js +98 -0
  69. package/components/SelectionCard/SelectionCard.d.ts +5 -1
  70. package/components/Slider/Slider.d.ts +5 -1
  71. package/components/SourceChip/SourceChip.css +102 -0
  72. package/components/SourceChip/SourceChip.d.ts +32 -0
  73. package/components/SourceChip/SourceChip.js +31 -0
  74. package/components/Stat/Stat.css +2 -2
  75. package/components/Textarea/Textarea.d.ts +5 -1
  76. package/components/Timeline/Timeline.d.ts +2 -0
  77. package/components/ToggleGroup/ToggleGroup.d.ts +10 -2
  78. package/components/ToggleSwitch/ToggleSwitch.d.ts +10 -2
  79. package/components/ToolCall/ToolCall.css +213 -0
  80. package/components/ToolCall/ToolCall.d.ts +43 -0
  81. package/components/ToolCall/ToolCall.js +89 -0
  82. package/components/registry.json +145 -8
  83. package/components/registry.json.d.ts +145 -8
  84. package/components/registry.json.js +2 -2
  85. package/index.d.ts +18 -0
  86. package/index.js +36 -0
  87. package/package.json +8 -4
  88. package/tokens/registry.json +13 -0
  89. package/tokens/registry.json.d.ts +13 -0
  90. package/tokens/registry.json.js +1 -1
  91. package/tokens/tokens-dark.css +13 -0
  92. package/tokens/tokens-light.css +42 -0
  93. package/tokens/tokens-motion.css +3 -1
  94. package/tokens/tokens-typography.css +24 -0
@@ -0,0 +1,252 @@
1
+ /* ============================================
2
+ PROSE COMPONENT
3
+ Token-styled typography for rendered markdown
4
+ ============================================ */
5
+
6
+ .ds-prose {
7
+ font-family: var(--font-paragraph-family);
8
+ font-size: var(--font-paragraph-size);
9
+ font-weight: var(--font-paragraph-weight);
10
+ line-height: var(--font-paragraph-line-height);
11
+ letter-spacing: var(--font-paragraph-letter-spacing);
12
+ color: var(--color-text-primary);
13
+ }
14
+
15
+ /* Block rhythm — every block owns its bottom margin; the edges are
16
+ trimmed so Prose slots into bubbles and cards cleanly */
17
+ .ds-prose p,
18
+ .ds-prose ul,
19
+ .ds-prose ol,
20
+ .ds-prose pre,
21
+ .ds-prose blockquote,
22
+ .ds-prose table,
23
+ .ds-prose hr,
24
+ .ds-prose img {
25
+ margin: 0;
26
+ margin-block-end: var(--gap-md);
27
+ }
28
+
29
+ .ds-prose > :first-child {
30
+ margin-block-start: 0;
31
+ }
32
+
33
+ .ds-prose > :last-child {
34
+ margin-block-end: 0;
35
+ }
36
+
37
+ /* ============================================
38
+ PARAGRAPHS
39
+ ============================================ */
40
+
41
+ .ds-prose p {
42
+ font-family: var(--font-paragraph-family);
43
+ font-size: var(--font-paragraph-size);
44
+ font-weight: var(--font-paragraph-weight);
45
+ line-height: var(--font-paragraph-line-height);
46
+ letter-spacing: var(--font-paragraph-letter-spacing);
47
+ color: var(--color-text-primary);
48
+ }
49
+
50
+ /* ============================================
51
+ HEADINGS
52
+ Hierarchy carried by the token scale; the
53
+ weight contrast is encoded in the tokens
54
+ ============================================ */
55
+
56
+ .ds-prose h1,
57
+ .ds-prose h2,
58
+ .ds-prose h3,
59
+ .ds-prose h4 {
60
+ margin: 0;
61
+ margin-block-start: var(--gap-lg);
62
+ margin-block-end: var(--gap-sm-md);
63
+ color: var(--color-text-primary);
64
+ }
65
+
66
+ .ds-prose h1 {
67
+ font-family: var(--font-heading-1-family);
68
+ font-size: var(--font-heading-1-size);
69
+ font-weight: var(--font-heading-1-weight);
70
+ line-height: var(--font-heading-1-line-height);
71
+ letter-spacing: var(--font-heading-1-letter-spacing);
72
+ }
73
+
74
+ .ds-prose h2 {
75
+ font-family: var(--font-heading-2-family);
76
+ font-size: var(--font-heading-2-size);
77
+ font-weight: var(--font-heading-2-weight);
78
+ line-height: var(--font-heading-2-line-height);
79
+ letter-spacing: var(--font-heading-2-letter-spacing);
80
+ }
81
+
82
+ .ds-prose h3 {
83
+ font-family: var(--font-heading-3-family);
84
+ font-size: var(--font-heading-3-size);
85
+ font-weight: var(--font-heading-3-weight);
86
+ line-height: var(--font-heading-3-line-height);
87
+ letter-spacing: var(--font-heading-3-letter-spacing);
88
+ }
89
+
90
+ .ds-prose h4 {
91
+ font-family: var(--font-title-body-family);
92
+ font-size: var(--font-title-body-size);
93
+ font-weight: var(--font-title-body-weight);
94
+ line-height: var(--font-title-body-line-height);
95
+ letter-spacing: var(--font-title-body-letter-spacing);
96
+ }
97
+
98
+ /* ============================================
99
+ LISTS
100
+ ============================================ */
101
+
102
+ .ds-prose ul,
103
+ .ds-prose ol {
104
+ padding-inline-start: var(--padding-md);
105
+ }
106
+
107
+ .ds-prose li {
108
+ font-family: var(--font-paragraph-family);
109
+ font-size: var(--font-paragraph-size);
110
+ font-weight: var(--font-paragraph-weight);
111
+ line-height: var(--font-paragraph-line-height);
112
+ letter-spacing: var(--font-paragraph-letter-spacing);
113
+ color: var(--color-text-primary);
114
+ }
115
+
116
+ .ds-prose li + li {
117
+ margin-block-start: var(--gap-xs);
118
+ }
119
+
120
+ /* Nested lists sit tight under their parent item */
121
+ .ds-prose li > ul,
122
+ .ds-prose li > ol {
123
+ margin-block-start: var(--gap-xs);
124
+ margin-block-end: 0;
125
+ }
126
+
127
+ /* ============================================
128
+ INLINE ELEMENTS
129
+ ============================================ */
130
+
131
+ .ds-prose a {
132
+ color: var(--color-action-primary-text-tertiary);
133
+ text-decoration: underline;
134
+ }
135
+
136
+ .ds-prose strong {
137
+ font-weight: var(--font-paragraph-em-weight);
138
+ }
139
+
140
+ .ds-prose em {
141
+ font-style: italic;
142
+ }
143
+
144
+ .ds-prose code {
145
+ font-family: var(--font-family-code);
146
+ font-size: var(--font-paragraph-sm-size);
147
+ background-color: var(--color-bg-container-secondary);
148
+ border-radius: var(--radius-xxs);
149
+ padding-inline: var(--padding-xxxs);
150
+ }
151
+
152
+ /* ============================================
153
+ CODE BLOCKS
154
+ The plain fallback — CodeBlock is the richer
155
+ choice for standalone code
156
+ ============================================ */
157
+
158
+ .ds-prose pre {
159
+ font-family: var(--font-family-code);
160
+ font-size: var(--font-paragraph-sm-size);
161
+ line-height: var(--font-paragraph-sm-line-height);
162
+ background-color: var(--color-bg-container-primary);
163
+ border: var(--border-xs) solid var(--color-bg-container-border);
164
+ border-radius: var(--radius-md);
165
+ padding: var(--padding-md);
166
+ overflow-x: auto;
167
+ }
168
+
169
+ .ds-prose pre code {
170
+ background-color: transparent;
171
+ border-radius: 0;
172
+ padding-inline: 0;
173
+ font-size: inherit;
174
+ }
175
+
176
+ /* ============================================
177
+ BLOCKQUOTES
178
+ Mirrors Reasoning's trace rail
179
+ ============================================ */
180
+
181
+ .ds-prose blockquote {
182
+ border-inline-start: var(--border-md) solid var(--color-divider);
183
+ padding-inline-start: var(--padding-md);
184
+ color: var(--color-text-secondary);
185
+ }
186
+
187
+ .ds-prose blockquote p {
188
+ color: var(--color-text-secondary);
189
+ }
190
+
191
+ /* ============================================
192
+ TABLES
193
+ ============================================ */
194
+
195
+ .ds-prose table {
196
+ width: 100%;
197
+ border-collapse: collapse;
198
+ }
199
+
200
+ .ds-prose th {
201
+ font-family: var(--font-title-body-family);
202
+ font-size: var(--font-paragraph-sm-size);
203
+ font-weight: var(--font-title-body-weight);
204
+ line-height: var(--font-paragraph-sm-line-height);
205
+ letter-spacing: var(--font-title-body-letter-spacing);
206
+ background-color: var(--color-bg-container-secondary);
207
+ text-align: start;
208
+ }
209
+
210
+ .ds-prose th,
211
+ .ds-prose td {
212
+ padding: var(--padding-xs) var(--padding-sm-md);
213
+ border-block-end: var(--border-xs) solid var(--color-divider);
214
+ }
215
+
216
+ /* ============================================
217
+ RULES AND MEDIA
218
+ ============================================ */
219
+
220
+ .ds-prose hr {
221
+ border: none;
222
+ border-block-start: var(--border-xs) solid var(--color-divider);
223
+ }
224
+
225
+ .ds-prose img {
226
+ max-width: 100%;
227
+ border-radius: var(--radius-md);
228
+ }
229
+
230
+ /* ============================================
231
+ SMALL SIZE
232
+ Dense chat contexts — body scale drops to the
233
+ small paragraph tokens; headings keep their tiers
234
+ ============================================ */
235
+
236
+ .ds-prose--sm,
237
+ .ds-prose--sm p,
238
+ .ds-prose--sm li {
239
+ font-family: var(--font-paragraph-sm-family);
240
+ font-size: var(--font-paragraph-sm-size);
241
+ font-weight: var(--font-paragraph-sm-weight);
242
+ line-height: var(--font-paragraph-sm-line-height);
243
+ letter-spacing: var(--font-paragraph-sm-letter-spacing);
244
+ }
245
+
246
+ .ds-prose--sm strong {
247
+ font-weight: var(--font-paragraph-sm-em-weight);
248
+ }
249
+
250
+ .ds-prose--sm code {
251
+ font-size: var(--font-paragraph-sm-size);
252
+ }
@@ -0,0 +1,21 @@
1
+ import { default as React } from 'react';
2
+ /** Props owned by Prose itself — everything else falls through to the root element. */
3
+ type ProseOwnProps = {
4
+ /** Body scale. `sm` maps paragraphs, lists and code to the small paragraph tokens for dense chat contexts. */
5
+ size?: 'default' | 'sm';
6
+ /** Additional CSS classes */
7
+ className?: string;
8
+ /** The rendered markup to style — the output of whatever markdown renderer the consumer uses. */
9
+ children?: React.ReactNode;
10
+ };
11
+ export interface ProseProps extends ProseOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof ProseOwnProps> {
12
+ }
13
+ /**
14
+ * Prose is the typography kit for rendered markdown and rich agent output.
15
+ * The package ships no markdown renderer: consumers render markdown with
16
+ * whatever library they already use and wrap the result in Prose, which
17
+ * styles the descendant elements — headings, paragraphs, lists, links,
18
+ * code, quotes, tables — with the token scale.
19
+ */
20
+ export declare const Prose: React.ForwardRefExoticComponent<ProseProps & React.RefAttributes<HTMLDivElement>>;
21
+ export {};
@@ -0,0 +1,14 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import "./Prose.css";
4
+ const Prose = React.forwardRef(
5
+ ({ size = "default", className = "", children, ...rest }, ref) => {
6
+ const baseClass = "ds-prose";
7
+ const classes = [baseClass, size === "sm" ? `${baseClass}--sm` : "", className].filter(Boolean).join(" ");
8
+ return /* @__PURE__ */ jsx("div", { ...rest, ref, className: classes, children });
9
+ }
10
+ );
11
+ Prose.displayName = "Prose";
12
+ export {
13
+ Prose
14
+ };
@@ -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,276 @@
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
+ /* Where an AgentStatus summary's label starts: matrix plus its gap.
11
+ The rail geometry and the handoff slide both derive from it. */
12
+ --ds-reasoning-align: calc(var(--icon-size-md) + var(--gap-sm-md));
13
+
14
+ display: flex;
15
+ flex-direction: column;
16
+ width: 100%;
17
+ }
18
+
19
+ /* ============================================
20
+ TRIGGER
21
+ ============================================ */
22
+
23
+ .ds-reasoning__trigger {
24
+ display: inline-flex;
25
+ align-items: center;
26
+ gap: var(--gap-sm);
27
+ align-self: flex-start;
28
+ padding: var(--padding-xxs) var(--padding-xs);
29
+ margin-left: calc(var(--padding-xs) * -1);
30
+ background: none;
31
+ border: none;
32
+ border-radius: var(--radius-sm);
33
+ color: var(--color-text-secondary);
34
+ font-family: var(--font-paragraph-family);
35
+ font-size: var(--font-paragraph-size);
36
+ font-weight: var(--font-paragraph-weight);
37
+ line-height: var(--font-paragraph-line-height);
38
+ letter-spacing: var(--font-paragraph-letter-spacing);
39
+ cursor: pointer;
40
+ transition: color var(--motion-duration-fast) var(--motion-ease-standard);
41
+ }
42
+
43
+ .ds-reasoning__trigger:hover {
44
+ color: var(--color-text-primary);
45
+ }
46
+
47
+ /* Summary-only: the same line, minus every affordance that would promise a
48
+ panel behind it. Not a button, so there is nothing to focus or press. */
49
+ .ds-reasoning__trigger--static {
50
+ cursor: default;
51
+ }
52
+
53
+ .ds-reasoning__trigger--static:hover {
54
+ color: var(--color-text-secondary);
55
+ }
56
+
57
+ .ds-reasoning__trigger:focus-visible {
58
+ outline: 2px solid var(--color-action-primary-bg);
59
+ outline-offset: -2px;
60
+ }
61
+
62
+ /* Closed the chevron points at the collapsed trace; open it points down the
63
+ way the panel expands. The glyph itself points down, so closed is the
64
+ rotated state — and the quarter turn to open runs clockwise, following
65
+ the panel as it opens. */
66
+ .ds-reasoning__chevron {
67
+ --icon-size: var(--icon-size-sm);
68
+
69
+ flex: none;
70
+ transform: rotate(-90deg);
71
+ transition: transform var(--motion-duration-slow) var(--motion-ease-standard);
72
+ }
73
+
74
+ .ds-reasoning--open .ds-reasoning__chevron {
75
+ transform: rotate(0deg);
76
+ }
77
+
78
+ /* ============================================
79
+ SUMMARY
80
+ While the trace streams, a sweep walks the
81
+ summary left to right — the same gradient
82
+ AgentStatus uses (primary base, tertiary
83
+ band, same stops), so "the model is working"
84
+ looks the same wherever it appears.
85
+ ============================================ */
86
+
87
+ .ds-reasoning__summary {
88
+ position: relative;
89
+ white-space: nowrap;
90
+ }
91
+
92
+ /* The live→done handoff. The departing node summary (an AgentStatus)
93
+ overlays the incoming text, fading out in place, while the text summary
94
+ slides left from where its label sat into the flush position. The
95
+ modifier comes off once the animation ends, so nothing stays composited. */
96
+ .ds-reasoning__summary--entering {
97
+ animation: ds-reasoning-summary-in var(--motion-duration-slow) var(--motion-ease-entrance) both;
98
+ }
99
+
100
+ .ds-reasoning__summary-leaving {
101
+ position: absolute;
102
+ left: 0;
103
+ top: 50%;
104
+ transform: translateY(-50%);
105
+ white-space: nowrap;
106
+ animation: ds-reasoning-summary-out var(--motion-duration-slow) var(--motion-ease-standard) both;
107
+ }
108
+
109
+ @keyframes ds-reasoning-summary-in {
110
+ from {
111
+ opacity: 0;
112
+ transform: translateX(var(--ds-reasoning-align));
113
+ }
114
+ }
115
+
116
+ @keyframes ds-reasoning-summary-out {
117
+ to {
118
+ opacity: 0;
119
+ }
120
+ }
121
+
122
+ /* A node summary (an AgentStatus) owns its own appearance — the text
123
+ shimmer below never applies to it. Inline-flex keeps the span exactly
124
+ the node's height: left inline, the node sits on the text baseline and
125
+ the leftover descender space pushes it off the chevron's centreline. */
126
+ .ds-reasoning__summary--node {
127
+ display: inline-flex;
128
+ align-items: center;
129
+ }
130
+
131
+ .ds-reasoning--streaming .ds-reasoning__summary:not(.ds-reasoning__summary--node) {
132
+ background-image: linear-gradient(
133
+ 100deg,
134
+ var(--color-text-primary) 35%,
135
+ var(--color-text-tertiary) 50%,
136
+ var(--color-text-primary) 65%
137
+ );
138
+ background-size: 250% 100%;
139
+ background-clip: text;
140
+ -webkit-background-clip: text;
141
+ color: transparent;
142
+ animation: ds-reasoning-shimmer var(--motion-duration-loop-shimmer)
143
+ var(--motion-ease-linear) infinite;
144
+ }
145
+
146
+ @keyframes ds-reasoning-shimmer {
147
+ from {
148
+ background-position-x: 100%;
149
+ }
150
+
151
+ to {
152
+ background-position-x: 0%;
153
+ }
154
+ }
155
+
156
+ /* ============================================
157
+ PANEL
158
+ ============================================ */
159
+
160
+ .ds-reasoning__panel {
161
+ display: grid;
162
+ grid-template-rows: 0fr;
163
+ visibility: hidden;
164
+ transition:
165
+ grid-template-rows var(--motion-duration-slow) var(--motion-ease-standard),
166
+ visibility var(--motion-duration-slow) var(--motion-ease-standard);
167
+ }
168
+
169
+ .ds-reasoning--open .ds-reasoning__panel {
170
+ grid-template-rows: 1fr;
171
+ visibility: visible;
172
+ }
173
+
174
+ .ds-reasoning__content {
175
+ overflow: hidden;
176
+ min-height: 0;
177
+ transition: padding-block var(--motion-duration-slow) var(--motion-ease-standard);
178
+ /* The rail and trace align to an AgentStatus summary's geometry: the
179
+ rail runs down the centre of the matrix (half an icon step, corrected
180
+ by half the rail's own width) and the trace text starts exactly where
181
+ the status label's first letter starts (matrix + its gap). A plain
182
+ text summary shares the same geometry, so swapping a live status for
183
+ the thought-for line never shifts the trace. */
184
+ margin-left: calc(var(--icon-size-md) / 2 - var(--border-md) / 2);
185
+ padding-left: calc(var(--icon-size-md) / 2 + var(--gap-sm-md) - var(--border-md) / 2);
186
+ border-left: var(--border-md) solid var(--color-divider);
187
+ color: var(--color-text-secondary);
188
+ font-family: var(--font-paragraph-family);
189
+ font-size: var(--font-paragraph-size);
190
+ font-weight: var(--font-paragraph-weight);
191
+ line-height: var(--font-paragraph-line-height);
192
+ letter-spacing: var(--font-paragraph-letter-spacing);
193
+ }
194
+
195
+ /* With the trigger's own bottom padding, the panel opens one --gap-lg
196
+ below the summary row — the same step a --gap-lg trace list uses
197
+ between nodes, so the first node isn't tighter than the rest. */
198
+ .ds-reasoning--open .ds-reasoning__content {
199
+ padding-block: var(--padding-md);
200
+ }
201
+
202
+ .ds-reasoning__content > :first-child {
203
+ margin-top: 0;
204
+ }
205
+
206
+ .ds-reasoning__content > :last-child {
207
+ margin-bottom: 0;
208
+ }
209
+
210
+ /* ============================================
211
+ TRACE NODES
212
+ Inside Reasoning, a list is the trace's node
213
+ list: one thinking step per item, no bullets
214
+ (the rail is the marker), on the same
215
+ --gap-lg beat the panel opens with. New
216
+ nodes rise in as the trace builds.
217
+ ============================================ */
218
+
219
+ .ds-reasoning__content ul,
220
+ .ds-reasoning__content ol {
221
+ list-style: none;
222
+ margin: 0;
223
+ padding: 0;
224
+ display: flex;
225
+ flex-direction: column;
226
+ gap: var(--gap-lg);
227
+ }
228
+
229
+ .ds-reasoning__content li {
230
+ animation: ds-reasoning-node-in var(--motion-duration-slow) var(--motion-ease-entrance);
231
+ }
232
+
233
+ @keyframes ds-reasoning-node-in {
234
+ from {
235
+ opacity: 0;
236
+ transform: translateY(6px);
237
+ }
238
+ }
239
+
240
+ /* ============================================
241
+ SIZES
242
+ The scale pairs with ChatMessage: default
243
+ matches default message text, compact
244
+ matches compact message text.
245
+ ============================================ */
246
+
247
+ .ds-reasoning--compact .ds-reasoning__trigger,
248
+ .ds-reasoning--compact .ds-reasoning__content {
249
+ font-family: var(--font-paragraph-sm-family);
250
+ font-size: var(--font-paragraph-sm-size);
251
+ font-weight: var(--font-paragraph-sm-weight);
252
+ line-height: var(--font-paragraph-sm-line-height);
253
+ letter-spacing: var(--font-paragraph-sm-letter-spacing);
254
+ }
255
+
256
+ /* Compact pairs with a compact AgentStatus: sm matrix, sm gap. */
257
+ .ds-reasoning--compact {
258
+ --ds-reasoning-align: calc(var(--icon-size-sm) + var(--gap-sm));
259
+ }
260
+
261
+ .ds-reasoning--compact .ds-reasoning__content {
262
+ margin-left: calc(var(--icon-size-sm) / 2 - var(--border-md) / 2);
263
+ padding-left: calc(var(--icon-size-sm) / 2 + var(--gap-sm) - var(--border-md) / 2);
264
+ }
265
+
266
+ /* ============================================
267
+ REDUCED MOTION
268
+ ============================================ */
269
+
270
+ @media (prefers-reduced-motion: reduce) {
271
+ .ds-reasoning--streaming .ds-reasoning__summary:not(.ds-reasoning__summary--node) {
272
+ background-image: none;
273
+ color: var(--color-text-tertiary);
274
+ animation: none;
275
+ }
276
+ }
@@ -0,0 +1,55 @@
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
+ /**
11
+ * Replace the summary text with custom content — typically an AgentStatus,
12
+ * pairing the live indicator with the trace disclosure. The node owns its
13
+ * own appearance and announcement, so Reasoning's shimmer and live region
14
+ * stand down.
15
+ */
16
+ summary?: React.ReactNode;
17
+ /**
18
+ * Render the summary line alone, with no chevron, no trigger, and no
19
+ * panel — for a model that reports what it is doing but produces no trace
20
+ * to read. A disclosure that opens onto nothing is a promise the component
21
+ * cannot keep, so it stops being one.
22
+ */
23
+ summaryOnly?: boolean;
24
+ /**
25
+ * Text scale, paired with ChatMessage's sizes: `default` matches default
26
+ * message text, `compact` matches compact message text.
27
+ */
28
+ size?: 'default' | 'compact';
29
+ /** Open state for controlled use. Pair with `onOpenChange`. */
30
+ open?: boolean;
31
+ /** Open state for uncontrolled use. Defaults to open while `streaming`. */
32
+ defaultOpen?: boolean;
33
+ /** Fires whenever the panel opens or closes, from a click or from the stream ending. */
34
+ onOpenChange?: (open: boolean) => void;
35
+ /** Additional CSS classes */
36
+ className?: string;
37
+ /** The reasoning trace. */
38
+ children?: React.ReactNode;
39
+ };
40
+ export interface ReasoningProps extends ReasoningOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof ReasoningOwnProps> {
41
+ }
42
+ /**
43
+ * Reasoning discloses a model's thinking without letting it dominate the
44
+ * response: open while the trace streams in, collapsed to a one-line summary
45
+ * once it finishes.
46
+ *
47
+ * The auto-collapse yields to the reader — once someone has toggled the panel
48
+ * themselves, the stream ending no longer closes it.
49
+ *
50
+ * Only the summary line is a live region. A trace announced token by token
51
+ * floods a screen reader, so the body is ordinary expandable content and the
52
+ * announcement covers the boundaries: thinking, then thought for so long.
53
+ */
54
+ export declare const Reasoning: React.ForwardRefExoticComponent<ReasoningProps & React.RefAttributes<HTMLDivElement>>;
55
+ export {};