@ciridae/ui 1.0.2 → 1.0.4

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 (209) hide show
  1. package/dist/app/auth.d.ts +10 -0
  2. package/dist/app/auth.js +60 -0
  3. package/dist/app/error-boundary.d.ts +18 -0
  4. package/dist/app/error-boundary.js +45 -0
  5. package/dist/app/feedback.d.ts +12 -0
  6. package/dist/app/feedback.js +128 -0
  7. package/dist/app/index.d.ts +8 -0
  8. package/dist/app/index.js +8 -0
  9. package/dist/app/request-errors.d.ts +63 -0
  10. package/dist/app/request-errors.js +172 -0
  11. package/dist/app/sentry.d.ts +18 -0
  12. package/dist/app/sentry.js +52 -0
  13. package/dist/app/telemetry.d.ts +7 -0
  14. package/dist/app/telemetry.js +28 -0
  15. package/dist/app/trail.d.ts +9 -0
  16. package/dist/app/trail.js +18 -0
  17. package/dist/chat/chat-query-keys.d.ts +3 -3
  18. package/dist/chat/contract.d.ts +15 -15
  19. package/dist/chat/conversation-items-query-options.d.ts +114 -114
  20. package/dist/chat/conversation-source.d.ts +89 -0
  21. package/dist/chat/conversation-source.js +1 -0
  22. package/dist/chat/describe-tool-call.d.ts +3 -3
  23. package/dist/chat/describe-tool-call.js +3 -3
  24. package/dist/chat/message-text.d.ts +1 -1
  25. package/dist/chat/message-text.js +116 -48
  26. package/dist/chat/use-conversation-list.d.ts +6 -6
  27. package/dist/ciridae.css +16 -4
  28. package/dist/components/activity-feed.d.ts +3 -2
  29. package/dist/components/activity-feed.js +1 -0
  30. package/dist/components/agent-work.d.ts +3 -3
  31. package/dist/components/app-frame.d.ts +91 -0
  32. package/dist/components/app-frame.js +134 -0
  33. package/dist/components/app-navigation.d.ts +30 -3
  34. package/dist/components/app-navigation.js +105 -14
  35. package/dist/components/badge.d.ts +30 -5
  36. package/dist/components/badge.js +134 -15
  37. package/dist/components/brand-icons.d.ts +3 -3
  38. package/dist/components/bulk-action-bar.d.ts +1 -1
  39. package/dist/components/bulk-action-bar.js +3 -3
  40. package/dist/components/button.d.ts +12 -5
  41. package/dist/components/button.js +77 -44
  42. package/dist/components/calendar.d.ts +1 -1
  43. package/dist/components/calendar.js +44 -17
  44. package/dist/components/centered-page.d.ts +1 -1
  45. package/dist/components/centered-page.js +2 -2
  46. package/dist/components/chart.d.ts +22 -2
  47. package/dist/components/chart.js +251 -51
  48. package/dist/components/chat-client-source.d.ts +16 -0
  49. package/dist/components/chat-client-source.js +297 -0
  50. package/dist/components/chat-page.d.ts +9 -8
  51. package/dist/components/chat-page.js +7 -11
  52. package/dist/components/chat-sheet-controller.d.ts +11 -14
  53. package/dist/components/chat-sheet-controller.js +3 -3
  54. package/dist/components/chat-sheet.d.ts +18 -11
  55. package/dist/components/chat-sheet.js +188 -289
  56. package/dist/components/chat.d.ts +109 -19
  57. package/dist/components/chat.js +520 -124
  58. package/dist/components/checkbox-item.d.ts +6 -3
  59. package/dist/components/checkbox-item.js +9 -5
  60. package/dist/components/checkbox-list.d.ts +1 -1
  61. package/dist/components/chip.d.ts +6 -1
  62. package/dist/components/chip.js +27 -1
  63. package/dist/components/collapsible.d.ts +1 -1
  64. package/dist/components/color-theme.d.ts +1 -1
  65. package/dist/components/column-settings.d.ts +1 -1
  66. package/dist/components/column-settings.js +1 -1
  67. package/dist/components/command-menu.d.ts +5 -1
  68. package/dist/components/command-menu.js +98 -32
  69. package/dist/components/command-palette.d.ts +7 -3
  70. package/dist/components/command-palette.js +20 -11
  71. package/dist/components/copyable-id.d.ts +22 -5
  72. package/dist/components/copyable-id.js +46 -6
  73. package/dist/components/data-display.d.ts +39 -8
  74. package/dist/components/data-display.js +138 -19
  75. package/dist/components/data-grid.d.ts +23 -11
  76. package/dist/components/data-grid.js +61 -26
  77. package/dist/components/date-range-picker.d.ts +1 -1
  78. package/dist/components/date-range-picker.js +9 -20
  79. package/dist/components/date-time.d.ts +1 -1
  80. package/dist/components/dialog-height-context.d.ts +1 -1
  81. package/dist/components/document-viewer.d.ts +2 -2
  82. package/dist/components/drawer.d.ts +11 -6
  83. package/dist/components/drawer.js +91 -54
  84. package/dist/components/dropzone.d.ts +4 -4
  85. package/dist/components/editable-field.d.ts +12 -3
  86. package/dist/components/editable-field.js +57 -27
  87. package/dist/components/email-input.d.ts +1 -1
  88. package/dist/components/email-input.js +6 -5
  89. package/dist/components/environment-frame.d.ts +2 -2
  90. package/dist/components/environment-frame.js +37 -6
  91. package/dist/components/expandable-text.d.ts +1 -1
  92. package/dist/components/feedback-screenshot.d.ts +1 -1
  93. package/dist/components/feedback-sheet.d.ts +18 -3
  94. package/dist/components/feedback-sheet.js +216 -55
  95. package/dist/components/field-context.d.ts +1 -1
  96. package/dist/components/filter-bar.d.ts +3 -3
  97. package/dist/components/filter-bar.js +43 -29
  98. package/dist/components/form-controls.d.ts +12 -3
  99. package/dist/components/form-controls.js +46 -22
  100. package/dist/components/form-layout.d.ts +14 -10
  101. package/dist/components/form-layout.js +68 -23
  102. package/dist/components/glass-menu.d.ts +3 -0
  103. package/dist/components/glass-menu.js +63 -0
  104. package/dist/components/gradient-edge.d.ts +9 -0
  105. package/dist/components/gradient-edge.js +31 -0
  106. package/dist/components/hotkeys.d.ts +2 -2
  107. package/dist/components/icon.d.ts +1 -1
  108. package/dist/components/input.d.ts +7 -5
  109. package/dist/components/input.js +29 -17
  110. package/dist/components/keyboard-shortcuts.d.ts +2 -2
  111. package/dist/components/keycap.d.ts +10 -6
  112. package/dist/components/keycap.js +57 -19
  113. package/dist/components/layout.d.ts +13 -13
  114. package/dist/components/lightbox.d.ts +9 -3
  115. package/dist/components/lightbox.js +13 -9
  116. package/dist/components/link.d.ts +1 -1
  117. package/dist/components/locale.d.ts +42 -2
  118. package/dist/components/locale.js +43 -3
  119. package/dist/components/log-entry.d.ts +40 -0
  120. package/dist/components/log-entry.js +146 -0
  121. package/dist/components/log-list.d.ts +3 -3
  122. package/dist/components/mention-input.d.ts +2 -2
  123. package/dist/components/mention-input.js +4 -3
  124. package/dist/components/menu.d.ts +7 -3
  125. package/dist/components/menu.js +34 -37
  126. package/dist/components/meter.d.ts +10 -2
  127. package/dist/components/meter.js +64 -6
  128. package/dist/components/navigation.d.ts +21 -4
  129. package/dist/components/navigation.js +84 -19
  130. package/dist/components/notification-tray.d.ts +1 -1
  131. package/dist/components/notification-tray.js +5 -4
  132. package/dist/components/overlays.d.ts +6 -4
  133. package/dist/components/overlays.js +69 -40
  134. package/dist/components/page-frame.d.ts +4 -4
  135. package/dist/components/page-frame.js +1 -1
  136. package/dist/components/panel.d.ts +4 -4
  137. package/dist/components/panel.js +18 -12
  138. package/dist/components/profile-header.d.ts +1 -1
  139. package/dist/components/progress.d.ts +1 -1
  140. package/dist/components/project-avatar.d.ts +1 -1
  141. package/dist/components/radio-card.d.ts +2 -2
  142. package/dist/components/radio-card.js +10 -9
  143. package/dist/components/record.d.ts +29 -5
  144. package/dist/components/record.js +147 -18
  145. package/dist/components/resolved-file-url.d.ts +19 -0
  146. package/dist/components/resolved-file-url.js +49 -0
  147. package/dist/components/scroll-area.d.ts +1 -1
  148. package/dist/components/secret-dialog.d.ts +1 -1
  149. package/dist/components/segmented-bar.d.ts +4 -2
  150. package/dist/components/segmented-bar.js +16 -6
  151. package/dist/components/select.d.ts +9 -6
  152. package/dist/components/select.js +103 -127
  153. package/dist/components/settings.d.ts +4 -4
  154. package/dist/components/shell-skeleton.d.ts +1 -1
  155. package/dist/components/shell-skeleton.js +1 -1
  156. package/dist/components/shell.d.ts +21 -21
  157. package/dist/components/shell.js +43 -43
  158. package/dist/components/side-panel.d.ts +3 -3
  159. package/dist/components/sidebar.d.ts +13 -8
  160. package/dist/components/sidebar.js +55 -27
  161. package/dist/components/single-line-text.d.ts +2 -0
  162. package/dist/components/single-line-text.js +16 -0
  163. package/dist/components/site-banner.d.ts +5 -2
  164. package/dist/components/site-banner.js +17 -6
  165. package/dist/components/skeleton.d.ts +8 -7
  166. package/dist/components/skeleton.js +28 -16
  167. package/dist/components/skeletons.d.ts +17 -5
  168. package/dist/components/skeletons.js +71 -8
  169. package/dist/components/stages.d.ts +83 -11
  170. package/dist/components/stages.js +512 -156
  171. package/dist/components/stat-card.d.ts +12 -4
  172. package/dist/components/stat-card.js +92 -37
  173. package/dist/components/status-banner.d.ts +1 -1
  174. package/dist/components/status-banner.js +1 -1
  175. package/dist/components/status.d.ts +2 -2
  176. package/dist/components/steps.d.ts +1 -1
  177. package/dist/components/switch.d.ts +1 -1
  178. package/dist/components/tabs.d.ts +8 -8
  179. package/dist/components/tabs.js +26 -13
  180. package/dist/components/theme-customizer.d.ts +2 -2
  181. package/dist/components/theme-toggle.d.ts +4 -0
  182. package/dist/components/theme-toggle.js +67 -0
  183. package/dist/components/toast.d.ts +10 -3
  184. package/dist/components/toast.js +78 -29
  185. package/dist/components/use-new-version-available.d.ts +6 -0
  186. package/dist/components/use-new-version-available.js +29 -0
  187. package/dist/components/user-chip.d.ts +3 -3
  188. package/dist/components/wizard.d.ts +2 -2
  189. package/dist/feedback/contract.d.ts +136 -136
  190. package/dist/feedback/feedback-controller.d.ts +6 -6
  191. package/dist/feedback/generated/zod.gen.d.ts +28 -28
  192. package/dist/feedback/operator-contract.d.ts +11 -11
  193. package/dist/feedback/operator-controller.d.ts +32 -13
  194. package/dist/feedback/operator-controller.js +44 -11
  195. package/dist/preset.js +289 -33
  196. package/dist/styled-system/styles.css +3294 -1079
  197. package/dist/styled-system/tokens/index.mjs +598 -22
  198. package/dist/styled-system/tokens/tokens.d.ts +11 -11
  199. package/dist/styled-system/types/prop-type.d.ts +2 -2
  200. package/dist/styles.css +16 -4
  201. package/dist/theme/color.d.ts +3 -0
  202. package/dist/theme/color.js +5 -0
  203. package/dist/theme/derive.d.ts +9 -2
  204. package/dist/theme/derive.js +72 -12
  205. package/dist/theme/palettes.d.ts +49 -6
  206. package/dist/theme/palettes.js +84 -15
  207. package/dist/theme/tokens.d.ts +3 -3
  208. package/dist/theme/tokens.js +107 -32
  209. package/package.json +40 -3
