@robr0/design-system 0.8.0 → 0.10.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 (109) hide show
  1. package/README.md +12 -7
  2. package/components/Accordion/Accordion.js +1 -0
  3. package/components/AgentPlan/AgentPlan.css +2 -2
  4. package/components/AgentPlan/AgentPlan.js +1 -0
  5. package/components/AgentStatus/AgentStatus.js +1 -0
  6. package/components/AiButton/AiButton.js +1 -0
  7. package/components/AlertDialog/AlertDialog.js +1 -0
  8. package/components/AnchorNav/AnchorNav.css +63 -0
  9. package/components/AnchorNav/AnchorNav.d.ts +33 -0
  10. package/components/AnchorNav/AnchorNav.js +82 -0
  11. package/components/AppLayout/AppLayout.js +1 -0
  12. package/components/AppSidebar/AppSidebar.css +13 -3
  13. package/components/AppSidebar/AppSidebar.d.ts +6 -2
  14. package/components/AppSidebar/AppSidebar.js +68 -36
  15. package/components/Avatar/Avatar.js +1 -0
  16. package/components/Button/Button.js +1 -0
  17. package/components/Card/Card.js +1 -0
  18. package/components/Carousel/Carousel.js +1 -0
  19. package/components/Chart/AreaChart.js +1 -1
  20. package/components/Chart/BarChart.js +1 -1
  21. package/components/Chart/LineChart.js +1 -1
  22. package/components/Chart/PieChart.js +2 -2
  23. package/components/Chart/RadarChart.js +1 -1
  24. package/components/Chart/RadialChart.js +2 -2
  25. package/components/Chart/StackedBarChart.js +2 -2
  26. package/components/ChatThread/ChatThread.js +1 -0
  27. package/components/Checkbox/Checkbox.js +1 -0
  28. package/components/CodeBlock/CodeBlock.js +1 -0
  29. package/components/CodeDiff/CodeDiff.css +175 -0
  30. package/components/CodeDiff/CodeDiff.d.ts +58 -0
  31. package/components/CodeDiff/CodeDiff.js +114 -0
  32. package/components/ColorPicker/ColorPicker.js +1 -0
  33. package/components/Combobox/Combobox.js +1 -0
  34. package/components/CommandPalette/CommandPalette.js +1 -0
  35. package/components/Composer/Composer.js +1 -0
  36. package/components/ContactCard/ContactCard.js +1 -0
  37. package/components/ContextMenu/ContextMenu.js +1 -0
  38. package/components/DataTable/DataTable.js +1 -0
  39. package/components/DateInput/DateInput.js +1 -0
  40. package/components/DatePicker/DatePicker.js +1 -0
  41. package/components/Dialog/Dialog.js +1 -0
  42. package/components/Drawer/Drawer.js +1 -0
  43. package/components/Dropdown/Dropdown.js +1 -0
  44. package/components/DropdownMenu/DropdownMenu.css +1 -1
  45. package/components/DropdownMenu/DropdownMenu.js +1 -0
  46. package/components/EventCalendar/EventCalendar.js +1 -0
  47. package/components/Field/Field.js +1 -0
  48. package/components/Field/FieldContext.js +1 -0
  49. package/components/FileInput/FileInput.js +1 -0
  50. package/components/Input/Input.js +1 -0
  51. package/components/InterruptCard/InterruptCard.css +11 -21
  52. package/components/InterruptCard/InterruptCard.d.ts +5 -6
  53. package/components/MessageCard/MessageCard.css +1 -2
  54. package/components/ModelPicker/ModelPicker.css +3 -1
  55. package/components/ModelPicker/ModelPicker.js +1 -0
  56. package/components/NavList/NavList.js +1 -0
  57. package/components/NotificationCenter/NotificationCenter.js +1 -0
  58. package/components/NumberInput/NumberInput.css +154 -0
  59. package/components/NumberInput/NumberInput.d.ts +44 -0
  60. package/components/NumberInput/NumberInput.js +147 -0
  61. package/components/Pagination/Pagination.js +1 -0
  62. package/components/PinInput/PinInput.css +92 -0
  63. package/components/PinInput/PinInput.d.ts +46 -0
  64. package/components/PinInput/PinInput.js +161 -0
  65. package/components/Popover/Popover.css +5 -6
  66. package/components/Popover/Popover.js +1 -0
  67. package/components/RadioButton/RadioButton.js +1 -0
  68. package/components/Reasoning/Reasoning.js +1 -0
  69. package/components/SectionTitle/SectionTitle.css +8 -0
  70. package/components/SectionTitle/SectionTitle.d.ts +3 -1
  71. package/components/SectionTitle/SectionTitle.js +6 -1
  72. package/components/SegmentedControl/SegmentedControl.js +1 -0
  73. package/components/SelectionCard/SelectionCard.js +1 -0
  74. package/components/ShaderField/ShaderField.js +1 -0
  75. package/components/ShaderField/useShaderField.js +1 -0
  76. package/components/Slider/Slider.js +1 -0
  77. package/components/Sparkline/Sparkline.css +52 -0
  78. package/components/Sparkline/Sparkline.d.ts +49 -0
  79. package/components/Sparkline/Sparkline.js +86 -0
  80. package/components/Stepper/Stepper.css +207 -0
  81. package/components/Stepper/Stepper.d.ts +41 -0
  82. package/components/Stepper/Stepper.js +61 -0
  83. package/components/Tabs/Tabs.js +1 -0
  84. package/components/TagInput/TagInput.css +160 -0
  85. package/components/TagInput/TagInput.d.ts +43 -0
  86. package/components/TagInput/TagInput.js +137 -0
  87. package/components/Textarea/Textarea.js +1 -0
  88. package/components/TimePicker/TimePicker.css +230 -0
  89. package/components/TimePicker/TimePicker.d.ts +46 -0
  90. package/components/TimePicker/TimePicker.js +246 -0
  91. package/components/Toast/Toast.js +1 -0
  92. package/components/ToggleGroup/ToggleGroup.js +1 -0
  93. package/components/ToggleSwitch/ToggleSwitch.js +1 -0
  94. package/components/ToolCall/ToolCall.css +7 -11
  95. package/components/ToolCall/ToolCall.js +1 -0
  96. package/components/Tooltip/Tooltip.js +1 -0
  97. package/components/TreeView/TreeView.css +119 -0
  98. package/components/TreeView/TreeView.d.ts +45 -0
  99. package/components/TreeView/TreeView.js +232 -0
  100. package/components/registry.d.ts +22 -6
  101. package/components/registry.js +3 -1
  102. package/components/registry.json +206 -20
  103. package/components/registry.json.d.ts +206 -20
  104. package/components/registry.json.js +2 -2
  105. package/index.d.ts +11 -2
  106. package/index.js +21 -1
  107. package/package.json +1 -1
  108. package/tokens/tokens-dark.css +17 -13
  109. package/tokens/tokens-light.css +15 -12
