@robr0/design-system 0.9.0 → 0.11.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 (99) hide show
  1. package/README.md +16 -10
  2. package/components/AgentPlan/AgentPlan.css +14 -3
  3. package/components/AiButton/AiButton.css +1 -1
  4. package/components/Alert/Alert.css +9 -0
  5. package/components/AlertDialog/AlertDialog.css +3 -1
  6. package/components/AlertDialog/AlertDialog.js +2 -3
  7. package/components/AppSidebar/AppSidebar.css +22 -3
  8. package/components/AppSidebar/AppSidebar.d.ts +6 -2
  9. package/components/AppSidebar/AppSidebar.js +67 -36
  10. package/components/Card/Card.css +7 -2
  11. package/components/CardStack/CardStack.css +106 -0
  12. package/components/CardStack/CardStack.d.ts +44 -0
  13. package/components/CardStack/CardStack.js +140 -0
  14. package/components/Carousel/Carousel.css +9 -0
  15. package/components/Carousel/Carousel.js +37 -4
  16. package/components/Chart/AreaChart.js +6 -5
  17. package/components/Chart/BarChart.js +1 -1
  18. package/components/Chart/LineChart.js +4 -3
  19. package/components/Chart/PieChart.js +2 -15
  20. package/components/Chart/RadarChart.js +5 -4
  21. package/components/Chart/RadialChart.js +2 -15
  22. package/components/Chart/ScatterChart.js +3 -13
  23. package/components/Chart/StackedBarChart.js +2 -15
  24. package/components/Chart/Treemap.js +3 -17
  25. package/components/Chart/palette.d.ts +1 -0
  26. package/components/Chart/palette.js +19 -0
  27. package/components/ChatMarker/ChatMarker.css +9 -0
  28. package/components/ChatMessage/ChatMessage.css +16 -0
  29. package/components/ChatThread/ChatThread.js +2 -2
  30. package/components/Chip/Chip.css +9 -0
  31. package/components/CodeBlock/CodeBlock.css +10 -1
  32. package/components/CodeBlock/CodeBlock.js +2 -1
  33. package/components/ColorPicker/ColorPicker.js +10 -0
  34. package/components/Combobox/Combobox.css +9 -0
  35. package/components/CommandPalette/CommandPalette.css +9 -0
  36. package/components/CommandPalette/CommandPalette.js +31 -5
  37. package/components/Composer/Composer.css +118 -0
  38. package/components/Composer/Composer.d.ts +7 -0
  39. package/components/Composer/Composer.js +7 -1
  40. package/components/ContactCard/ContactCard.css +9 -0
  41. package/components/ContextMenu/ContextMenu.js +39 -3
  42. package/components/DatePicker/DatePicker.js +16 -0
  43. package/components/Dialog/Dialog.css +3 -1
  44. package/components/Dialog/Dialog.js +5 -4
  45. package/components/DocumentChip/DocumentChip.css +9 -0
  46. package/components/Dropdown/Dropdown.js +22 -3
  47. package/components/DropdownMenu/DropdownMenu.js +43 -6
  48. package/components/EmptyState/EmptyState.css +9 -0
  49. package/components/FileInput/FileInput.css +9 -0
  50. package/components/Globe/Globe.css +155 -0
  51. package/components/Globe/Globe.d.ts +96 -0
  52. package/components/Globe/Globe.js +415 -0
  53. package/components/InterruptCard/InterruptCard.css +27 -17
  54. package/components/InterruptCard/InterruptCard.d.ts +1 -1
  55. package/components/InterruptCard/InterruptCard.js +1 -1
  56. package/components/MapCallout/MapCallout.css +46 -0
  57. package/components/MapCallout/MapCallout.d.ts +29 -0
  58. package/components/MapCallout/MapCallout.js +17 -0
  59. package/components/MapLegend/MapLegend.css +88 -0
  60. package/components/MapLegend/MapLegend.d.ts +39 -0
  61. package/components/MapLegend/MapLegend.js +68 -0
  62. package/components/MessageActions/MessageActions.css +9 -0
  63. package/components/MessageCard/MessageCard.css +68 -16
  64. package/components/MessageCard/MessageCard.d.ts +1 -1
  65. package/components/MessageCard/MessageCard.js +6 -4
  66. package/components/ModelPicker/ModelPicker.css +4 -1
  67. package/components/ModelPicker/ModelPicker.js +43 -1
  68. package/components/NotificationCenter/NotificationCenter.css +9 -0
  69. package/components/NotificationCenter/NotificationCenter.js +26 -10
  70. package/components/NumberInput/NumberInput.css +9 -0
  71. package/components/Popover/Popover.css +3 -1
  72. package/components/Popover/Popover.js +2 -1
  73. package/components/SectionTitle/SectionTitle.css +8 -0
  74. package/components/SectionTitle/SectionTitle.d.ts +3 -1
  75. package/components/SectionTitle/SectionTitle.js +6 -1
  76. package/components/SourceChip/SourceChip.css +9 -0
  77. package/components/Stat/Stat.css +9 -0
  78. package/components/Stepper/Stepper.css +9 -0
  79. package/components/TagInput/TagInput.css +9 -0
  80. package/components/TimePicker/TimePicker.js +4 -1
  81. package/components/Toast/Toast.css +32 -11
  82. package/components/Toast/Toast.js +5 -4
  83. package/components/ToggleGroup/ToggleGroup.css +9 -0
  84. package/components/ToolCall/ToolCall.css +18 -6
  85. package/components/Tooltip/Tooltip.js +20 -16
  86. package/components/registry.json +37 -0
  87. package/components/registry.json.d.ts +37 -0
  88. package/components/registry.json.js +2 -2
  89. package/index.d.ts +4 -0
  90. package/index.js +8 -0
  91. package/package.json +5 -1
  92. package/tokens/motion.d.ts +23 -0
  93. package/tokens/motion.js +14 -0
  94. package/tokens/registry.json +17 -0
  95. package/tokens/registry.json.d.ts +17 -0
  96. package/tokens/registry.json.js +1 -1
  97. package/tokens/tokens-dark.css +28 -13
  98. package/tokens/tokens-light.css +26 -12
  99. package/tokens/tokens-typography.css +20 -0
