@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.
- package/README.md +30 -27
- package/components/AgentStatus/AgentStatus.css +436 -0
- package/components/AgentStatus/AgentStatus.d.ts +37 -0
- package/components/AgentStatus/AgentStatus.js +53 -0
- package/components/AgentStatus/AgentStatusPatterns.d.ts +17 -0
- package/components/AgentStatus/AgentStatusPatterns.js +20 -0
- package/components/AlertDialog/AlertDialog.css +5 -5
- package/components/Button/Button.d.ts +14 -2
- package/components/ButtonGroup/ButtonGroup.js +2 -9
- package/components/Checkbox/Checkbox.d.ts +17 -3
- package/components/CircularButton/CircularButton.d.ts +9 -3
- package/components/CircularButton/CircularButton.js +4 -2
- package/components/Combobox/Combobox.d.ts +10 -2
- package/components/ContextMenu/ContextMenu.css +0 -4
- package/components/DateInput/DateInput.d.ts +5 -1
- package/components/Dialog/Dialog.css +5 -5
- package/components/Dropdown/Dropdown.css +2 -4
- package/components/Dropdown/Dropdown.d.ts +10 -2
- package/components/DropdownMenu/DropdownMenu.css +2 -4
- package/components/FileInput/FileInput.d.ts +5 -1
- package/components/Input/Input.d.ts +5 -1
- package/components/LinkList/LinkList.d.ts +1 -0
- package/components/RadioButton/RadioButton.d.ts +17 -3
- package/components/Reasoning/Reasoning.css +152 -0
- package/components/Reasoning/Reasoning.d.ts +36 -0
- package/components/Reasoning/Reasoning.js +69 -0
- package/components/SelectionCard/SelectionCard.d.ts +5 -1
- package/components/Slider/Slider.d.ts +5 -1
- package/components/Textarea/Textarea.d.ts +5 -1
- package/components/Timeline/Timeline.d.ts +2 -0
- package/components/ToggleGroup/ToggleGroup.d.ts +10 -2
- package/components/ToggleSwitch/ToggleSwitch.d.ts +10 -2
- package/components/ToolCall/ToolCall.css +213 -0
- package/components/ToolCall/ToolCall.d.ts +43 -0
- package/components/ToolCall/ToolCall.js +89 -0
- package/components/registry.json +32 -7
- package/components/registry.json.d.ts +32 -7
- package/components/registry.json.js +2 -2
- package/index.d.ts +4 -0
- package/index.js +8 -0
- package/package.json +8 -4
- package/tokens/registry.json +1 -0
- package/tokens/registry.json.d.ts +1 -0
- package/tokens/registry.json.js +1 -1
- 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-
|
|
85
|
-
font-size: var(--font-heading-
|
|
86
|
-
font-weight: var(--font-heading-
|
|
87
|
-
line-height: var(--font-heading-
|
|
88
|
-
letter-spacing: var(--font-heading-
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
|
|
21
|
-
|
|
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
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Legacy change handler, kept for backwards compatibility.
|
|
20
|
+
*
|
|
21
|
+
* @deprecated Use `onCheckedChange` instead.
|
|
22
|
+
*/
|
|
19
23
|
onChange?: (checked: boolean) => void;
|
|
20
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Legacy change handler, kept for backwards compatibility.
|
|
64
|
+
*
|
|
65
|
+
* @deprecated Use `onValueChange` instead.
|
|
66
|
+
*/
|
|
63
67
|
onChange?: (value: string | string[]) => void;
|
|
64
|
-
/**
|
|
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
|
-
/**
|
|
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-
|
|
92
|
-
font-size: var(--font-heading-
|
|
93
|
-
font-weight: var(--font-heading-
|
|
94
|
-
line-height: var(--font-heading-
|
|
95
|
-
letter-spacing: var(--font-heading-
|
|
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
|
-
|
|
258
|
-
|
|
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
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Legacy change handler, kept for backwards compatibility.
|
|
44
|
+
*
|
|
45
|
+
* @deprecated Use `onValueChange` instead.
|
|
46
|
+
*/
|
|
43
47
|
onChange?: (value: string) => void;
|
|
44
|
-
/**
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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,11 +13,21 @@ type RadioButtonOwnProps = {
|
|
|
13
13
|
onValueChange?: (value: string) => void;
|
|
14
14
|
/** Additional CSS classes */
|
|
15
15
|
className?: string;
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Legacy change handler, kept for backwards compatibility.
|
|
18
|
+
*
|
|
19
|
+
* @deprecated Use `onValueChange` instead.
|
|
20
|
+
*/
|
|
17
21
|
onChange?: (value: string) => void;
|
|
18
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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'> {
|