@@ -11,6 +11,14 @@
11
11
  padding-bottom: var(--padding-xl);
12
12
  }
13
13
 
14
+ /* Divider-less variant: for headings above content that draws its own
15
+ lines, where a second rule would double up. The generous clearance
16
+ the divider needed drops to a small breathing gap. */
17
+ .ds-section-title--no-divider {
18
+ border-bottom: none;
19
+ padding-bottom: var(--padding-md);
20
+ }
21
+
14
22
  /* ============================================
15
23
  HEADING
16
24
  ============================================ */
@@ -4,7 +4,9 @@ export interface SectionTitleProps {
4
4
  title: string;
5
5
  /** Optional trailing content (count, badge, metadata) */
6
6
  trailing?: React.ReactNode;
7
+ /** Whether to draw the bottom divider line. Set false above content that draws its own lines (bordered tables, calendars), so the section separates by whitespace alone. */
8
+ divider?: boolean;
7
9
  /** Additional CSS classes */
8
10
  className?: string;
9
11
  }
10
- export declare function SectionTitle({ title, trailing, className, }: SectionTitleProps): React.JSX.Element;
12
+ export declare function SectionTitle({ title, trailing, divider, className, }: SectionTitleProps): React.JSX.Element;
@@ -4,9 +4,14 @@ import "./SectionTitle.css";
4
4
  function SectionTitle({
5
5
  title,
6
6
  trailing,
7
+ divider = true,
7
8
  className
8
9
  }) {
9
- const classes = ["ds-section-title", className].filter(Boolean).join(" ");
10
+ const classes = [
11
+ "ds-section-title",
12
+ !divider && "ds-section-title--no-divider",
13
+ className
14
+ ].filter(Boolean).join(" ");
10
15
  return /* @__PURE__ */ jsxs("div", { className: classes, children: [
11
16
  /* @__PURE__ */ jsx("h2", { className: "ds-section-title__heading", children: title }),
12
17
  trailing !== void 0 && trailing !== null && /* @__PURE__ */ jsx("span", { className: "ds-section-title__trailing", children: trailing })
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx, jsxs } from "react/jsx-runtime";
2
3
  import { useRef } from "react";
3
4
  import "./SegmentedControl.css";
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx, jsxs } from "react/jsx-runtime";
2
3
  import React from "react";
3
4
  import "./SelectionCard.css";
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx } from "react/jsx-runtime";
2
3
  import React, { useRef, useMemo, useState, useEffect } from "react";
3
4
  import { DEFAULT_SHADER_BLOBS, DEFAULT_SHADER_PARAMS, useShaderField } from "./useShaderField.js";
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useState, useRef, useEffect } from "react";
2
3
  import { BLOB_COUNT, vertexSource, fragmentSource } from "./field.glsl.js";