@@ -0,0 +1,140 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import React, { useState, useRef, useCallback } from "react";
4
+ import "./CardStack.css";
5
+ const INTERACTIVE_SELECTOR = 'a, button, input, select, textarea, summary, [role="button"], [role="link"], [tabindex]';
6
+ const NEXT_KEYS = /* @__PURE__ */ new Set(["ArrowRight", "ArrowDown", " ", "Enter"]);
7
+ const PREV_KEYS = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowUp"]);
8
+ const CardStack = React.forwardRef(
9
+ ({
10
+ children,
11
+ index: indexProp,
12
+ defaultIndex = 0,
13
+ onIndexChange,
14
+ peek = 2,
15
+ loop = true,
16
+ advanceOnClick = true,
17
+ label,
18
+ className = "",
19
+ onClick,
20
+ onKeyDown,
21
+ style,
22
+ ...rest
23
+ }, ref) => {
24
+ const baseClass = "ds-card-stack";
25
+ const items = React.Children.toArray(children);
26
+ const count = items.length;
27
+ const isControlled = indexProp !== void 0;
28
+ const [innerIndex, setInnerIndex] = useState(defaultIndex);
29
+ const index = Math.max(0, Math.min(isControlled ? indexProp : innerIndex, count - 1));
30
+ const [leaving, setLeaving] = useState(false);
31
+ const [entering, setEntering] = useState(false);
32
+ const pendingRef = useRef(null);
33
+ const commit = useCallback(
34
+ (next2) => {
35
+ const normalized = (next2 % count + count) % count;
36
+ if (!isControlled) setInnerIndex(normalized);
37
+ onIndexChange?.(normalized);
38
+ },
39
+ [count, isControlled, onIndexChange]
40
+ );
41
+ const next = useCallback(() => {
42
+ if (count < 2 || leaving || entering) return;
43
+ if (!loop && index >= count - 1) return;
44
+ pendingRef.current = index + 1;
45
+ setLeaving(true);
46
+ }, [count, leaving, entering, loop, index]);
47
+ const prev = useCallback(() => {
48
+ if (count < 2 || leaving || entering) return;
49
+ if (!loop && index <= 0) return;
50
+ commit(index - 1);
51
+ setEntering(true);
52
+ }, [count, leaving, entering, loop, index, commit]);
53
+ const handleTopAnimationEnd = (e) => {
54
+ if (e.target !== e.currentTarget) return;
55
+ if (leaving) {
56
+ setLeaving(false);
57
+ if (pendingRef.current !== null) commit(pendingRef.current);
58
+ pendingRef.current = null;
59
+ }
60
+ if (entering) setEntering(false);
61
+ };
62
+ const handleClick = (e) => {
63
+ onClick?.(e);
64
+ if (!advanceOnClick || e.defaultPrevented) return;
65
+ const target = e.target;
66
+ const control = target.closest(INTERACTIVE_SELECTOR);
67
+ if (control && control !== e.currentTarget) return;
68
+ next();
69
+ };
70
+ const handleKeyDown = (e) => {
71
+ onKeyDown?.(e);
72
+ if (e.defaultPrevented || e.target !== e.currentTarget) return;
73
+ if (NEXT_KEYS.has(e.key)) {
74
+ e.preventDefault();
75
+ next();
76
+ } else if (PREV_KEYS.has(e.key)) {
77
+ e.preventDefault();
78
+ prev();
79
+ }
80
+ };
81
+ const visiblePeek = Math.max(0, Math.min(peek, count - 1));
82
+ const classes = [baseClass, className].filter(Boolean).join(" ");
83
+ return /* @__PURE__ */ jsxs(
84
+ "div",
85
+ {
86
+ ...rest,
87
+ ref,
88
+ className: classes,
89
+ role: "group",
90
+ "aria-roledescription": "card stack",
91
+ "aria-label": label,
92
+ tabIndex: count > 1 ? 0 : void 0,
93
+ style: { ...style, "--ds-card-stack-depth": visiblePeek },
94
+ onClick: handleClick,
95
+ onKeyDown: handleKeyDown,
96
+ children: [
97
+ items.map((child, k) => {
98
+ const raw = k - index;
99
+ const pos = loop ? (raw % count + count) % count : raw;
100
+ const gone = pos < 0;
101
+ const buried = pos > visiblePeek;
102
+ const isTop = pos === 0;
103
+ const itemClasses = [
104
+ `${baseClass}__item`,
105
+ gone ? `${baseClass}__item--gone` : "",
106
+ buried ? `${baseClass}__item--buried` : "",
107
+ isTop && leaving ? `${baseClass}__item--leaving` : "",
108
+ isTop && entering ? `${baseClass}__item--entering` : ""
109
+ ].filter(Boolean).join(" ");
110
+ return /* @__PURE__ */ jsx(
111
+ "div",
112
+ {
113
+ className: itemClasses,
114
+ style: {
115
+ "--ds-card-stack-pos": gone ? 0 : Math.min(pos, visiblePeek),
116
+ zIndex: count - pos
117
+ },
118
+ inert: !isTop || void 0,
119
+ "aria-hidden": !isTop || void 0,
120
+ onAnimationEnd: isTop ? handleTopAnimationEnd : void 0,
121
+ children: child
122
+ },
123
+ k
124
+ );
125
+ }),
126
+ count > 1 && /* @__PURE__ */ jsxs("div", { className: `${baseClass}__sr-only`, role: "status", children: [
127
+ "Card ",
128
+ index + 1,
129
+ " of ",
130
+ count
131
+ ] })
132
+ ]
133
+ }
134
+ );
135
+ }
136
+ );
137
+ CardStack.displayName = "CardStack";
138
+ export {
139
+ CardStack
140
+ };
@@ -110,3 +110,12 @@
110
110
  outline: 2px solid var(--color-action-primary-bg);