@@ -7,7 +7,7 @@ export type TrendProps = {
7
7
  arrow?: boolean;
8
8
  children: ReactNode;
9
9
  };
10
- export declare function Trend({ direction, tone, arrow, children }: TrendProps): import("@types/react").JSX.Element;
10
+ export declare function Trend({ direction, tone, arrow, children }: TrendProps): import("react").JSX.Element;
11
11
  export type SparklineProps = Omit<ComponentProps<"div">, "children"> & {
12
12
  values: readonly number[];
13
13
  /** The value at the box's foot; by default far enough under the lowest that the line floats. */
@@ -17,8 +17,11 @@ export type SparklineProps = Omit<ComponentProps<"div">, "children"> & {
17
17
  strokeWidth?: number;
18
18
  endPointSize?: number;
19
19
  };
20
- /** A run of values as a line filling its box; decorative, as the figure beside it says what it shows. */
21
- export declare function Sparkline({ values, low: ownLow, high: ownHigh, strokeWidth, endPointSize, className, ...props }: SparklineProps): import("@types/react").JSX.Element;
20
+ /**
21
+ * A run of values as a line filling its box; decorative, as the figure beside it says what it
22
+ * shows. Under two values there is no line, and a dashed rule stands in for it.
23
+ */
24
+ export declare function Sparkline({ values, low: ownLow, high: ownHigh, strokeWidth, endPointSize, className, ...props }: SparklineProps): import("react").JSX.Element;
22
25
  export type MetricCardProps = Omit<useRender.ComponentProps<"div">, "children" | "onSelect"> & {
23
26
  label: ReactNode;
24
27
  value: ReactNode;
@@ -30,5 +33,10 @@ export type MetricCardProps = Omit<useRender.ComponentProps<"div">, "children" |
30
33
  onSelect?: () => void;
31
34
  /** Makes the card a link; a router's link as `render` routes it. */
32
35
  href?: string;
36
+ /**
37
+ * `card` (the default) frames it on its own; in a row of tiles, `left` rules its leading edge
38
+ * and `none` leaves it bare.
39
+ */
40
+ divider?: "card" | "left" | "none";
33
41
  };
34
- export declare function MetricCard({ label, value, change, sparkline, onSelect, href, render, className, ...props }: MetricCardProps): import("@types/react").ReactElement<unknown, string | import("@types/react").JSXElementConstructor<any>>;
42
+ export declare function MetricCard({ label, value, change, sparkline, onSelect, href, divider, render, className, ...props }: MetricCardProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -2,12 +2,12 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  /*
3
3
  * Figures for a dashboard. `MetricCard` is one figure: its label, its value, how it changed
4
4
  * (`Trend`) and its recent run (`Sparkline`); it can open what it counts. `Sparkline` is a blue
5
- * line over a flat tinted area that stretches to its box: the stroke keeps its width and the end
6
- * point is HTML, so neither distorts.
5
+ * line over an area that fades to its foot, stretched to its box: the stroke keeps its width, and
6
+ * the area and end point are HTML, so none of them distorts.
7
7
  */
8
8
  import { useRender } from "@base-ui/react/use-render";
9
9
  import { ArrowDownIcon, ArrowRightIcon, ArrowUpIcon } from "@phosphor-icons/react";
10
- import { css, cx } from "#primitives/css";
10
+ import { css, cva, cx } from "#primitives/css";
11
11
  import { icon } from "./icon.js";
12
12
  import { cardSurface } from "./panel.js";
13
13
  /* A change beside a figure: which way it moved, and separately whether that is good. */
@@ -20,17 +20,28 @@ const trend = css({
20
20
  fontWeight: "medium",
21
21
  "&[data-tone=good]": { color: "accent.green" },
22
22
  "&[data-tone=bad]": { color: "accent.red" },
23
- "&[data-tone=neutral]": { color: "fg.muted" },
23
+ "&[data-tone=neutral]": { color: "fg.label" },
24
24
  "& > svg": { flexShrink: "0" },
25
25
  });
26
26
  const trendText = css({ minWidth: "0", overflow: "hidden", textOverflow: "ellipsis" });
27
27
  const TREND_ARROWS = { up: ArrowUpIcon, down: ArrowDownIcon, flat: ArrowRightIcon };
28
28
  export function Trend({ direction, tone = "neutral", arrow = true, children }) {
29
29
  const Arrow = TREND_ARROWS[direction];
30
- return (_jsxs("span", { className: trend, "data-tone": tone, "data-ciridae-ui": "", children: [arrow && _jsx(Arrow, { className: icon({ size: "compact" }), weight: "bold", "aria-hidden": "true" }), _jsx("span", { className: trendText, children: children })] }));
30
+ return (_jsxs("span", { className: trend, "data-tone": tone, "data-ciridae-ui": "", children: [arrow && _jsx(Arrow, { className: icon({ size: "compact" }), weight: "bold", "aria-hidden": "true" }), _jsx("span", { className: trendText, "data-trend-text": "", children: children })] }));
31
31
  }
32
- /* Sparkline: drawn into a 100x100 box that stretches to its container. */
33
- const plot = css({ position: "relative", color: "accent.blue" });
32
+ /*
33
+ * Sparkline: drawn into a 100x100 box that stretches to its plot. The plot fills the box unless
34
+ * `--sparkline-plot-width` and `--sparkline-plot-height` size it, at the box's foot and start, so
35
+ * the end point's ring has room above and after the line.
36
+ */
37
+ const plot = css({ position: "relative", color: "chart.trend" });
38
+ const plotArea = css({
39
+ position: "absolute",
40
+ insetInlineStart: "0",
41
+ bottom: "0",
42
+ width: "var(--sparkline-plot-width, 100%)",
43
+ height: "var(--sparkline-plot-height, 100%)",
44
+ });
34
45
  const svg = css({
35
46
  position: "absolute",
36
47
  inset: "0",
@@ -38,16 +49,31 @@ const svg = css({
38
49
  height: "100%",
39
50
  overflow: "visible",
40
51
  });
52
+ // The area under the line, clipped to it, so its gradient runs top to foot whatever the box.
53
+ const area = css({ position: "absolute", inset: "0", background: "token(gradients.chart.area)" });
54
+ // The ring is the tile's face, so the point reads as cut out of the line.
41
55
  const endPoint = css({
42
56
  position: "absolute",
43
57
  borderRadius: "round",
44
- background: "accent.blue",
58
+ background: "chart.trend",
45
59
  borderStyle: "solid",
46
- borderColor: "bg.card",
60
+ borderColor: "bg.surface",
47
61
  translate: "-50% -50%",
48
62
  });
49
- /** A run of values as a line filling its box; decorative, as the figure beside it says what it shows. */
63
+ // No run to draw: a dashed rule across the middle holds the line's place.
64
+ const noRun = css({
65
+ position: "absolute",
66
+ insetInline: "0",
67
+ top: "50%",
68
+ borderTop: "2px dashed token(colors.border.divider)",
69
+ });
70
+ /**
71
+ * A run of values as a line filling its box; decorative, as the figure beside it says what it
72
+ * shows. Under two values there is no line, and a dashed rule stands in for it.
73
+ */
50
74
  export function Sparkline({ values, low: ownLow, high: ownHigh, strokeWidth = 1.5, endPointSize = 6, className, ...props }) {
75
+ if (values.length < 2)
76
+ return (_jsx("div", { "aria-hidden": "true", ...props, className: cx(plot, className), "data-ciridae-ui": "", children: _jsx("span", { className: noRun }) }));
51
77
  const lowest = Math.min(...values);
52
78
  const high = ownHigh ?? Math.max(...values);
53
79
  const low = ownLow ?? lowest - (high - lowest) * 0.4;
@@ -56,31 +82,60 @@ export function Sparkline({ values, low: ownLow, high: ownHigh, strokeWidth = 1.
56
82
  const step = 100 / Math.max(values.length - 1, 1);
57
83
  const points = tops.map((top, index) => `${index * step},${top}`).join(" ");
58
84
  const lastTop = tops[tops.length - 1] ?? 100;
59
- return (_jsxs("div", { "aria-hidden": "true", ...props, className: cx(plot, className), "data-ciridae-ui": "", children: [_jsxs("svg", { className: svg, viewBox: "0 0 100 100", preserveAspectRatio: "none", children: [_jsx("polygon", { points: `0,100 ${points} 100,100`, fill: "currentColor", fillOpacity: 0.08 }), _jsx("polyline", { points: points, fill: "none", stroke: "currentColor", strokeWidth: strokeWidth, strokeLinejoin: "round", vectorEffect: "non-scaling-stroke" })] }), _jsx("span", { className: endPoint, style: {
60
- insetInlineStart: "100%",
61
- top: `${lastTop}%`,
62
- width: endPointSize,
63
- height: endPointSize,
64
- borderWidth: strokeWidth,
65
- } })] }));
85
+ const areaOutline = tops.map((top, index) => `${index * step}% ${top}%`).join(", ");
86
+ return (_jsx("div", { "aria-hidden": "true", ...props, className: cx(plot, className), "data-ciridae-ui": "", children: _jsxs("span", { className: plotArea, children: [_jsx("span", { className: area, style: { clipPath: `polygon(0% 100%, ${areaOutline}, 100% 100%)` } }), _jsx("svg", { className: svg, viewBox: "0 0 100 100", preserveAspectRatio: "none", children: _jsx("polyline", { points: points, fill: "none", stroke: "currentColor", strokeWidth: strokeWidth, strokeLinejoin: "round", vectorEffect: "non-scaling-stroke" }) }), _jsx("span", { className: endPoint, style: {
87
+ insetInlineStart: "100%",
88
+ top: `${lastTop}%`,
89
+ width: endPointSize,
90
+ height: endPointSize,
91
+ borderWidth: strokeWidth,
92
+ } })] }) }));
66
93
  }
67
- /* Metric card: a figure with its change, and its run beside it. */
68
- const metricCard = css(cardSurface, {
69
- display: "flex",
70
- gap: "layout.contentGap",
71
- padding: "panel.comfortable",
72
- color: "fg.primary",
73
- font: "inherit",
74
- textAlign: "start",
75
- textDecoration: "none",
76
- lineHeight: "tight",
77
- "&:is(button, a)": { cursor: "pointer", _hover: { borderColor: "border.glass" } },
78
- _focusVisible: { focusRing: "outer" },
79
- "& > [data-sparkline]": {
80
- width: "84px",
81
- height: "25px",
82
- flexShrink: "0",
83
- alignSelf: "flex-end",
94
+ /*
95
+ * Metric card: a figure with its change, and its run beside it. A tile in a row of them drops the
96
+ * card for a rule on its leading edge, or for nothing, and its label steps back to the label grey.
97
+ * The change's words are the label grey too, the kit's Stat tile: its arrow carries the tone.
98
+ * The run sits in the kit's 88x32 chart slot, its line in the slot's lower 84x25.
99
+ */
100
+ const metricCard = cva({
101
+ base: {
102
+ display: "flex",
103
+ gap: "layout.contentGap",
104
+ padding: "panel.comfortable",
105
+ color: "fg.primary",
106
+ font: "inherit",
107
+ textAlign: "start",
108
+ textDecoration: "none",
109
+ lineHeight: "tight",
110
+ "&:is(button, a)": { cursor: "pointer" },
111
+ _focusVisible: { focusRing: "outer" },
112
+ "& [data-trend-text]": { color: "fg.label" },
113
+ "& > [data-sparkline]": {
114
+ "--sparkline-plot-width": "token(sizes.sparkline.plotWidth)",
115
+ "--sparkline-plot-height": "token(sizes.sparkline.plotHeight)",
116
+ width: "sparkline.width",
117
+ height: "sparkline.height",
118
+ flexShrink: "0",
119
+ alignSelf: "flex-end",
120
+ },
121
+ },
122
+ variants: {
123
+ divider: {
124
+ card: { ...cardSurface, "&:is(button, a)": { _hover: { borderColor: "border.glass" } } },
125
+ left: {
126
+ minWidth: "0",
127
+ border: "0",
128
+ borderInlineStart: "1px solid token(colors.border.panel)",
129
+ background: "transparent",
130
+ "& [data-metric-label]": { color: "fg.label" },
131
+ },
132
+ none: {
133
+ minWidth: "0",
134
+ border: "0",
135
+ background: "transparent",
136
+ "& [data-metric-label]": { color: "fg.label" },
137
+ },
138
+ },
84
139
  },
85
140
  });
86
141
  const metricCopy = css({
@@ -97,7 +152,7 @@ const metricValue = css({
97
152
  lineHeight: "tight",
98
153
  fontVariantNumeric: "tabular-nums",
99
154
  });
100
- export function MetricCard({ label, value, change, sparkline, onSelect, href, render, className, ...props }) {
155
+ export function MetricCard({ label, value, change, sparkline, onSelect, href, divider = "card", render, className, ...props }) {
101
156
  return useRender({
102
157
  defaultTagName: href !== undefined ? "a" : onSelect !== undefined ? "button" : "div",
103
158
  render,
@@ -109,9 +164,9 @@ export function MetricCard({ label, value, change, sparkline, onSelect, href, re
109
164
  : {}),
110
165
  ...props,
111
166
  onClick: onSelect,
112
- className: cx(metricCard, className),
167
+ className: cx(metricCard({ divider }), className),
113
168
  "data-ciridae-ui": "",
114
- children: (_jsxs(_Fragment, { children: [_jsxs("span", { className: metricCopy, children: [_jsx("span", { className: metricLabel, children: label }), _jsx("span", { className: metricValue, children: value }), change && _jsx(Trend, { ...change })] }), sparkline && _jsx(Sparkline, { values: sparkline, "data-sparkline": "" })] })),
169
+ children: (_jsxs(_Fragment, { children: [_jsxs("span", { className: metricCopy, children: [_jsx("span", { className: metricLabel, "data-metric-label": "", children: label }), _jsx("span", { className: metricValue, children: value }), change && _jsx(Trend, { ...change })] }), sparkline && _jsx(Sparkline, { values: sparkline, "data-sparkline": "" })] })),
115
170
  },
116
171
  });
117
172
  }
@@ -14,4 +14,4 @@ export type StatusBannerProps = Omit<ComponentProps<"div">, "title"> & {
14
14
  /** The locale's "Dismiss" by default. */
15
15
  dismissLabel?: string;
16
16
  };
17
- export declare function StatusBanner({ title, description, tone, emphasis, action, onDismiss, dismissLabel, className, ...props }: StatusBannerProps): import("@types/react").JSX.Element;
17
+ export declare function StatusBanner({ title, description, tone, emphasis, action, onDismiss, dismissLabel, className, ...props }: StatusBannerProps): import("react").JSX.Element;
@@ -70,7 +70,7 @@ const bannerIcon = cva({
70
70
  neutral: { color: "fg.muted" },
71
71
  info: { color: "accent.blue" },
72
72
  success: { color: "accent.green" },
73
- warning: { color: "accent.yellow" },
73
+ warning: { color: "accent.yellowIcon" },
74
74
  danger: { color: "accent.red" },
75
75
  },
76
76
  },
@@ -21,12 +21,12 @@ export type StatusProps = ComponentProps<"span"> & {
21
21
  /** Shows only the icon, with the children as its tooltip and accessible name. */
22
22
  iconOnly?: boolean;
23
23
  };
24
- export declare function Status({ variant, iconOnly, className, style, ...props }: StatusProps): import("@types/react").JSX.Element;
24
+ export declare function Status({ variant, iconOnly, className, style, ...props }: StatusProps): import("react").JSX.Element;
25
25
  export type PendingTextProps = Omit<ComponentProps<"span">, "children"> & {
26
26
  children: ReactNode;
27
27
  /** `centered` holds the place of a page or panel that is still loading. */
28
28
  placement?: "inline" | "centered";
29
29
  };
30
30
  /** Work in progress, named: the spinner and a label such as "Signing in…", announced as a status. */
31
- export declare function PendingText({ children, placement, className, ...props }: PendingTextProps): import("@types/react").JSX.Element;
31
+ export declare function PendingText({ children, placement, className, ...props }: PendingTextProps): import("react").JSX.Element;
32
32
  export {};
@@ -14,4 +14,4 @@ export type StepContent = {
14
14
  export declare function Steps({ steps, notes, }: {
15
15
  steps: readonly StepContent[];
16
16
  notes?: readonly string[];
17
- }): import("@types/react").JSX.Element;
17
+ }): import("react").JSX.Element;
@@ -3,4 +3,4 @@ import type { ComponentProps } from "react";
3
3
  export type SwitchProps = Omit<ComponentProps<typeof BaseSwitch.Root>, "className"> & {
4
4
  className?: string;
5
5
  };
6
- export declare function Switch({ className, ...props }: SwitchProps): import("@types/react").JSX.Element;
6
+ export declare function Switch({ className, ...props }: SwitchProps): import("react").JSX.Element;
@@ -2,11 +2,11 @@ import { Tabs as BaseTabs } from "@base-ui/react/tabs";
2
2
  import type { ComponentProps, ReactNode } from "react";
3
3
  export declare function TabsRoot({ className, ...props }: Omit<ComponentProps<typeof BaseTabs.Root>, "className"> & {
4
4
  className?: string;
5
- }): import("@types/react").JSX.Element;
6
- export declare const TabsPanel: import("@types/react").ForwardRefExoticComponent<Omit<import("@base-ui/react").TabsPanelProps, "ref"> & import("@types/react").RefAttributes<HTMLDivElement>>;
5
+ }): import("react").JSX.Element;
6
+ export declare const TabsPanel: import("react").ForwardRefExoticComponent<Omit<import("@base-ui/react").TabsPanelProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
7
7
  export declare function TabsGroup({ border, className, ...props }: ComponentProps<"span"> & {
8
8
  border?: "control" | "glass";
9
- }): import("@types/react").JSX.Element;
9
+ }): import("react").JSX.Element;
10
10
  export declare function TabsList({ className, variant, overflow: ownOverflow, children, ...props }: Omit<ComponentProps<typeof BaseTabs.List>, "className"> & {
11
11
  className?: string;
12
12
  /**
@@ -19,7 +19,7 @@ export declare function TabsList({ className, variant, overflow: ownOverflow, ch
19
19
  * scrolls the row. `menu` in a `TabsBar`, `scroll` elsewhere.
20
20
  */
21
21
  overflow?: "menu" | "scroll";
22
- }): import("@types/react").JSX.Element;
22
+ }): import("react").JSX.Element;
23
23
  export type TabsTabProps = Omit<ComponentProps<typeof BaseTabs.Tab>, "className"> & {
24
24
  className?: string;
25
25
  /** Tint the tab icon bronze while inactive, as the Projects hub type tabs do. */
@@ -32,17 +32,17 @@ export type TabsTabProps = Omit<ComponentProps<typeof BaseTabs.Tab>, "className"
32
32
  /** Muted after the label, such as how many rows the tab holds. */
33
33
  count?: ReactNode;
34
34
  };
35
- export declare function TabsTab({ className, iconTone, href, render, count: tabCount, children, ...props }: TabsTabProps): import("@types/react").JSX.Element;
35
+ export declare function TabsTab({ className, iconTone, href, render, count: tabCount, children, ...props }: TabsTabProps): import("react").JSX.Element;
36
36
  /**
37
37
  * Wraps a page's `TabsBar` and the section below it, so the section can place its controls on the
38
38
  * tab row with `TabsBarActions` while keeping its own state.
39
39
  */
40
40
  export declare function TabsBarProvider({ children }: {
41
41
  children: ReactNode;
42
- }): import("@types/react").JSX.Element;
42
+ }): import("react").JSX.Element;
43
43
  /** Section tabs (a `TabsRoot`) with a slot at the end of the row for the open section's controls. */
44
- export declare function TabsBar({ className, children, ...props }: ComponentProps<"div">): import("@types/react").JSX.Element;
44
+ export declare function TabsBar({ className, children, ...props }: ComponentProps<"div">): import("react").JSX.Element;
45
45
  /** Renders the open section's controls at the end of the nearest `TabsBar` row. */
46
46
  export declare function TabsBarActions({ children }: {
47
47
  children: ReactNode;
48
- }): import("@types/react").ReactPortal | null;
48
+ }): import("react").ReactPortal | null;
@@ -22,14 +22,15 @@ const list = css({
22
22
  overflowX: "auto",
23
23
  scrollbarWidth: "none",
24
24
  });
25
- /** Finalization "Menu Tabs": tabs sit inside a bordered pill with a hairline inset. */
25
+ /** Finalization "View tabs": tabs sit inside a grey pill well with a hairline inset. */
26
26
  const containedList = css({
27
27
  width: "max-content",
28
28
  padding: "control.trackInset",
29
29
  border: "1px solid token(colors.border.control)",
30
30
  borderRadius: "pill",
31
- background: "bg.control",
32
- gap: "control.trackInset",
31
+ background: "bg.field",
32
+ // Raised over the base list's own gap, as the text list's is.
33
+ "&[data-variant=contained]": { gap: "control.trackInset" },
33
34
  });
34
35
  /* Text tabs: words only, the open one in the primary text, for a tray's or a sheet's filters. */
35
36
  const textList = css({ "&[data-variant=text]": { gap: "layout.contentGap" } });
@@ -48,8 +49,9 @@ const tab = css({
48
49
  alignItems: "center",
49
50
  justifyContent: "center",
50
51
  gap: "control.iconGap",
51
- height: "control.small",
52
+ height: "control.restingTab",
52
53
  paddingInline: "control.tabInline",
54
+ // The open tab's edge's own 1px, kept at rest too so a tab keeps its width as it opens.
53
55
  border: "1px solid transparent",
54
56
  borderRadius: "pill",
55
57
  background: "transparent",
@@ -62,19 +64,26 @@ const tab = css({
62
64
  cursor: "pointer",
63
65
  flexShrink: "0",
64
66
  "&[data-icon-tone=bronze] svg": { color: "accent.bronze" },
65
- _before: { display: "none" },
67
+ // The open tab is raised on the secondary button's face, with its gradient edge and soft shadow.
68
+ _before: { display: "none", background: "token(gradients.border.raised)" },
66
69
  _hover: {
67
- background: "bg.hover",
70
+ background: "bg.controlHover",
68
71
  color: "fg.primary",
69
72
  "& svg": { color: "inherit" },
70
- _before: { display: "block" },
71
73
  },
72
74
  "&[data-active]": {
73
- background: "bg.selected",
75
+ background: "token(gradients.raised)",
76
+ boxShadow: "soft",
74
77
  color: "fg.primary",
75
78
  "& svg": { color: "inherit" },
76
79
  _before: { display: "block" },
77
80
  },
81
+ // On a face, the words read in the primary ink in light, where only the open tab is raised, and
82
+ // the open tab stands 2px taller than the rest.
83
+ "[data-variant=plain] > &, [data-variant=contained] > &": {
84
+ _light: { color: "fg.primary" },
85
+ "&[data-active]": { height: "control.small", _phone: { height: "control.compact" } },
86
+ },
78
87
  // Words only: no face, no inset, and focus underlines the word rather than boxing it.
79
88
  "[data-variant=text] > &": {
80
89
  height: "auto",
@@ -83,8 +92,8 @@ const tab = css({
83
92
  border: "0",
84
93
  background: "transparent",
85
94
  _hover: { background: "transparent" },
86
- "&[data-active]": { background: "transparent" },
87
- // No glass edge either: the open word is the only mark.
95
+ "&[data-active]": { background: "transparent", boxShadow: "none" },
96
+ // No edge either: the open word is the only mark.
88
97
  "&::before, &:hover::before, &[data-active]::before": { display: "none" },
89
98
  _focusVisible: {
90
99
  boxShadow: "none",
@@ -103,7 +112,11 @@ const tab = css({
103
112
  marginBottom: "-1px",
104
113
  background: "transparent",
105
114
  _hover: { background: "transparent" },
106
- "&[data-active]": { background: "transparent", borderBottomColor: "fg.primary" },
115
+ "&[data-active]": {
116
+ background: "transparent",
117
+ boxShadow: "none",
118
+ borderBottomColor: "fg.primary",
119
+ },
107
120
  "&::before, &:hover::before, &[data-active]::before": { display: "none" },
108
121
  _phone: { height: "control.search", paddingInline: "none" },
109
122
  },
@@ -190,7 +203,7 @@ export function TabsList({ className, variant = "plain", overflow: ownOverflow,
190
203
  const overflow = ownOverflow ?? (inBar ? "menu" : "scroll");
191
204
  const { labels } = useCiridaeLocale();
192
205
  const { listRef, moreRef, overflowed, activeHidden, activate } = useOverflowedTabs(overflow === "menu", children);
193
- return (_jsxs(BaseTabs.List, { ...props, ref: listRef, className: cx(list, variant === "contained" && containedList, variant === "text" && textList, variant === "underline" && underlineList, className), "data-ciridae-ui": "", "data-variant": variant, children: [children, overflow === "menu" && overflowed.length > 0 && (_jsx(Menu, { align: "end", trigger: _jsx("button", { type: "button", ref: moreRef, className: tab, "aria-label": labels.common.moreTabs, "data-ciridae-ui": "", "data-edge": "glass", "data-active": activeHidden || undefined, children: _jsx(DotsThreeIcon, { className: icon({ size: "small" }), weight: "bold" }) }), items: overflowed.map((item) => ({
206
+ return (_jsxs(BaseTabs.List, { ...props, ref: listRef, className: cx(list, variant === "contained" && containedList, variant === "text" && textList, variant === "underline" && underlineList, className), "data-ciridae-ui": "", "data-variant": variant, children: [children, overflow === "menu" && overflowed.length > 0 && (_jsx(Menu, { align: "end", trigger: _jsx("button", { type: "button", ref: moreRef, className: tab, "aria-label": labels.common.moreTabs, "data-ciridae-ui": "", "data-edge": "gradient", "data-active": activeHidden || undefined, children: _jsx(DotsThreeIcon, { className: icon({ size: "small" }), weight: "bold" }) }), items: overflowed.map((item) => ({
194
207
  label: item.label,
195
208
  meta: item.count,
196
209
  onSelect: () => activate(item.index),
@@ -198,7 +211,7 @@ export function TabsList({ className, variant = "plain", overflow: ownOverflow,
198
211
  }
199
212
  export function TabsTab({ className, iconTone, href, render, count: tabCount, children, ...props }) {
200
213
  const link = href !== undefined || render !== undefined;
201
- return (_jsxs(BaseTabs.Tab, { ...props, render: render ?? (href !== undefined ? _jsx("a", { href: href }) : undefined), nativeButton: link ? false : props.nativeButton, className: cx(tab, className), "data-ciridae-ui": "", "data-edge": "glass", "data-icon-tone": iconTone, children: [children, tabCount !== undefined && tabCount !== null && (_jsx("span", { className: count, "data-tab-count": "", children: tabCount }))] }));
214
+ return (_jsxs(BaseTabs.Tab, { ...props, render: render ?? (href !== undefined ? _jsx("a", { href: href }) : undefined), nativeButton: link ? false : props.nativeButton, className: cx(tab, className), "data-ciridae-ui": "", "data-edge": "gradient", "data-icon-tone": iconTone, children: [children, tabCount !== undefined && tabCount !== null && (_jsx("span", { className: count, "data-tab-count": "", children: tabCount }))] }));
202
215
  }
203
216
  /*
204
217
  * A page's tabs share one row with the open section's controls: tabs that do not fit go into the
@@ -40,7 +40,7 @@ export type UseThemeCustomizationOptions<Value extends ThemeCustomization> = {
40
40
  */
41
41
  export declare function useThemeCustomization<Value extends ThemeCustomization>({ defaultValue, fonts, persistKey, parse, }: UseThemeCustomizationOptions<Value>): {
42
42
  value: Value;
43
- setValue: import("@types/react").Dispatch<import("@types/react").SetStateAction<Value>>;
43
+ setValue: import("react").Dispatch<import("react").SetStateAction<Value>>;
44
44
  reset: () => void;
45
45
  theme: Pick<CiridaeTheme, "fonts" | "palette">;
46
46
  };
@@ -50,4 +50,4 @@ export type ThemeCustomizerProps<Value extends ThemeCustomization> = Omit<Compon
50
50
  fonts: ThemeFontOptions;
51
51
  labels?: Partial<CiridaeLabels["themeCustomizer"]>;
52
52
  };
53
- export declare function ThemeCustomizer<Value extends ThemeCustomization>({ value, onValueChange, fonts, labels: ownLabels, className, ...props }: ThemeCustomizerProps<Value>): import("@types/react").JSX.Element;
53
+ export declare function ThemeCustomizer<Value extends ThemeCustomization>({ value, onValueChange, fonts, labels: ownLabels, className, ...props }: ThemeCustomizerProps<Value>): import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ /** Sets the color theme the `ThemeProvider` keeps: light, dark, or the operating system's. */
2
+ export declare function ThemeToggle({ className }: {
3
+ className?: string;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { CircleHalfIcon, MoonIcon, SunIcon } from "@phosphor-icons/react";
3
+ import { css, cx } from "#primitives/css";
4
+ import { useColorTheme } from "./color-theme.js";
5
+ import { faceEdge } from "./gradient-edge.js";
6
+ import { icon } from "./icon.js";
7
+ import { useCiridaeLocale } from "./locale.js";
8
+ /*
9
+ * Light, dark or the system's theme, as three icon segments in a pale track: the chosen one is
10
+ * raised on the secondary button's face, its icon in the primary ink, the others a step quieter.
11
+ */
12
+ const track = css({
13
+ display: "inline-flex",
14
+ alignItems: "center",
15
+ gap: "control.trackInset",
16
+ padding: "control.trackInset",
17
+ // The design lays the track's edge over its inset, and rounds it to its options' corners.
18
+ border: "0",
19
+ borderRadius: "calc(token(radii.inset) + token(spacing.control.trackInset))",
20
+ background: "token(gradients.panel)",
21
+ });
22
+ const option = css({
23
+ display: "inline-grid",
24
+ placeItems: "center",
25
+ width: "control.small",
26
+ height: "calc(token(sizes.control.small) - 2 * token(spacing.control.trackInset))",
27
+ padding: "none",
28
+ border: "0",
29
+ borderRadius: "inset",
30
+ background: "transparent",
31
+ color: "fg.secondary",
32
+ cursor: "pointer",
33
+ transitionProperty: "background, color",
34
+ transitionDuration: "fast",
35
+ _hover: { color: "fg.primary" },
36
+ _focusVisible: { focusRing: "outer" },
37
+ _before: { display: "none", background: "token(gradients.border.raised)" },
38
+ "&[aria-pressed=true]": {
39
+ background: "token(gradients.raised)",
40
+ color: "fg.primary",
41
+ _before: { display: "block" },
42
+ },
43
+ });
44
+ /** Sets the color theme the `ThemeProvider` keeps: light, dark, or the operating system's. */
45
+ export function ThemeToggle({ className }) {
46
+ const { preference, setPreference } = useColorTheme();
47
+ const { labels } = useCiridaeLocale();
48
+ const trackEdge = faceEdge("raised");
49
+ const choices = [
50
+ {
51
+ value: "light",
52
+ label: labels.themeCustomizer.light,
53
+ glyph: _jsx(SunIcon, { className: icon({ size: "small" }) }),
54
+ },
55
+ {
56
+ value: "dark",
57
+ label: labels.themeCustomizer.dark,
58
+ glyph: _jsx(MoonIcon, { className: icon({ size: "small" }) }),
59
+ },
60
+ {
61
+ value: "system",
62
+ label: labels.themeCustomizer.system,
63
+ glyph: _jsx(CircleHalfIcon, { className: icon({ size: "small" }) }),
64
+ },
65
+ ];
66
+ return (_jsx("div", { role: "group", "aria-label": labels.themeCustomizer.colorTheme, className: cx(track, trackEdge.className, className), "data-ciridae-ui": "", "data-edge": trackEdge["data-edge"], children: choices.map((choice) => (_jsx("button", { type: "button", "aria-label": choice.label, "aria-pressed": preference === choice.value, className: option, "data-ciridae-ui": "", "data-edge": "gradient", onClick: () => setPreference(choice.value), children: choice.glyph }, choice.value))) }));
67
+ }
@@ -2,7 +2,7 @@ import { toast, type ToasterProps } from "sonner";
2
2
  import type { ComponentProps, ReactNode } from "react";
3
3
  export { toast };
4
4
  /** The toast stack, in the kit's look: mount one at the app's root. */
5
- export declare function Toaster(props: ToasterProps): import("@types/react").JSX.Element;
5
+ export declare function Toaster(props: ToasterProps): import("react").JSX.Element;
6
6
  export type ToastVariant = "success" | "progress" | "info" | "warning" | "error";
7
7
  export type ToastOptions = {
8
8
  title: ReactNode;
@@ -11,11 +11,18 @@ export type ToastOptions = {
11
11
  variant?: ToastVariant;
12
12
  /** Milliseconds it stays; `0` keeps it until dismissed. An error stays by default. */
13
13
  timeout?: number;
14
- /** One text button, such as Undo; its children are the label. */
14
+ /**
15
+ * One small secondary button, such as Undo; its children are the label. It closes the toast, and
16
+ * takes the close button's place.
17
+ */
15
18
  actionProps?: Pick<ComponentProps<"button">, "children" | "onClick">;
19
+ /** Replaces the toast already shown with this id, such as a progress toast moving along. */
20
+ id?: string | number;
21
+ /** How far a `progress` toast is, 0 to 100, shown as a track and a percentage after its message. */
22
+ percent?: number;
16
23
  };
17
24
  /** Raises a toast with the kit's options, returning its id. */
18
- declare function addToast({ title: message, description: detail, variant, timeout, actionProps, }: ToastOptions): string | number;
25
+ declare function addToast({ title: ownMessage, description: detail, variant, timeout, actionProps, id, percent, }: ToastOptions): string | number;
19
26
  /** The kit's toast calls: `add` raises one and returns its id, `close` dismisses it. */
20
27
  export declare function useToast(): {
21
28
  add: typeof addToast;