3
4
  const DEFAULT_SHADER_PARAMS = {
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx } from "react/jsx-runtime";
2
3
  import React from "react";
3
4
  import "./Slider.css";
@@ -0,0 +1,52 @@
1
+ /* ============================================
2
+ SPARKLINE COMPONENT
3
+ Inline trend line for stats and table cells.
4
+ Colour flows through `color` — the line, fill
5
+ and dot all draw with currentColor, so a tone
6
+ is one custom property swap.
7
+ ============================================ */
8
+
9
+ /* Base */
10
+
11
+ .ds-sparkline {
12
+ display: inline-block;
13
+ vertical-align: middle;
14
+ flex-shrink: 0;
15
+ color: var(--color-action-primary-bg);
16
+ }
17
+
18
+ /* Parts */
19
+
20
+ .ds-sparkline__line {
21
+ fill: none;
22
+ stroke: currentColor;
23
+ stroke-linecap: round;
24
+ stroke-linejoin: round;
25
+ }
26
+
27
+ .ds-sparkline__fill {
28
+ fill: currentColor;
29
+ opacity: 0.15;
30
+ }
31
+
32
+ .ds-sparkline__dot {
33
+ fill: currentColor;
34
+ }
35
+
36
+ /* Tones */
37
+
38
+ .ds-sparkline--accent {
39
+ color: var(--color-action-primary-bg);
40
+ }
41
+
42
+ .ds-sparkline--positive {
43
+ color: var(--color-status-positive-text);
44
+ }
45
+
46
+ .ds-sparkline--negative {
47
+ color: var(--color-status-error-text);
48
+ }
49
+
50
+ .ds-sparkline--neutral {
51
+ color: var(--color-text-secondary);
52
+ }
@@ -0,0 +1,49 @@
1
+ import { default as React } from 'react';
2
+ /** Props owned by Sparkline itself — everything else falls through to the SVG node. */
3
+ type SparklineOwnProps = {
4
+ /** The series to plot, in order. Values are normalised into the viewBox. */
5
+ data: number[];
6
+ /** Rendering treatment — a bare line, or a line with a soft fill underneath. */
7
+ variant?: 'line' | 'area';
8
+ /**
9
+ * Colour role for the line and end dot. `accent` follows the chart palette's
10
+ * lead colour; `positive`/`negative` map to the status text tokens; `neutral`
11
+ * recedes to secondary text.
12
+ */
13
+ tone?: 'accent' | 'positive' | 'negative' | 'neutral';
14
+ /** Marks the final point with a small dot. */
15
+ showDot?: boolean;
16
+ /** Line thickness in viewBox units — an SVG geometry attribute, not a token. */
17
+ strokeWidth?: number;
18
+ /**
19
+ * ViewBox width. Also the default rendered width; the SVG scales to its
20
+ * container when sized externally via CSS. Intentionally shadows the native
21
+ * SVG `width` attribute, which it sets.
22
+ */
23
+ width?: number;
24
+ /**
25
+ * ViewBox height. Also the default rendered height; the SVG scales to its
26
+ * container when sized externally via CSS. Intentionally shadows the native
27
+ * SVG `height` attribute, which it sets.
28
+ */
29
+ height?: number;
30
+ /**
31
+ * Accessible description of the trend, e.g. "Revenue, trending up". When
32
+ * omitted the SVG is decorative and hidden from assistive technology.
33
+ */
34
+ label?: string;
35
+ /** Additional CSS classes */
36
+ className?: string;
37
+ };
38
+ export interface SparklineProps extends SparklineOwnProps, Omit<React.ComponentPropsWithoutRef<'svg'>, keyof SparklineOwnProps | 'children'> {
39
+ }
40
+ /**
41
+ * Sparkline — an inline trend line for stats and table cells, drawn without
42
+ * axes or chrome. Pure SVG computed from props: no charting library, no hooks,
43
+ * no dependencies, so it renders from a Server Component and costs nothing in
44
+ * a dense table. Degenerate data never breaks the path: an all-equal series
45
+ * renders a horizontal midline, and fewer than two points render just the
46
+ * end dot, or nothing.
47
+ */
48
+ export declare const Sparkline: React.ForwardRefExoticComponent<SparklineProps & React.RefAttributes<SVGSVGElement>>;
49
+ export {};
@@ -0,0 +1,86 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import "./Sparkline.css";
4
+ const round = (n) => Math.round(n * 100) / 100;
5
+ const Sparkline = React.forwardRef(
6
+ ({
7
+ data,
8
+ variant = "line",
9
+ tone = "accent",
10
+ showDot = true,
11
+ strokeWidth = 2,
12
+ width = 120,
13
+ height = 32,
14
+ label,
15
+ className = "",
16
+ ...rest
17
+ }, ref) => {
18
+ const baseClass = "ds-sparkline";
19
+ const classes = [
20
+ baseClass,
21
+ `${baseClass}--${variant}`,
22
+ `${baseClass}--${tone}`,
23
+ className
24
+ ].filter(Boolean).join(" ");
25
+ const dotRadius = strokeWidth * 1.5;
26
+ const pad = dotRadius + strokeWidth / 2;
27
+ const innerWidth = Math.max(width - pad * 2, 0);
28
+ const innerHeight = Math.max(height - pad * 2, 0);
29
+ const min = Math.min(...data);
30
+ const max = Math.max(...data);
31
+ const range = max - min;
32
+ const points = data.map((value, i) => ({
33
+ x: round(
34
+ data.length < 2 ? pad + innerWidth : pad + i / (data.length - 1) * innerWidth
35
+ ),
36
+ // A flat series (range 0) draws a horizontal midline instead of dividing by zero.
37
+ y: round(
38
+ range === 0 ? pad + innerHeight / 2 : pad + (1 - (value - min) / range) * innerHeight
39
+ )
40
+ }));
41
+ const lastPoint = points.length > 0 ? points[points.length - 1] : void 0;
42
+ const hasLine = points.length >= 2;
43
+ const linePath = hasLine ? `M ${points.map((p) => `${p.x} ${p.y}`).join(" L ")}` : void 0;
44
+ const baseline = round(height - pad);
45
+ const areaPath = hasLine && variant === "area" ? `${linePath} L ${points[points.length - 1].x} ${baseline} L ${points[0].x} ${baseline} Z` : void 0;
46
+ return /* @__PURE__ */ jsxs(
47
+ "svg",
48
+ {
49
+ ...rest,
50
+ ref,
51
+ className: classes,
52
+ viewBox: `0 0 ${width} ${height}`,
53
+ width,
54
+ height,
55
+ xmlns: "http://www.w3.org/2000/svg",
56
+ role: label ? "img" : void 0,
57
+ "aria-label": label,
58
+ "aria-hidden": label ? void 0 : true,
59
+ children: [
60
+ areaPath && /* @__PURE__ */ jsx("path", { className: `${baseClass}__fill`, d: areaPath }),
61
+ linePath && /* @__PURE__ */ jsx(
62
+ "path",
63
+ {
64
+ className: `${baseClass}__line`,
65
+ d: linePath,
66
+ strokeWidth
67
+ }
68
+ ),
69
+ showDot && lastPoint && /* @__PURE__ */ jsx(
70
+ "circle",
71
+ {
72
+ className: `${baseClass}__dot`,
73
+ cx: lastPoint.x,
74
+ cy: lastPoint.y,
75
+ r: dotRadius
76
+ }
77
+ )
78
+ ]
79
+ }
80
+ );
81
+ }
82
+ );
83
+ Sparkline.displayName = "Sparkline";
84
+ export {
85
+ Sparkline
86
+ };
@@ -0,0 +1,207 @@
1
+ /* ============================================
2
+ STEPPER COMPONENT
3
+ Step-by-step progress indicator for wizards
4
+ and multi-stage flows
5
+ ============================================ */
6
+
7
+ /* Base */
8
+
9
+ .ds-stepper {
10
+ display: flex;
11
+ align-items: flex-start;
12
+ list-style: none;
13
+ margin: 0;
14
+ padding: 0;
15
+ width: 100%;
16
+ }
17
+
18
+ .ds-stepper__step {
19
+ position: relative;
20
+ flex: 1 1 0;
21
+ min-width: 0;
22
+ display: flex;
23
+ justify-content: center;
24
+ }
25
+
26
+ /* Shared inner layout — a <button> when the step is clickable,
27
+ a <span> otherwise */
28
+ .ds-stepper__content {
29
+ display: flex;
30
+ flex-direction: column;
31
+ align-items: center;
32
+ gap: var(--gap-sm); /* 8px */
33
+ padding: 0;
34
+ border: none;
35
+ background-color: transparent;
36
+ font-family: inherit;
37
+ text-align: center;
38
+ color: inherit;
39
+ min-width: 0;
40
+ }
41
+
42
+ button.ds-stepper__content {
43
+ cursor: pointer;
44
+ }
45
+
46
+ button.ds-stepper__content:focus-visible {
47
+ outline: 2px solid var(--color-action-primary-bg);
48
+ outline-offset: 2px;
49
+ border-radius: var(--radius-sm);
50
+ }
51
+
52
+ /* ============================================
53
+ INDICATOR
54
+ 32px circle — check for complete, number
55
+ for active and upcoming
56
+ ============================================ */
57
+
58
+ .ds-stepper__indicator {
59
+ --icon-size: var(--icon-size-sm);
60
+ display: inline-flex;
61
+ align-items: center;
62
+ justify-content: center;
63
+ width: 32px;
64
+ height: 32px;
65
+ flex-shrink: 0;
66
+ border: var(--border-xs) solid transparent;
67
+ border-radius: var(--radius-full);
68
+ font-family: var(--font-paragraph-sm-em-family);
69
+ font-size: var(--font-paragraph-sm-em-size);
70
+ font-weight: var(--font-paragraph-sm-em-weight);
71
+ line-height: var(--font-paragraph-sm-em-line-height);
72
+ letter-spacing: var(--font-paragraph-sm-em-letter-spacing);
73
+ transition:
74
+ background-color var(--motion-duration-base) var(--motion-ease-standard),
75
+ border-color var(--motion-duration-base) var(--motion-ease-standard),
76
+ color var(--motion-duration-base) var(--motion-ease-standard);
77
+ }
78
+
79
+ /* States */
80
+
81
+ .ds-stepper__step--complete .ds-stepper__indicator {
82
+ border-color: var(--color-action-primary-border-secondary);
83
+ color: var(--color-action-primary-text-tertiary);
84
+ }
85
+
86
+ .ds-stepper__step--active .ds-stepper__indicator {
87
+ background-color: var(--color-action-primary-bg);
88
+ border-color: var(--color-action-primary-bg);
89
+ color: var(--color-action-primary-text);
90
+ }
91
+
92
+ .ds-stepper__step--upcoming .ds-stepper__indicator {
93
+ border-color: var(--color-bg-container-border);
94
+ color: var(--color-text-tertiary);
95
+ }
96
+
97
+ button.ds-stepper__content:hover .ds-stepper__indicator {
98
+ background-color: var(--color-action-passive-bg-hover);
99
+ }
100
+
101
+ .ds-stepper__step--active button.ds-stepper__content:hover .ds-stepper__indicator {
102
+ background-color: var(--color-action-primary-bg-hover);
103
+ }
104
+
105
+ /* ============================================
106
+ LABEL + DESCRIPTION
107
+ ============================================ */
108
+
109
+ .ds-stepper__text {
110
+ display: flex;
111
+ flex-direction: column;
112
+ gap: var(--gap-xxs); /* 2px */
113
+ min-width: 0;
114
+ }
115
+
116
+ .ds-stepper__label {
117
+ font-family: var(--font-paragraph-sm-em-family);
118
+ font-size: var(--font-paragraph-sm-em-size);
119
+ font-weight: var(--font-paragraph-sm-em-weight);
120
+ line-height: var(--font-paragraph-sm-em-line-height);
121
+ letter-spacing: var(--font-paragraph-sm-em-letter-spacing);
122
+ color: var(--color-text-secondary);
123
+ transition: color var(--motion-duration-base) var(--motion-ease-standard);
124
+ }
125
+
126
+ .ds-stepper__step--active .ds-stepper__label {
127
+ color: var(--color-text-primary);
128
+ }
129
+
130
+ .ds-stepper__step--upcoming .ds-stepper__label {
131
+ color: var(--color-text-tertiary);
132
+ }
133
+
134
+ button.ds-stepper__content:hover .ds-stepper__label {
135
+ color: var(--color-text-primary);
136
+ }
137
+
138
+ .ds-stepper__description {
139
+ font-family: var(--font-paragraph-sm-family);
140
+ font-size: var(--font-paragraph-sm-size);
141
+ font-weight: var(--font-paragraph-sm-weight);
142
+ line-height: var(--font-paragraph-sm-line-height);
143
+ letter-spacing: var(--font-paragraph-sm-letter-spacing);
144
+ color: var(--color-text-tertiary);
145
+ }
146
+
147
+ /* ============================================
148
+ CONNECTOR
149
+ Drawn between an indicator and the next;
150
+ turns action-coloured behind completed steps
151
+ ============================================ */
152
+
153
+ .ds-stepper__connector {
154
+ position: absolute;
155
+ top: 16px; /* vertical centre of the 32px indicator */
156
+ left: calc(50% + 24px);
157
+ right: calc(-50% + 24px);
158
+ height: var(--border-md);
159
+ transform: translateY(-50%);
160
+ background-color: var(--color-divider);
161
+ transition: background-color var(--motion-duration-base) var(--motion-ease-standard);
162
+ }
163
+
164
+ .ds-stepper__step--complete .ds-stepper__connector {
165
+ background-color: var(--color-action-primary-border-secondary);
166
+ }
167
+
168
+ /* ============================================
169
+ VERTICAL
170
+ ============================================ */
171
+
172
+ .ds-stepper--vertical {
173
+ flex-direction: column;
174
+ align-items: stretch;
175
+ }
176
+
177
+ .ds-stepper--vertical .ds-stepper__step {
178
+ flex: none;
179
+ justify-content: flex-start;
180
+ padding-bottom: var(--gap-lg); /* 20px */
181
+ }
182
+
183
+ .ds-stepper--vertical .ds-stepper__step:last-child {
184
+ padding-bottom: 0;
185
+ }
186
+
187
+ .ds-stepper--vertical .ds-stepper__content {
188
+ flex-direction: row;
189
+ align-items: flex-start;
190
+ gap: var(--gap-sm-md); /* 12px */
191
+ text-align: left;
192
+ }
193
+
194
+ /* Centre the first label line on the 32px indicator */
195
+ .ds-stepper--vertical .ds-stepper__text {
196
+ padding-top: calc((32px - var(--font-paragraph-sm-em-line-height)) / 2);
197
+ }
198
+
199
+ .ds-stepper--vertical .ds-stepper__connector {
200
+ top: calc(32px + var(--gap-xs));
201
+ bottom: var(--gap-xs);
202
+ left: 16px; /* horizontal centre of the 32px indicator */
203
+ right: auto;
204
+ width: var(--border-md);
205
+ height: auto;
206
+ transform: translateX(-50%);
207
+ }
@@ -0,0 +1,41 @@
1
+ import { default as React } from 'react';
2
+ /** A single step in a Stepper flow. */
3
+ export type StepperStep = {
4
+ /** Step label shown beside or below the indicator */
5
+ label: string;
6
+ /** Optional supporting line rendered under the label */
7
+ description?: string;
8
+ };
9
+ /** Props owned by Stepper itself — everything else falls through to the `<ol>`. */
10
+ type StepperOwnProps = {
11
+ /** Ordered list of steps in the flow */
12
+ steps: StepperStep[];
13
+ /**
14
+ * Index of the active step. Steps before it render as complete (check
15
+ * icon), steps after it as upcoming (step number). Pass `steps.length`
16
+ * to mark the whole flow complete.
17
+ */
18
+ activeStep: number;
19
+ /**
20
+ * Callback with the clicked step's index. When provided, completed steps
21
+ * and the active step become buttons so the reader can revisit an earlier
22
+ * stage; upcoming steps stay non-interactive either way.
23
+ */
24
+ onStepClick?: (index: number) => void;
25
+ /** Layout direction */
26
+ orientation?: 'horizontal' | 'vertical';
27
+ /** Additional CSS classes */
28
+ className?: string;
29
+ };
30
+ export interface StepperProps extends StepperOwnProps, Omit<React.ComponentPropsWithoutRef<'ol'>, keyof StepperOwnProps> {
31
+ }
32
+ /**
33
+ * Stepper component — step-by-step progress indicator for wizards and
34
+ * multi-stage flows. Renders an ordered list of steps with CSS-drawn
35
+ * connectors: completed steps show a check, the active step carries
36
+ * `aria-current="step"`, and upcoming steps show their number.
37
+ *
38
+ * Forwards a ref to the `<ol>` and spreads unrecognised props onto it.
39
+ */
40
+ export declare const Stepper: React.ForwardRefExoticComponent<StepperProps & React.RefAttributes<HTMLOListElement>>;
41
+ export {};
@@ -0,0 +1,61 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import React from "react";
4
+ import "./Stepper.css";
5
+ import "../../fonts/material-symbols.css";
6
+ const Stepper = React.forwardRef(
7
+ ({
8
+ steps,
9
+ activeStep,
10
+ onStepClick,
11
+ orientation = "horizontal",
12
+ className = "",
13
+ ...rest
14
+ }, ref) => {
15
+ const baseClass = "ds-stepper";
16
+ const classes = [
17
+ baseClass,
18
+ orientation === "vertical" && `${baseClass}--vertical`,
19
+ className
20
+ ].filter(Boolean).join(" ");
21
+ return /* @__PURE__ */ jsx("ol", { ...rest, ref, className: classes, children: steps.map((step, index) => {
22
+ const status = index < activeStep ? "complete" : index === activeStep ? "active" : "upcoming";
23
+ const interactive = Boolean(onStepClick) && status !== "upcoming";
24
+ const indicator = /* @__PURE__ */ jsx("span", { className: `${baseClass}__indicator`, "aria-hidden": "true", children: status === "complete" ? /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded", children: "check" }) : index + 1 });
25
+ const text = /* @__PURE__ */ jsxs("span", { className: `${baseClass}__text`, children: [
26
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: step.label }),
27
+ step.description && /* @__PURE__ */ jsx("span", { className: `${baseClass}__description`, children: step.description })
28
+ ] });
29
+ return /* @__PURE__ */ jsxs(
30
+ "li",
31
+ {
32
+ className: `${baseClass}__step ${baseClass}__step--${status}`,
33
+ "aria-current": status === "active" ? "step" : void 0,
34
+ children: [
35
+ interactive ? /* @__PURE__ */ jsxs(
36
+ "button",
37
+ {
38
+ type: "button",
39
+ className: `${baseClass}__content`,
40
+ onClick: () => onStepClick?.(index),
41
+ children: [
42
+ indicator,
43
+ text
44
+ ]
45
+ }
46
+ ) : /* @__PURE__ */ jsxs("span", { className: `${baseClass}__content`, children: [
47
+ indicator,
48
+ text
49
+ ] }),
50
+ index < steps.length - 1 && /* @__PURE__ */ jsx("span", { className: `${baseClass}__connector`, "aria-hidden": "true" })
51
+ ]
52
+ },
53
+ index
54
+ );
55
+ }) });
56
+ }
57
+ );
58
+ Stepper.displayName = "Stepper";
59
+ export {
60
+ Stepper
61
+ };
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx, jsxs } from "react/jsx-runtime";
2
3
  import "react";
3
4
  import "./Tabs.css";