111
111
  outline-offset: 2px;
112
112
  }
113
+
114
+ /* Icons take the colour of the text around them. Explicit, not just
115
+ inherited by default: a consumer stylesheet that sets a colour on
116
+ .material-symbols-rounded itself (a common global default) would
117
+ otherwise override inheritance and detach the icon from the state
118
+ colours this component sets on its parents. */
119
+ .ds-carousel .material-symbols-rounded {
120
+ color: inherit;
121
+ }
@@ -1,14 +1,23 @@
1
1
  "use client";
2
2
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
3
- import React, { useState, useRef, useCallback, useEffect } from "react";
3
+ import React, { useState, useSyncExternalStore, useRef, useCallback, useEffect } from "react";
4
+ import { MOTION_AUTOPLAY_INTERVAL_MS } from "../../tokens/motion.js";
4
5
  import "./Carousel.css";
5
6
  import "../../fonts/material-symbols.css";
7
+ const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
8
+ const subscribeReducedMotion = (callback) => {
9
+ const query = window.matchMedia(REDUCED_MOTION_QUERY);
10
+ query.addEventListener("change", callback);
11
+ return () => query.removeEventListener("change", callback);
12
+ };
13
+ const getReducedMotion = () => window.matchMedia(REDUCED_MOTION_QUERY).matches;
14
+ const getServerReducedMotion = () => false;
6
15
  const Carousel = ({
7
16
  children,
8
17
  showDots = true,
9
18
  showArrows = true,
10
19
  autoPlay = false,
11
- autoPlayInterval = 5e3,
20
+ autoPlayInterval = MOTION_AUTOPLAY_INTERVAL_MS,
12
21
  loop = false,
13
22
  onSlideChange,
14
23
  className = ""
@@ -17,6 +26,11 @@ const Carousel = ({
17
26
  const slideCount = slides.length;
18
27
  const [activeIndex, setActiveIndex] = useState(0);
19
28
  const [paused, setPaused] = useState(false);
29
+ const reducedMotion = useSyncExternalStore(
30
+ subscribeReducedMotion,
31
+ getReducedMotion,
32
+ getServerReducedMotion
33
+ );
20
34
  const containerRef = useRef(null);
21
35
  const baseClass = "ds-carousel";
22
36
  const goTo = useCallback(
@@ -35,10 +49,10 @@ const Carousel = ({
35
49
  const goNext = useCallback(() => goTo(activeIndex + 1), [activeIndex, goTo]);
36
50
  const goPrev = useCallback(() => goTo(activeIndex - 1), [activeIndex, goTo]);
37
51
  useEffect(() => {
38
- if (!autoPlay || paused || slideCount <= 1) return;
52
+ if (!autoPlay || paused || reducedMotion || slideCount <= 1) return;
39
53
  const interval = setInterval(goNext, autoPlayInterval);
40
54
  return () => clearInterval(interval);
41
- }, [autoPlay, paused, autoPlayInterval, goNext, slideCount]);
55
+ }, [autoPlay, paused, reducedMotion, autoPlayInterval, goNext, slideCount]);
42
56
  const handleKeyDown = (e) => {
43
57
  if (e.key === "ArrowLeft") {
44
58
  e.preventDefault();
@@ -48,6 +62,21 @@ const Carousel = ({
48
62
  goNext();
49
63
  }
50
64
  };
65
+ const handleDotKeyDown = (e, index) => {
66
+ let target;
67
+ if (e.key === "ArrowRight") {
68
+ target = loop ? (index + 1) % slideCount : Math.min(index + 1, slideCount - 1);
69
+ } else if (e.key === "ArrowLeft") {
70
+ target = loop ? (index - 1 + slideCount) % slideCount : Math.max(index - 1, 0);
71
+ }
72
+ if (target === void 0) return;
73
+ e.preventDefault();
74
+ e.stopPropagation();
75
+ goTo(target);
76
+ const dotList = e.target.parentElement;
77
+ const dots = dotList?.querySelectorAll(`.${baseClass}__dot`);
78
+ dots?.[target]?.focus();
79
+ };
51
80
  const canGoPrev = loop || activeIndex > 0;
52
81
  const canGoNext = loop || activeIndex < slideCount - 1;
53
82
  const containerClasses = [baseClass, className].filter(Boolean).join(" ");
@@ -59,6 +88,8 @@ const Carousel = ({
59
88
  ref: containerRef,
60
89
  onMouseEnter: () => setPaused(true),
61
90
  onMouseLeave: () => setPaused(false),
91
+ onFocus: () => setPaused(true),
92
+ onBlur: () => setPaused(false),
62
93
  onKeyDown: handleKeyDown,
63
94
  role: "region",
64
95
  "aria-roledescription": "carousel",
@@ -111,8 +142,10 @@ const Carousel = ({
111
142
  {
112
143
  className: `${baseClass}__dot${index === activeIndex ? ` ${baseClass}__dot--active` : ""}`,
113
144
  onClick: () => goTo(index),
145
+ onKeyDown: (e) => handleDotKeyDown(e, index),
114
146
  role: "tab",
115
147
  "aria-selected": index === activeIndex,
148
+ tabIndex: index === activeIndex ? 0 : -1,
116
149
  "aria-label": `Go to slide ${index + 1}`,
117
150
  type: "button"
118
151
  },
@@ -1,6 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback } from "react";
3
3
  import { ResponsiveContainer, AreaChart as AreaChart$1, CartesianGrid, XAxis, YAxis, Tooltip, Area, Legend } from "recharts";
4
+ import { getChartSeriesColors } from "./palette.js";
4
5
  import "./Chart.css";
5
6
  function getCSSVar(name, fallback) {
6
7
  if (typeof window === "undefined") return fallback;
@@ -32,7 +33,7 @@ const AreaChart = ({
32
33
  const classes = [baseClass, className].filter(Boolean).join(" ");
33
34
  const textSecondary = getCSSVar("--color-text-secondary", "#A2A2A2");
34
35
  const gridColor = getCSSVar("--color-divider", "#232323");
35
- const defaultColor = getCSSVar("--color-action-primary-bg", "#118AB2");
36
+ const seriesColors = getChartSeriesColors();
36
37
  const renderTooltip = useCallback(
37
38
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
38
39
  (props) => /* @__PURE__ */ jsx(AreaTooltip, { ...props }),
@@ -50,8 +51,8 @@ const AreaChart = ({
50
51
  ] }, i)) })
51
52
  ] }),
52
53
  /* @__PURE__ */ jsx("div", { className: `${baseClass}__body`, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxs(AreaChart$1, { data, margin: { top: 8, right: 4, bottom: 0, left: -12 }, children: [
53
- /* @__PURE__ */ jsx("defs", { children: series.map((s) => {
54
- const color = s.color || defaultColor;
54
+ /* @__PURE__ */ jsx("defs", { children: series.map((s, i) => {
55
+ const color = s.color || seriesColors[i % seriesColors.length];
55
56
  return /* @__PURE__ */ jsxs("linearGradient", { id: `area-gradient-${s.dataKey}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
56
57
  /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.4 }),
57
58
  /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0.05 })
@@ -76,13 +77,13 @@ const AreaChart = ({
76
77
  }
77
78
  ),
78
79
  /* @__PURE__ */ jsx(Tooltip, { content: renderTooltip }),
79
- series.map((s) => /* @__PURE__ */ jsx(
80
+ series.map((s, i) => /* @__PURE__ */ jsx(
80
81
  Area,
81
82
  {
82
83
  type: "monotone",
83
84
  dataKey: s.dataKey,
84
85
  name: s.label,
85
- stroke: s.color || defaultColor,
86
+ stroke: s.color || seriesColors[i % seriesColors.length],
86
87
  strokeWidth: 2,
87
88
  fill: `url(#area-gradient-${s.dataKey})`,
88
89
  fillOpacity: s.fillOpacity ?? 1,
@@ -37,7 +37,7 @@ const BarChart = ({
37
37
  }) => {
38
38
  const baseClass = "ds-chart";
39
39
  const classes = [baseClass, className].filter(Boolean).join(" ");
40
- const resolvedBarColor = barColor || getCSSVar("--color-action-primary-bg", "#118AB2");
40
+ const resolvedBarColor = barColor || getCSSVar("--color-action-primary-bg", "#0E6E8F");
41
41
  const textSecondary = getCSSVar("--color-text-secondary", "#A2A2A2");
42
42
  const gridColor = getCSSVar("--color-divider", "#232323");
43
43
  const cursorColor = getCSSVar("--color-bg-container-secondary", "#303030");
@@ -1,6 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback } from "react";
3
3
  import { ResponsiveContainer, LineChart as LineChart$1, CartesianGrid, XAxis, YAxis, Tooltip, Line } from "recharts";
4
+ import { getChartSeriesColors } from "./palette.js";
4
5
  import "./Chart.css";
5
6
  function getCSSVar(name, fallback) {
6
7
  if (typeof window === "undefined") return fallback;
@@ -31,7 +32,7 @@ const LineChart = ({
31
32
  const classes = [baseClass, className].filter(Boolean).join(" ");
32
33
  const textSecondary = getCSSVar("--color-text-secondary", "#A2A2A2");
33
34
  const gridColor = getCSSVar("--color-divider", "#232323");
34
- const defaultColor = getCSSVar("--color-action-primary-bg", "#118AB2");
35
+ const seriesColors = getChartSeriesColors();
35
36
  const renderTooltip = useCallback(
36
37
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
37
38
  (props) => /* @__PURE__ */ jsx(LineChartTooltip, { ...props }),
@@ -68,13 +69,13 @@ const LineChart = ({
68
69
  }
69
70
  ),
70
71
  /* @__PURE__ */ jsx(Tooltip, { content: renderTooltip }),
71
- series.map((s) => /* @__PURE__ */ jsx(
72
+ series.map((s, i) => /* @__PURE__ */ jsx(
72
73
  Line,
73
74
  {
74
75
  type: "monotone",
75
76
  dataKey: s.dataKey,
76
77
  name: s.label,
77
- stroke: s.color || defaultColor,
78
+ stroke: s.color || seriesColors[i % seriesColors.length],
78
79
  strokeWidth: 2,
79
80
  strokeDasharray: s.strokeDasharray,
80
81
  dot: false,
@@ -1,21 +1,8 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback } from "react";
3
3
  import { ResponsiveContainer, PieChart as PieChart$1, Pie, Cell, Tooltip, Legend } from "recharts";
4
+ import { getChartSeriesColors } from "./palette.js";
4
5
  import "./Chart.css";
5
- function getDefaultColors() {
6
- if (typeof window === "undefined") {
7
- return ["#118AB2", "#06D6A0", "#FFD166", "#EF476F", "#9E47EF", "#EF8247"];
8
- }
9
- const get = (v, fb) => getComputedStyle(document.documentElement).getPropertyValue(v).trim() || fb;
10
- return [
11
- get("--color-action-primary-bg", "#118AB2"),
12
- get("--color-core-accent-mint", "#06D6A0"),
13
- get("--color-core-accent-gold", "#FFD166"),
14
- get("--color-core-accent-coral", "#EF476F"),
15
- get("--color-core-accent-violet", "#9E47EF"),
16
- get("--color-core-accent-amber", "#EF8247")
17
- ];
18
- }
19
6
  function getCSSVar(name, fallback) {
20
7
  if (typeof window === "undefined") return fallback;
21
8
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
@@ -48,7 +35,7 @@ const PieChart = ({
48
35
  }) => {
49
36
  const baseClass = "ds-chart";
50
37
  const classes = [baseClass, className].filter(Boolean).join(" ");
51
- const defaultColors = getDefaultColors();
38
+ const defaultColors = getChartSeriesColors();
52
39
  const textSecondary = getCSSVar("--color-text-secondary", "#A2A2A2");
53
40
  const renderTooltip = useCallback(
54
41
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
@@ -1,6 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback } from "react";
3
3
  import { ResponsiveContainer, RadarChart as RadarChart$1, PolarGrid, PolarAngleAxis, PolarRadiusAxis, Tooltip, Radar, Legend } from "recharts";
4
+ import { getChartSeriesColors } from "./palette.js";
4
5
  import "./Chart.css";
5
6
  function getCSSVar(name, fallback) {
6
7
  if (typeof window === "undefined") return fallback;
@@ -31,7 +32,7 @@ const RadarChart = ({
31
32
  const classes = [baseClass, className].filter(Boolean).join(" ");
32
33
  const textSecondary = getCSSVar("--color-text-secondary", "#A2A2A2");
33
34
  const gridColor = getCSSVar("--color-divider", "#232323");
34
- const defaultColor = getCSSVar("--color-action-primary-bg", "#118AB2");
35
+ const seriesColors = getChartSeriesColors();
35
36
  const renderTooltip = useCallback(
36
37
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
37
38
  (props) => /* @__PURE__ */ jsx(RadarTooltip, { ...props }),
@@ -66,13 +67,13 @@ const RadarChart = ({
66
67
  }
67
68
  ),
68
69
  /* @__PURE__ */ jsx(Tooltip, { content: renderTooltip }),
69
- series.map((s) => /* @__PURE__ */ jsx(
70
+ series.map((s, i) => /* @__PURE__ */ jsx(
70
71
  Radar,
71
72
  {
72
73
  name: s.label,
73
74
  dataKey: s.dataKey,
74
- stroke: s.color || defaultColor,
75
- fill: s.color || defaultColor,
75
+ stroke: s.color || seriesColors[i % seriesColors.length],
76
+ fill: s.color || seriesColors[i % seriesColors.length],
76
77
  fillOpacity: s.fillOpacity ?? 0.3
77
78
  },
78
79
  s.dataKey
@@ -1,21 +1,8 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback } from "react";
3
3
  import { ResponsiveContainer, RadialBarChart, PolarAngleAxis, RadialBar, Tooltip, Legend } from "recharts";
4
+ import { getChartSeriesColors } from "./palette.js";
4
5
  import "./Chart.css";
5
- function getDefaultColors() {
6
- if (typeof window === "undefined") {
7
- return ["#118AB2", "#06D6A0", "#FFD166", "#EF476F", "#9E47EF", "#EF8247"];
8
- }
9
- const get = (v, fb) => getComputedStyle(document.documentElement).getPropertyValue(v).trim() || fb;
10
- return [
11
- get("--color-action-primary-bg", "#118AB2"),
12
- get("--color-core-accent-mint", "#06D6A0"),
13
- get("--color-core-accent-gold", "#FFD166"),
14
- get("--color-core-accent-coral", "#EF476F"),
15
- get("--color-core-accent-violet", "#9E47EF"),
16
- get("--color-core-accent-amber", "#EF8247")
17
- ];
18
- }
19
6
  function getCSSVar(name, fallback) {
20
7
  if (typeof window === "undefined") return fallback;
21
8
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
@@ -49,7 +36,7 @@ const RadialChart = ({
49
36
  }) => {
50
37
  const baseClass = "ds-chart";
51
38
  const classes = [baseClass, className].filter(Boolean).join(" ");
52
- const defaultColors = getDefaultColors();
39
+ const defaultColors = getChartSeriesColors();
53
40
  const textSecondary = getCSSVar("--color-text-secondary", "#A2A2A2");
54
41
  const bgColor = getCSSVar("--color-bg-container-primary", "#0E0E0E");
55
42
  const chartData = data.map((item, i) => ({
@@ -1,19 +1,8 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback } from "react";
3
3
  import { ResponsiveContainer, ScatterChart as ScatterChart$1, CartesianGrid, XAxis, YAxis, ZAxis, Tooltip, Scatter, Legend } from "recharts";
4
+ import { getChartSeriesColors } from "./palette.js";
4
5
  import "./Chart.css";
5
- const PALETTE = [
6
- "#118AB2",
7
- // teal-07
8
- "#06D6A0",
9
- // green-07
10
- "#EF476F",
11
- // red-07
12
- "#FFD166",
13
- // yellow-07
14
- "#9E47EF"
15
- // purple-07
16
- ];
17
6
  function getCSSVar(name, fallback) {
18
7
  if (typeof window === "undefined") return fallback;
19
8
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
@@ -47,6 +36,7 @@ const ScatterChart = ({
47
36
  }) => {
48
37
  const baseClass = "ds-chart";
49
38
  const classes = [baseClass, className].filter(Boolean).join(" ");
39
+ const seriesColors = getChartSeriesColors();
50
40
  const textSecondary = getCSSVar("--color-text-secondary", "#A2A2A2");
51
41
  const gridColor = getCSSVar("--color-divider", "#232323");
52
42
  const renderTooltip = useCallback(
@@ -96,7 +86,7 @@ const ScatterChart = ({
96
86
  {
97
87
  name: ds.name,
98
88
  data: ds.data,
99
- fill: ds.color || PALETTE[i % PALETTE.length]
89
+ fill: ds.color || seriesColors[i % seriesColors.length]
100
90
  },
101
91
  ds.name
102
92
  )),
@@ -1,25 +1,12 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback } from "react";
3
3
  import { ResponsiveContainer, BarChart, CartesianGrid, XAxis, YAxis, Tooltip, Bar } from "recharts";
4
+ import { getChartSeriesColors } from "./palette.js";
4
5
  import "./Chart.css";
5
6
  function getCSSVar(name, fallback) {
6
7
  if (typeof window === "undefined") return fallback;
7
8
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
8
9
  }
9
- function getDefaultColors() {
10
- if (typeof window === "undefined") {
11
- return ["#118AB2", "#06D6A0", "#FFD166", "#EF476F", "#9E47EF", "#EF8247"];
12
- }
13
- const get = (v, fb) => getComputedStyle(document.documentElement).getPropertyValue(v).trim() || fb;
14
- return [
15
- get("--color-action-primary-bg", "#118AB2"),
16
- get("--color-core-accent-mint", "#06D6A0"),
17
- get("--color-core-accent-gold", "#FFD166"),
18
- get("--color-core-accent-coral", "#EF476F"),
19
- get("--color-core-accent-violet", "#9E47EF"),
20
- get("--color-core-accent-amber", "#EF8247")
21
- ];
22
- }
23
10
  function StackedTooltip({ active, payload, label }) {
24
11
  if (!active || !payload?.length) return null;
25
12
  return /* @__PURE__ */ jsxs("div", { className: "ds-chart__tooltip", children: [
@@ -47,7 +34,7 @@ const StackedBarChart = ({
47
34
  const textSecondary = getCSSVar("--color-text-secondary", "#A2A2A2");
48
35
  const gridColor = getCSSVar("--color-divider", "#232323");
49
36
  const cursorColor = getCSSVar("--color-bg-container-secondary", "#303030");
50
- const defaultColors = getDefaultColors();
37
+ const defaultColors = getChartSeriesColors();
51
38
  const renderTooltip = useCallback(
52
39
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
53
40
  (props) => /* @__PURE__ */ jsx(StackedTooltip, { ...props }),
@@ -1,23 +1,8 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback } from "react";
3
3
  import { ResponsiveContainer, Treemap as Treemap$1, Tooltip } from "recharts";
4
+ import { getChartSeriesColors } from "./palette.js";
4
5
  import "./Chart.css";
5
- const PALETTE = [
6
- "#118AB2",
7
- // teal-07
8
- "#06D6A0",
9
- // green-07
10
- "#EF476F",
11
- // red-07
12
- "#FFD166",
13
- // yellow-07
14
- "#9E47EF",
15
- // purple-07
16
- "#1E47B0",
17
- // blue-07
18
- "#EF8247"
19
- // orange
20
- ];
21
6
  function getCSSVar(name, fallback) {
22
7
  if (typeof window === "undefined") return fallback;
23
8
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
@@ -25,7 +10,8 @@ function getCSSVar(name, fallback) {
25
10
  function TreemapContent(props) {
26
11
  const { x, y, width, height, name, index, color } = props;
27
12
  if (width < 4 || height < 4) return null;
28
- const fill = color || PALETTE[index % PALETTE.length];
13
+ const seriesColors = getChartSeriesColors();
14
+ const fill = color || seriesColors[index % seriesColors.length];
29
15
  const textColor = getCSSVar("--color-text-primary", "#050505");
30
16
  const showLabel = width > 50 && height > 28;
31
17
  return /* @__PURE__ */ jsxs("g", { children: [
@@ -0,0 +1 @@
1
+ export declare function getChartSeriesColors(): string[];
@@ -0,0 +1,19 @@
1
+ const SERIES_FALLBACKS = [
2
+ "#0E6E8F",
3
+ "#06D6A0",
4
+ "#FFD166",
5
+ "#EF476F",
6
+ "#9E47EF",
7
+ "#EF8247",
8
+ "#1E47B0"
9
+ ];
10
+ function getChartSeriesColors() {
11
+ if (typeof window === "undefined") return SERIES_FALLBACKS;
12
+ const style = getComputedStyle(document.documentElement);
13
+ return SERIES_FALLBACKS.map(
14
+ (fallback, i) => style.getPropertyValue(`--color-chart-series-${i + 1}`).trim() || fallback
15
+ );
16
+ }
17
+ export {
18
+ getChartSeriesColors
19
+ };
@@ -50,3 +50,12 @@
50
50
  .ds-chat-marker__icon .material-symbols-rounded {
51
51
  --icon-size: var(--icon-size-sm);
52
52
  }
53
+
54
+ /* Icons take the colour of the text around them. Explicit, not just
55
+ inherited by default: a consumer stylesheet that sets a colour on
56
+ .material-symbols-rounded itself (a common global default) would
57
+ otherwise override inheritance and detach the icon from the state
58
+ colours this component sets on its parents. */
59
+ .ds-chat-marker .material-symbols-rounded {
60
+ color: inherit;
61
+ }
@@ -110,6 +110,22 @@
110
110
  color: var(--color-text-primary);
111
111
  }
112
112
 
113
+ /* Card furniture inside a turn steps clear of the content around it — at
114
+ the body's default rhythm an adjacent text line sits close enough to read
115
+ as a caption rather than a neighbouring block. Margins, not gap, so a
116
+ card standing alone adds nothing. */
117
+ .ds-chat-message__content > .ds-message-card:not(:first-child),
118
+ .ds-chat-message__content > .ds-interrupt-card:not(:first-child),
119
+ .ds-chat-message__content > .ds-tool-call:not(:first-child) {
120
+ margin-top: var(--gap-sm-md);
121
+ }
122
+
123
+ .ds-chat-message__content > .ds-message-card:not(:last-child),
124
+ .ds-chat-message__content > .ds-interrupt-card:not(:last-child),
125
+ .ds-chat-message__content > .ds-tool-call:not(:last-child) {
126
+ margin-bottom: var(--gap-sm-md);
127
+ }
128
+
113
129
  /* Bubble — capped width so a short line never drags a surface across the
114
130
  whole row; the fallback is the sanctioned consumer-override hook */
115
131
  .ds-chat-message--bubble .ds-chat-message__content {
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from "react/jsx-runtime";
3
3
  import React, { useRef, useEffect, useState, useLayoutEffect } from "react";
4
+ import { MOTION_SCROLL_SETTLE_MS } from "../../tokens/motion.js";
4
5
  import "./ChatThread.css";
5
6
  import "../../fonts/material-symbols.css";
6
- const SCROLLBAR_SETTLE_MS = 600;
7
7
  const JUMP_THRESHOLD_PX = 24;
8
8
  const ChatThread = React.forwardRef(
9
9
  ({
@@ -129,7 +129,7 @@ const ChatThread = React.forwardRef(
129
129
  window.clearTimeout(settleTimer.current);
130
130
  settleTimer.current = window.setTimeout(
131
131
  () => setScrolling(false),
132
- SCROLLBAR_SETTLE_MS
132
+ MOTION_SCROLL_SETTLE_MS
133
133
  );
134
134
  };
135
135
  const jumpToBottom = () => {
@@ -220,3 +220,12 @@
220
220
  outline: 2px solid var(--color-action-primary-bg);
221
221
  outline-offset: 2px;
222
222
  }
223
+
224
+ /* Icons take the colour of the text around them. Explicit, not just
225
+ inherited by default: a consumer stylesheet that sets a colour on
226
+ .material-symbols-rounded itself (a common global default) would
227
+ otherwise override inheritance and detach the icon from the state
228
+ colours this component sets on its parents. */
229
+ .ds-chip .material-symbols-rounded {
230
+ color: inherit;
231
+ }
@@ -95,7 +95,7 @@
95
95
  font-weight: var(--font-paragraph-sm-em-weight);
96
96
  line-height: var(--font-paragraph-sm-line-height);
97
97
  text-transform: uppercase;
98
- letter-spacing: 0.08em;
98
+ letter-spacing: var(--font-overline-letter-spacing);
99
99
  color: var(--color-text-tertiary);
100
100
  flex-shrink: 0;
101
101
  }
@@ -178,3 +178,12 @@
178
178
  color: var(--color-text-primary);
179
179
  white-space: pre;
180
180
  }
181
+
182
+ /* Icons take the colour of the text around them. Explicit, not just
183
+ inherited by default: a consumer stylesheet that sets a colour on
184
+ .material-symbols-rounded itself (a common global default) would
185
+ otherwise override inheritance and detach the icon from the state
186
+ colours this component sets on its parents. */
187
+ .ds-code-block .material-symbols-rounded {
188
+ color: inherit;
189
+ }