@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
@@ -1,30 +1,67 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CaretLeftIcon, CaretRightIcon } from "@phosphor-icons/react";
2
3
  import { css, cva, cx } from "#primitives/css";
3
- import { Button } from "./button.js";
4
+ import { Button, IconButton } from "./button.js";
5
+ import { icon } from "./icon.js";
4
6
  import { Heading } from "./layout.js";
5
7
  import { useCiridaeLocale } from "./locale.js";
6
- export function Pagination({ page, pages, onPageChange, labels: ownLabels, className, ...props }) {
8
+ import { cardSurface } from "./panel.js";
9
+ /*
10
+ * The bar under a table, the kit's Pagination. Full: the page size at the start, then the summary
11
+ * and the pager at the end, inset 12px. Simple, with no page size: the summary at the start, the
12
+ * pager at the end, flush.
13
+ */
14
+ const pagination = css({
15
+ display: "flex",
16
+ alignItems: "center",
17
+ justifyContent: "space-between",
18
+ gap: "layout.controlGap",
19
+ minHeight: "control.row",
20
+ paddingInline: "panel.default",
21
+ lineHeight: "tight",
22
+ "&[data-type=simple]": { paddingInline: "0" },
23
+ });
24
+ const paginationEnd = css({
25
+ display: "flex",
26
+ alignItems: "center",
27
+ gap: "layout.clusterGap",
28
+ marginInlineStart: "auto",
29
+ });
30
+ const paginationSummary = css({
31
+ color: "fg.secondary",
32
+ fontSize: "code",
33
+ fontWeight: "medium",
34
+ letterSpacing: "compact",
35
+ fontVariantNumeric: "tabular-nums",
36
+ });
37
+ // Simple: the summary and the pager are the bar's own ends.
38
+ const summaryAndPagerAsBarEnds = css({ display: "contents" });
39
+ const pager = css({ display: "flex", alignItems: "center", gap: "layout.tightGap" });
40
+ const pagerAlone = css({ marginInlineStart: "auto" });
41
+ export function Pagination({ page, pages, onPageChange, pageSizeSelect, summary, numbered = false, labels: ownLabels, className, ...props }) {
7
42
  const locale = useCiridaeLocale();
8
43
  const labels = { ...locale.labels.pagination, ...ownLabels };
9
- const visible = Array.from({ length: pages }, (_, index) => index + 1);
10
- return (_jsxs("nav", { "aria-label": labels.label, ...props, className: cx(css({ display: "flex", gap: "layout.tightGap" }), className), "data-ciridae-ui": "", children: [_jsx(Button, { variant: "ghost", disabled: pages === 0 || page <= 1, onClick: () => onPageChange(Math.max(1, page - 1)), children: labels.previous }), visible.map((value) => (_jsx(Button, { variant: value === page ? "primary" : "ghost", "aria-current": value === page ? "page" : undefined, onClick: () => onPageChange(value), children: locale.formatNumber(value) }, value))), _jsx(Button, { variant: "ghost", disabled: pages === 0 || page >= pages, onClick: () => onPageChange(Math.min(pages, page + 1)), children: labels.next })] }));
44
+ const Previous = locale.dir === "rtl" ? CaretRightIcon : CaretLeftIcon;
45
+ const Next = locale.dir === "rtl" ? CaretLeftIcon : CaretRightIcon;
46
+ return (_jsxs("nav", { "aria-label": labels.label, ...props, className: cx(pagination, className), "data-ciridae-ui": "", "data-type": pageSizeSelect ? "full" : "simple", children: [pageSizeSelect, _jsxs("div", { className: pageSizeSelect ? paginationEnd : summaryAndPagerAsBarEnds, children: [summary && _jsx("span", { className: paginationSummary, children: summary }), _jsxs("div", { className: cx(pager, !summary && pagerAlone), children: [_jsx(IconButton, { "aria-label": labels.previous, size: "medium", disabled: pages === 0 || page <= 1, onClick: () => onPageChange(Math.max(1, page - 1)), children: _jsx(Previous, { className: icon({ size: "small" }) }) }), numbered &&
47
+ Array.from({ length: pages }, (_, index) => index + 1).map((value) => (_jsx(Button, { variant: value === page ? "primary" : "ghost", "aria-current": value === page ? "page" : undefined, onClick: () => onPageChange(value), children: locale.formatNumber(value) }, value))), _jsx(IconButton, { "aria-label": labels.next, size: "medium", disabled: pages === 0 || page >= pages, onClick: () => onPageChange(Math.min(pages, page + 1)), children: _jsx(Next, { className: icon({ size: "small" }) }) })] })] })] }));
11
48
  }
12
49
  const emptyState = cva({
13
50
  base: { display: "grid", placeItems: "center", textAlign: "center" },
14
51
  variants: {
15
52
  variant: {
16
- // A page or panel with nothing in it yet: a dashed frame with room for a heading.
53
+ // A page or panel with nothing in it yet: no frame, with room around it.
17
54
  block: {
18
- minHeight: "emptyState.minimum",
19
- padding: "panel.roomy",
20
- border: "1px dashed token(colors.border.control)",
21
- borderRadius: "inset",
55
+ justifyItems: "center",
56
+ gap: "layout.clusterGap",
57
+ paddingBlock: "emptyState.pageBlock",
58
+ paddingInline: "panel.roomy",
22
59
  },
23
- // Inside a table or a card that frames it already: the icon in a ring, no frame of its own.
60
+ // Inside a table or a card that frames it already: tighter, its copy wrapping to the card.
24
61
  bare: {
25
62
  justifyItems: "center",
26
- gap: "layout.clusterGap",
27
- paddingBlock: "panel.roomy",
63
+ gap: "layout.contentGap",
64
+ paddingBlock: "emptyState.compactBlock",
28
65
  paddingInline: "panel.comfortable",
29
66
  },
30
67
  // A list or section with nothing to show: one muted line, no frame.
@@ -45,31 +82,59 @@ const emptyRing = css({
45
82
  height: "brand.logo",
46
83
  border: "1px solid token(colors.border.control)",
47
84
  borderRadius: "round",
48
- background: "bg.field",
85
+ // The field's grey well in light; in dark the deep grey a disabled field wears, not the white
86
+ // wash of a dark field, so the ring sits below the page rather than lit on it.
87
+ background: "bg.fieldDisabled",
88
+ _light: { background: "bg.field" },
49
89
  color: "fg.muted",
50
90
  fontSize: "icon.small",
51
91
  });
52
92
  const emptyCopy = css({ display: "grid", gap: "control.iconGap", maxWidth: "card.centered" });
93
+ // The title in the primary ink, whatever the table or card round it sets as its text colour.
94
+ const emptyTitle = css({ color: "fg.primary", lineHeight: "tight" });
53
95
  const emptyDescription = css({
54
96
  margin: "none",
55
97
  color: "fg.muted",
98
+ _light: { color: "fg.secondary" },
56
99
  fontSize: "code",
57
100
  fontWeight: "medium",
58
101
  letterSpacing: "compact",
59
- lineHeight: "body",
102
+ // A page's one line of help sits on the title's tight line; a card's wraps.
103
+ lineHeight: "tight",
104
+ "[data-variant=bare] &": { lineHeight: "body" },
60
105
  });
61
106
  const emptyActions = css({
62
107
  display: "flex",
63
108
  flexWrap: "wrap",
64
109
  justifyContent: "center",
65
110
  gap: "layout.controlGap",
111
+ paddingBlock: "layout.tightGap",
112
+ "[data-variant=bare] > &": { paddingBlock: "none" },
66
113
  });
67
- export function EmptyState({ icon, title, description, action, variant = "block", className, ...props }) {
114
+ export function EmptyState({ icon, title, description, action, secondaryAction, variant = "block", className, ...props }) {
68
115
  if (variant === "inline") {
69
116
  return (_jsxs("section", { ...props, "data-ciridae-ui": "", className: cx(emptyState({ variant }), className), children: [_jsxs("span", { className: css({ display: "inline-flex", alignItems: "center", gap: "control.iconGap" }), children: [icon, title] }), description && _jsx("span", { children: description }), action] }));
70
117
  }
71
- if (variant === "bare") {
72
- return (_jsxs("section", { ...props, "data-ciridae-ui": "", className: cx(emptyState({ variant }), className), children: [icon && (_jsx("span", { className: emptyRing, "aria-hidden": "true", children: icon })), _jsxs("div", { className: emptyCopy, children: [_jsx(Heading, { level: 2, size: "small", children: title }), description && _jsx("p", { className: emptyDescription, children: description })] }), action && _jsx("div", { className: emptyActions, children: action })] }));
73
- }
74
- return (_jsx("section", { ...props, "data-ciridae-ui": "", className: cx(emptyState({ variant }), className), children: _jsxs("div", { className: css({ display: "grid", justifyItems: "center", gap: "layout.contentGap" }), children: [icon, _jsx(Heading, { level: 2, children: title }), description && _jsx("p", { className: css({ margin: "none", color: "fg.muted" }), children: description }), action] }) }));
118
+ return (_jsxs("section", { ...props, "data-ciridae-ui": "", "data-variant": variant, className: cx(emptyState({ variant }), className), children: [icon && (_jsx("span", { className: emptyRing, "aria-hidden": "true", children: icon })), _jsxs("div", { className: emptyCopy, children: [_jsx(Heading, { level: 2, size: "small", className: emptyTitle, children: title }), description && _jsx("p", { className: emptyDescription, children: description })] }), (action || secondaryAction) && (_jsxs("div", { className: emptyActions, children: [secondaryAction, action] }))] }));
119
+ }
120
+ // A dashboard tile with nothing to count, worn like the stat tile it stands in for.
121
+ const emptyTile = css(cardSurface, {
122
+ display: "grid",
123
+ alignContent: "start",
124
+ justifyItems: "start",
125
+ gap: "layout.controlGap",
126
+ minHeight: "tile.minimum",
127
+ paddingBlock: "tile.block",
128
+ paddingInline: "tile.inline",
129
+ fontSize: "code",
130
+ fontWeight: "medium",
131
+ letterSpacing: "compact",
132
+ lineHeight: "tight",
133
+ });
134
+ const emptyTileLabel = css({ color: "fg.label" });
135
+ const emptyTileValue = css({ color: "fg.primary", fontSize: "body" });
136
+ const emptyTileNote = css({ color: "fg.subtle" });
137
+ /** A stat tile with no figure: its label, a dash in the figure's place, and why. */
138
+ export function EmptyTile({ label, note, className, ...props }) {
139
+ return (_jsxs("div", { ...props, className: cx(emptyTile, className), "data-ciridae-ui": "", children: [_jsx("span", { className: emptyTileLabel, children: label }), _jsx("span", { className: emptyTileValue, children: "\u2014" }), note && _jsx("span", { className: emptyTileNote, children: note })] }));
75
140
  }
@@ -44,4 +44,4 @@ export type NotificationTrayProps = {
44
44
  onOpenChange?: (open: boolean) => void;
45
45
  };
46
46
  export type NotificationLabels = CiridaeLabels["notifications"];
47
- export declare function NotificationTray({ trigger, notifications, onOpen, onMarkAllRead, footerAction, placement, now, labels: ownLabels, open: ownOpen, onOpenChange, }: NotificationTrayProps): import("@types/react").JSX.Element;
47
+ export declare function NotificationTray({ trigger, notifications, onOpen, onMarkAllRead, footerAction, placement, now, labels: ownLabels, open: ownOpen, onOpenChange, }: NotificationTrayProps): import("react").JSX.Element;
@@ -45,12 +45,13 @@ const popup = css({
45
45
  maxWidth: "calc(100vw - token(spacing.layout.pageGap) * 2)",
46
46
  padding: "none",
47
47
  overflow: "hidden",
48
- border: "1px solid token(colors.border.control)",
48
+ border: "1px solid token(colors.border.divider)",
49
49
  borderRadius: "action",
50
- background: "bg.card",
50
+ background: "bg.popover",
51
+ backdropFilter: "blur(token(blurs.popover))",
51
52
  color: "fg.primary",
52
53
  textStyle: "body",
53
- boxShadow: "card",
54
+ boxShadow: "soft",
54
55
  outline: "none",
55
56
  });
56
57
  const header = css({
@@ -66,7 +67,7 @@ const caughtUp = css({ color: "fg.muted", fontSize: "caption", fontWeight: "medi
66
67
  const filters = css({
67
68
  paddingInline: "panel.comfortable",
68
69
  paddingBottom: "layout.tightGap",
69
- borderBottom: "1px solid token(colors.border.control)",
70
+ borderBottom: "1px solid token(colors.border.divider)",
70
71
  });
71
72
  const list = css({
72
73
  display: "grid",
@@ -53,7 +53,7 @@ export type DialogProps = Omit<ComponentProps<typeof BaseDialog.Root>, "children
53
53
  content: ReactNode;
54
54
  };
55
55
  };
56
- export declare function Dialog({ trigger, finalFocus, title, titleVisibility, icon: titleIcon, description, children, actions, leadingActions, kind, dismiss, closable, pending, dirty, closeLabel: ownCloseLabel, size, holdHeight, aside, onOpenChange, ...rootProps }: DialogProps): import("@types/react").JSX.Element;
56
+ export declare function Dialog({ trigger, finalFocus, title, titleVisibility, icon: titleIcon, description, children, actions, leadingActions, kind, dismiss, closable, pending, dirty, closeLabel: ownCloseLabel, size, holdHeight, aside, onOpenChange, ...rootProps }: DialogProps): import("react").JSX.Element;
57
57
  export type AlertDialogProps = Omit<ComponentProps<typeof BaseAlertDialog.Root>, "children" | "actionsRef"> & {
58
58
  /** Omit for a dialog opened only through controlled `open`. */
59
59
  trigger?: ReactElement;
@@ -77,7 +77,7 @@ export type AlertDialogProps = Omit<ComponentProps<typeof BaseAlertDialog.Root>,
77
77
  * closes it, which Base UI keeps as the cancelling path, except while an
78
78
  * async confirmation is pending.
79
79
  */
80
- export declare function AlertDialog({ trigger, title, children, confirmLabel, cancelLabel, onConfirm, variant, onOpenChange, ...rootProps }: AlertDialogProps): import("@types/react").JSX.Element;
80
+ export declare function AlertDialog({ trigger, title, children, confirmLabel, cancelLabel, onConfirm, variant, onOpenChange, ...rootProps }: AlertDialogProps): import("react").JSX.Element;
81
81
  export type PopoverProps = Omit<ComponentProps<typeof BasePopover.Root>, "children"> & {
82
82
  /** The button that opens it. Leave it out and pass `anchor` to open it from elsewhere, such as a menu item. */
83
83
  trigger?: ReactElement;
@@ -99,9 +99,11 @@ export type PopoverProps = Omit<ComponentProps<typeof BasePopover.Root>, "childr
99
99
  */
100
100
  openOnHover?: boolean;
101
101
  };
102
- export declare function Popover({ trigger, anchor, children, density, width, align, openOnHover, ...rootProps }: PopoverProps): import("@types/react").JSX.Element;
102
+ export declare function Popover({ trigger, anchor, children, density, width, align, openOnHover, ...rootProps }: PopoverProps): import("react").JSX.Element;
103
103
  export type TooltipProps = Omit<ComponentProps<typeof BaseTooltip.Root>, "children"> & {
104
104
  children: ReactElement;
105
105
  content: ReactNode;
106
+ /** A count or shortcut after the content, quieter than it. */
107
+ meta?: ReactNode;
106
108
  };
107
- export declare function Tooltip({ children, content, ...rootProps }: TooltipProps): import("@types/react").JSX.Element;
109
+ export declare function Tooltip({ children, content, meta, ...rootProps }: TooltipProps): import("react").JSX.Element;
@@ -6,8 +6,9 @@ import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
6
6
  import { XIcon } from "@phosphor-icons/react";
7
7
  import { useCallback, useRef, useState, } from "react";
8
8
  import { css, cx } from "#primitives/css";
9
- import { Button, IconButton } from "./button.js";
9
+ import { Button, ButtonSizeContext, IconButton } from "./button.js";
10
10
  import { DialogHeightResetContext } from "./dialog-height-context.js";
11
+ import { glassMenuSurface } from "./glass-menu.js";
11
12
  import { HotkeyLayer } from "./hotkeys.js";
12
13
  import { icon } from "./icon.js";
13
14
  import { heading } from "./layout.js";
@@ -15,18 +16,11 @@ import { useCiridaeLocale } from "./locale.js";
15
16
  /** A positioned popup carries its own stacking order; a positioner-anchored one gets it there. */
16
17
  const positioner = css({ zIndex: "popover" });
17
18
  const tooltipPositioner = css({ zIndex: "tooltip" });
18
- const popupStyle = css.raw({
19
+ // A popover is the menus' glass sheet, padded for a small form. A popup takes focus when it
20
+ // opens or when its focused content unmounts (a wizard changing step); the sheet draws no ring.
21
+ const popupStyle = css.raw(glassMenuSurface, {
19
22
  maxWidth: "overlay.dialog",
20
23
  padding: "panel.comfortable",
21
- border: "1px solid token(colors.border.control)",
22
- borderRadius: "inset",
23
- backgroundColor: "bg.card",
24
- color: "fg.primary",
25
- textStyle: "body",
26
- boxShadow: "card",
27
- // A popup takes focus when it opens or when its focused content unmounts (a wizard changing
28
- // step); it is a container, not a control, so it draws no ring.
29
- outline: "none",
30
24
  });
31
25
  const popup = css(popupStyle);
32
26
  // The title and footer stay put; a long body scrolls between them.
@@ -38,17 +32,27 @@ const dialogLayout = css.raw({
38
32
  // A dialog's own inset, not the page margin, so page density changes leave it alone.
39
33
  padding: "panel.comfortable",
40
34
  });
41
- const dialogPopup = css.raw(popupStyle, dialogLayout, {
35
+ /*
36
+ * A dialog is a glass shell, 4px round its sheet, holding the sheet itself. `--dialog-sheet` is
37
+ * the sheet's width; the shell adds its inset and edge. Dark blurs the shell and light the sheet.
38
+ */
39
+ const dialogShell = css.raw({
40
+ "--dialog-sheet": "token(sizes.overlay.dialog)",
42
41
  zIndex: "dialog",
43
42
  position: "fixed",
44
43
  top: "50%",
45
44
  left: "50%",
45
+ display: "grid",
46
+ gridTemplateRows: "minmax(0, 1fr)",
46
47
  width: "calc(100vw - token(spacing.layout.pageGap) * 2)",
48
+ maxWidth: "calc(var(--dialog-sheet) + 2 * (token(spacing.layout.tightGap) + token(sizes.border.hairline)))",
47
49
  maxHeight: "calc(100dvh - token(spacing.layout.pageGap) * 2)",
48
- border: "1px solid token(colors.border.card)",
49
- borderRadius: "inset",
50
- background: "bg.surface",
51
- boxShadow: "panel",
50
+ padding: "layout.tightGap",
51
+ border: "1px solid token(colors.border.control)",
52
+ borderRadius: "shell",
53
+ background: "bg.modalShell",
54
+ backdropFilter: "blur(token(blurs.modalShell))",
55
+ outline: "none",
52
56
  transform: "translate(-50%, -50%)",
53
57
  transitionProperty: "opacity, transform",
54
58
  transitionDuration: "fast",
@@ -58,6 +62,17 @@ const dialogPopup = css.raw(popupStyle, dialogLayout, {
58
62
  transform: "translate(-50%, calc(-50% + token(spacing.control.block)))",
59
63
  },
60
64
  });
65
+ const dialogSheetStyle = css.raw(dialogLayout, {
66
+ minHeight: "0",
67
+ border: "1px solid token(colors.border.control)",
68
+ borderRadius: "inset",
69
+ background: "bg.modalSheet",
70
+ backdropFilter: "blur(token(blurs.modalSheet))",
71
+ boxShadow: "soft",
72
+ color: "fg.primary",
73
+ textStyle: "body",
74
+ });
75
+ const dialogSheet = css(dialogSheetStyle);
61
76
  const visuallyHidden = css({ srOnly: true });
62
77
  const backdrop = css({
63
78
  position: "fixed",
@@ -77,8 +92,10 @@ const dialogTitle = cx(heading(), css({ display: "flex", alignItems: "center", g
77
92
  const dialogDescription = css({
78
93
  margin: "none",
79
94
  color: "fg.muted",
95
+ _light: { color: "fg.secondary" },
80
96
  fontSize: "body",
81
- lineHeight: "compact",
97
+ fontWeight: "medium",
98
+ lineHeight: "body",
82
99
  });
83
100
  // Bleeds past its edges by a control's focus ring, so scrolling does not clip the ring.
84
101
  const dialogBody = css({
@@ -98,16 +115,18 @@ const dialogLeadingActions = css({
98
115
  gap: "layout.controlGap",
99
116
  marginInlineEnd: "auto",
100
117
  });
118
+ // Under a divider, its buttons at the default height and close together.
101
119
  const dialogFooter = css({
102
120
  display: "flex",
103
121
  justifyContent: "flex-end",
104
- gap: "layout.controlGap",
105
- paddingTop: "layout.controlGap",
122
+ gap: "layout.tightGap",
123
+ paddingTop: "layout.clusterGap",
124
+ borderTop: "1px solid token(colors.border.divider)",
106
125
  });
107
- const narrowDialogPopup = css.raw({ maxWidth: "card.centeredForm" });
108
- const wideDialogPopup = css.raw({ maxWidth: "overlay.dialogWide" });
126
+ const narrowDialogShell = css.raw({ "--dialog-sheet": "token(sizes.card.centeredForm)" });
127
+ const wideDialogShell = css.raw({ "--dialog-sheet": "token(sizes.overlay.dialogWide)" });
109
128
  // Beside the dialog's own column, flush to its edges; below it on a narrow screen.
110
- const splitDialogPopup = css.raw({
129
+ const splitDialogSheet = css.raw({
111
130
  padding: "none",
112
131
  gap: "none",
113
132
  gridTemplateRows: "auto auto",
@@ -163,13 +182,13 @@ export function Dialog({ trigger, finalFocus, title, titleVisibility = "visible"
163
182
  const dismissInHeader = dismiss === "header";
164
183
  const showCancel = !dismissInHeader;
165
184
  const dismissalDisabled = !closable || pending;
166
- const dialogContent = (_jsxs(_Fragment, { children: [_jsxs("div", { className: dismissInHeader ? dialogHeaderRow : undefined, children: [_jsxs("div", { className: dialogHeader, children: [titleVisibility === "hidden" ? (_jsx(BaseDialog.Title, { className: visuallyHidden, children: title })) : (_jsxs(BaseDialog.Title, { className: dialogTitle, children: [titleIcon, title] })), description && (_jsx(BaseDialog.Description, { className: dialogDescription, children: description }))] }), dismissInHeader && closable && (_jsx(BaseDialog.Close, { disabled: pending, render: _jsx(IconButton, { "aria-label": closeLabel, size: "compact", variant: "ghost" }), children: _jsx(XIcon, { className: icon({ size: "small" }) }) }))] }), _jsx("div", { className: dialogBody, children: _jsx(DialogHeightResetContext, { value: holdHeight ? resetHeight : null, children: children }) }), ((showCancel && closable) || actions || leadingActions) && (_jsxs("div", { className: dialogFooter, children: [leadingActions && _jsx("div", { className: dialogLeadingActions, children: leadingActions }), showCancel && closable && (_jsx(BaseDialog.Close, { disabled: pending, render: _jsx(Button, { variant: "secondary" }), children: dismissInHeader ? labels.common.cancel : closeLabel })), actions] }))] }));
185
+ const dialogContent = (_jsxs(_Fragment, { children: [_jsxs("div", { className: dismissInHeader ? dialogHeaderRow : undefined, children: [_jsxs("div", { className: dialogHeader, children: [titleVisibility === "hidden" ? (_jsx(BaseDialog.Title, { className: visuallyHidden, children: title })) : (_jsxs(BaseDialog.Title, { className: dialogTitle, children: [titleIcon, title] })), description && (_jsx(BaseDialog.Description, { className: dialogDescription, children: description }))] }), dismissInHeader && closable && (_jsx(BaseDialog.Close, { disabled: pending, render: _jsx(IconButton, { "aria-label": closeLabel, size: "compact", variant: "ghost" }), children: _jsx(XIcon, { className: icon({ size: "small" }) }) }))] }), _jsx("div", { className: dialogBody, children: _jsx(DialogHeightResetContext, { value: holdHeight ? resetHeight : null, children: children }) }), ((showCancel && closable) || actions || leadingActions) && (_jsx("div", { className: dialogFooter, children: _jsxs(ButtonSizeContext, { value: "medium", children: [leadingActions && _jsx("div", { className: dialogLeadingActions, children: leadingActions }), showCancel && closable && (_jsx(BaseDialog.Close, { disabled: pending, render: _jsx(Button, { variant: "secondary" }), children: dismissInHeader ? labels.common.cancel : closeLabel })), actions] }) }))] }));
167
186
  return (_jsxs(BaseDialog.Root, { ...rootProps, onOpenChange: (open, details) => {
168
187
  if (!open && (dismissalDisabled || (dirty && details.reason !== "close-press"))) {
169
188
  return details.cancel();
170
189
  }
171
190
  onOpenChange?.(open, details);
172
- }, children: [trigger && _jsx(BaseDialog.Trigger, { render: trigger }), _jsx(BaseDialog.Portal, { children: _jsxs(HotkeyLayer, { children: [_jsx(BaseDialog.Backdrop, { "data-ciridae-ui": "", className: backdrop }), _jsx(BaseDialog.Popup, { finalFocus: finalFocus, ref: holdHeight ? holdTallestHeight : undefined, className: css(dialogPopup, size === "narrow" && aside === undefined && narrowDialogPopup, (size === "wide" || aside !== undefined) && wideDialogPopup, aside !== undefined && splitDialogPopup), "data-ciridae-ui": "", children: aside ? (_jsxs(_Fragment, { children: [_jsx("div", { className: splitDialogMain, children: dialogContent }), _jsx("aside", { className: splitDialogAside, "aria-label": aside.label, children: aside.content })] })) : (dialogContent) })] }) })] }));
191
+ }, children: [trigger && _jsx(BaseDialog.Trigger, { render: trigger }), _jsx(BaseDialog.Portal, { children: _jsxs(HotkeyLayer, { children: [_jsx(BaseDialog.Backdrop, { "data-ciridae-ui": "", className: backdrop }), _jsx(BaseDialog.Popup, { finalFocus: finalFocus, ref: holdHeight ? holdTallestHeight : undefined, className: css(dialogShell, size === "narrow" && aside === undefined && narrowDialogShell, (size === "wide" || aside !== undefined) && wideDialogShell), "data-ciridae-ui": "", children: aside ? (_jsxs("div", { className: css(dialogSheetStyle, splitDialogSheet), children: [_jsx("div", { className: splitDialogMain, children: dialogContent }), _jsx("aside", { className: splitDialogAside, "aria-label": aside.label, children: aside.content })] })) : (_jsx("div", { className: dialogSheet, children: dialogContent })) })] }) })] }));
173
192
  }
174
193
  /**
175
194
  * A confirmation the reader must answer. Unlike `Dialog` it carries the
@@ -207,13 +226,13 @@ export function AlertDialog({ trigger, title, children, confirmLabel, cancelLabe
207
226
  if (!open && pendingRef.current)
208
227
  return details.cancel();
209
228
  onOpenChange?.(open, details);
210
- }, children: [trigger && _jsx(BaseAlertDialog.Trigger, { render: trigger }), _jsx(BaseAlertDialog.Portal, { children: _jsxs(HotkeyLayer, { children: [_jsx(BaseAlertDialog.Backdrop, { "data-ciridae-ui": "", className: backdrop }), _jsxs(BaseAlertDialog.Popup, { className: css(dialogPopup), "data-ciridae-ui": "", children: [_jsx(BaseAlertDialog.Title, { className: dialogTitle, children: title }), children && _jsx("div", { className: dialogBody, children: children }), _jsxs("div", { className: dialogFooter, children: [_jsx(BaseAlertDialog.Close, { render: _jsx(Button, { variant: "secondary" }), disabled: pending, children: cancelLabel ?? labels.common.cancel }), _jsx(Button, { variant: variant === "danger" ? "danger" : "primary", loading: pending, onClick: () => void confirm(), children: confirmLabel })] })] })] }) })] }));
229
+ }, children: [trigger && _jsx(BaseAlertDialog.Trigger, { render: trigger }), _jsx(BaseAlertDialog.Portal, { children: _jsxs(HotkeyLayer, { children: [_jsx(BaseAlertDialog.Backdrop, { "data-ciridae-ui": "", className: backdrop }), _jsx(BaseAlertDialog.Popup, { className: css(dialogShell), "data-ciridae-ui": "", children: _jsxs("div", { className: dialogSheet, children: [_jsx(BaseAlertDialog.Title, { className: dialogTitle, children: title }), children && _jsx("div", { className: dialogBody, children: children }), _jsxs("div", { className: dialogFooter, children: [_jsx(BaseAlertDialog.Close, { render: _jsx(Button, { variant: "secondary", size: "medium" }), disabled: pending, children: cancelLabel ?? labels.common.cancel }), _jsx(Button, { variant: variant === "danger" ? "danger" : "primary", size: "medium", loading: pending, onClick: () => void confirm(), children: confirmLabel })] })] }) })] }) })] }));
211
230
  }
212
231
  // Merged rather than layered, so the density's inset replaces the popup's.
213
232
  const popoverPopups = {
214
233
  regular: popup,
215
- compact: css(popupStyle, { padding: "menu.inset", borderRadius: "action" }),
216
- flush: css(popupStyle, { padding: "none", overflow: "hidden", borderRadius: "action" }),
234
+ compact: css(popupStyle, { padding: "menu.inset" }),
235
+ flush: css(popupStyle, { padding: "none", overflow: "hidden" }),
217
236
  };
218
237
  const popoverWidths = {
219
238
  narrow: css({ width: "overlay.popoverNarrow" }),
@@ -223,18 +242,28 @@ const popoverWidths = {
223
242
  const hoverOpenDelayMs = 300;
224
243
  const hoverCloseDelayMs = 150;
225
244
  export function Popover({ trigger, anchor, children, density = "regular", width, align, openOnHover = false, ...rootProps }) {
226
- return (_jsxs(BasePopover.Root, { ...rootProps, children: [trigger && (_jsx(BasePopover.Trigger, { render: trigger, openOnHover: openOnHover, delay: hoverOpenDelayMs, closeDelay: hoverCloseDelayMs })), _jsx(BasePopover.Portal, { children: _jsx(HotkeyLayer, { enabled: !openOnHover, children: _jsx(BasePopover.Positioner, { className: positioner, sideOffset: 6, align: align, anchor: anchor, children: _jsx(BasePopover.Popup, { className: cx(popoverPopups[density], width && popoverWidths[width]), "data-ciridae-ui": "", initialFocus: openOnHover ? (openType) => openType === "keyboard" : undefined, children: children }) }) }) })] }));
245
+ return (_jsxs(BasePopover.Root, { ...rootProps, children: [trigger && (_jsx(BasePopover.Trigger, { render: trigger, openOnHover: openOnHover, delay: hoverOpenDelayMs, closeDelay: hoverCloseDelayMs })), _jsx(BasePopover.Portal, { children: _jsx(HotkeyLayer, { enabled: !openOnHover, children: _jsx(BasePopover.Positioner, { className: positioner, sideOffset: 4, align: align, anchor: anchor, children: _jsx(BasePopover.Popup, { className: cx(popoverPopups[density], width && popoverWidths[width]), "data-ciridae-ui": "", initialFocus: openOnHover ? (openType) => openType === "keyboard" : undefined, children: children }) }) }) })] }));
227
246
  }
228
- export function Tooltip({ children, content, ...rootProps }) {
229
- return (_jsx(BaseTooltip.Provider, { children: _jsxs(BaseTooltip.Root, { ...rootProps, children: [_jsx(BaseTooltip.Trigger, { render: children }), _jsx(BaseTooltip.Portal, { children: _jsx(BaseTooltip.Positioner, { className: tooltipPositioner, sideOffset: 6, children: _jsx(BaseTooltip.Popup, { className: css({
230
- zIndex: "tooltip",
231
- paddingBlock: "control.compactBlock",
232
- paddingInline: "menu.itemInline",
233
- borderRadius: "action",
234
- background: "fg.primary",
235
- color: "bg.canvas",
236
- fontSize: "caption",
237
- maxWidth: "overlay.tooltip",
238
- textWrap: "pretty",
239
- }), "data-ciridae-ui": "", children: content }) }) })] }) }));
247
+ /* An inverted chip: the primary face, ink in light and white in dark, with the text in the canvas's. */
248
+ const tooltipPopup = css({
249
+ zIndex: "tooltip",
250
+ display: "flex",
251
+ alignItems: "baseline",
252
+ gap: "layout.controlGap",
253
+ paddingBlock: "control.compactBlock",
254
+ paddingInline: "menu.itemInline",
255
+ borderRadius: "keycap",
256
+ background: "fg.primary",
257
+ color: "bg.canvas",
258
+ _light: { background: "token(gradients.primary)", color: "fg.onAccent" },
259
+ fontSize: "code",
260
+ fontWeight: "medium",
261
+ lineHeight: "tight",
262
+ letterSpacing: "compact",
263
+ maxWidth: "overlay.tooltip",
264
+ textWrap: "pretty",
265
+ });
266
+ const tooltipMeta = css({ flexShrink: "0", opacity: "0.6" });
267
+ export function Tooltip({ children, content, meta, ...rootProps }) {
268
+ return (_jsx(BaseTooltip.Provider, { children: _jsxs(BaseTooltip.Root, { ...rootProps, children: [_jsx(BaseTooltip.Trigger, { render: children }), _jsx(BaseTooltip.Portal, { children: _jsx(BaseTooltip.Positioner, { className: tooltipPositioner, sideOffset: 8, children: _jsxs(BaseTooltip.Popup, { className: tooltipPopup, "data-ciridae-ui": "", children: [content, meta !== undefined && _jsx("span", { className: tooltipMeta, children: meta })] }) }) })] }) }));
240
269
  }
@@ -20,7 +20,7 @@ export type BreadcrumbsProps = ComponentProps<"nav"> & {
20
20
  current?: ReactNode;
21
21
  };
22
22
  /** The page's trail: its parents, then the page itself as the trail's heading. */
23
- export declare function Breadcrumbs({ crumbs, current: ownCurrent, ...props }: BreadcrumbsProps): import("@types/react").JSX.Element;
23
+ export declare function Breadcrumbs({ crumbs, current: ownCurrent, ...props }: BreadcrumbsProps): import("react").JSX.Element;
24
24
  export type PageFrameProps = Omit<ComponentProps<"main">, "children"> & {
25
25
  crumbs: readonly Crumb[];
26
26
  /** The header's controls at its far edge, such as filters and the account menu. */
@@ -28,7 +28,7 @@ export type PageFrameProps = Omit<ComponentProps<"main">, "children"> & {
28
28
  children: ReactNode;
29
29
  };
30
30
  /** The main panel of a page: a header with its trail and actions, then the content. */
31
- export declare function PageFrame({ crumbs, headerActions, children, ...props }: PageFrameProps): import("@types/react").JSX.Element;
31
+ export declare function PageFrame({ crumbs, headerActions, children, ...props }: PageFrameProps): import("react").JSX.Element;
32
32
  export type PageHeadingProps = Omit<ComponentProps<"div">, "title"> & {
33
33
  title: ReactNode;
34
34
  /** Before the title, such as a record's avatar or a project's mark. */
@@ -52,7 +52,7 @@ export type PageHeadingProps = Omit<ComponentProps<"div">, "title"> & {
52
52
  * The title a page or a record opens with, the line under it, and its own actions: a node, or menu
53
53
  * items behind an `OverflowMenu`.
54
54
  */
55
- export declare function PageHeading({ title, leading, badge, meta, actions, actionsOpen, onActionsOpenChange, level, labels: ownLabels, className, ...props }: PageHeadingProps): import("@types/react").JSX.Element;
55
+ export declare function PageHeading({ title, leading, badge, meta, actions, actionsOpen, onActionsOpenChange, level, labels: ownLabels, className, ...props }: PageHeadingProps): import("react").JSX.Element;
56
56
  /** One count: the value that reads, and its muted label, as an object or a `[value, label]` pair. */
57
57
  export type Stat = {
58
58
  value: ReactNode;
@@ -62,4 +62,4 @@ export type Stat = {
62
62
  /** A row of `value label` stats split by dots: the value reads, the label stays muted. */
63
63
  export declare function StatLine({ stats, className, ...props }: ComponentProps<"span"> & {
64
64
  stats: readonly Stat[];
65
- }): import("@types/react").JSX.Element;
65
+ }): import("react").JSX.Element;
@@ -61,7 +61,7 @@ const metaLine = css({
61
61
  alignItems: "center",
62
62
  flexWrap: "wrap",
63
63
  gap: "layout.controlGap",
64
- color: "fg.muted",
64
+ color: "fg.label",
65
65
  fontSize: "code",
66
66
  fontWeight: "medium",
67
67
  letterSpacing: "compact",
@@ -3,17 +3,17 @@ import type { ReactNode } from "react";
3
3
  /** The card's surface as a style object, to merge into a `css()` call that adds layout. */
4
4
  export declare const cardSurface: import("../styled-system/types/index.js").SystemStyleObject;
5
5
  export type CardProps = useRender.ComponentProps<"div">;
6
- export declare function Card({ render, className, ...props }: CardProps): import("@types/react").ReactElement<unknown, string | import("@types/react").JSXElementConstructor<any>>;
6
+ export declare function Card({ render, className, ...props }: CardProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
7
7
  export type PanelProps = useRender.ComponentProps<"section"> & {
8
8
  /** `default` pads a group of rows; `compact` insets cards by a hairline; `none` runs flush. */
9
9
  padding?: "none" | "compact" | "default";
10
10
  /** `panel` is the translucent lift off the page; `outline` is the edge alone. */
11
11
  tone?: "panel" | "outline";
12
12
  };
13
- export declare function Panel({ padding, tone, render, className, ...props }: PanelProps): import("@types/react").ReactElement<unknown, string | import("@types/react").JSXElementConstructor<any>>;
13
+ export declare function Panel({ padding, tone, render, className, ...props }: PanelProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
14
14
  export type PanelHeaderProps = Omit<useRender.ComponentProps<"div">, "title"> & {
15
15
  title: ReactNode;
16
- /** Muted beside the title, such as a count or the period it covers. */
16
+ /** Muted at the row's far edge, before the actions, such as a count or the period it covers. */
17
17
  meta?: ReactNode;
18
18
  /** At the row's end, such as a link to the full list. */
19
19
  actions?: ReactNode;
@@ -21,4 +21,4 @@ export type PanelHeaderProps = Omit<useRender.ComponentProps<"div">, "title"> &
21
21
  level?: 2 | 3 | 4;
22
22
  };
23
23
  /** A panel's top row: its title and meta, and its actions at the far edge. */
24
- export declare function PanelHeader({ title, meta, actions, level, render, className, ...props }: PanelHeaderProps): import("@types/react").ReactElement<unknown, string | import("@types/react").JSXElementConstructor<any>>;
24
+ export declare function PanelHeader({ title, meta, actions, level, render, className, ...props }: PanelHeaderProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -9,13 +9,13 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
9
9
  */
10
10
  import { useRender } from "@base-ui/react/use-render";
11
11
  import { css, cva, cx } from "#primitives/css";
12
+ import { singleLineText } from "./single-line-text.js";
12
13
  /** The card's surface as a style object, to merge into a `css()` call that adds layout. */
13
14
  export const cardSurface = css.raw({
14
15
  minWidth: "0",
15
- border: "1px solid token(colors.border.panel)",
16
+ border: "1px solid token(colors.border.card)",
16
17
  borderRadius: "action",
17
- background: "bg.hover",
18
- _light: { background: "bg.card" },
18
+ background: "token(gradients.card)",
19
19
  });
20
20
  const card = css(cardSurface);
21
21
  const panel = cva({
@@ -39,7 +39,7 @@ const panel = cva({
39
39
  default: { gap: "layout.contentGap", padding: "panel.default" },
40
40
  },
41
41
  tone: {
42
- panel: { borderColor: "border.panel", background: "bg.panel" },
42
+ panel: { borderColor: "border.panel", background: "token(gradients.panel)" },
43
43
  outline: { borderColor: "border.control" },
44
44
  },
45
45
  },
@@ -55,19 +55,25 @@ const panelHeader = css({
55
55
  paddingInline: "panel.comfortable",
56
56
  fontSize: "body",
57
57
  fontWeight: "medium",
58
- // In a padded panel the header is one more row inside the padding.
59
- "[data-panel-padding=default] > &": { height: "auto", paddingInline: "none" },
58
+ lineHeight: "tight",
59
+ /*
60
+ * In a padded panel the header is one more row inside the padding, inset from what follows by
61
+ * the design's 16px: its own padding, less the panel's gap, which it takes back.
62
+ */
63
+ "[data-panel-padding=default] > &": {
64
+ height: "auto",
65
+ gap: "layout.controlGap",
66
+ paddingInline: "none",
67
+ paddingBottom: "panel.comfortable",
68
+ marginBottom: "calc(token(spacing.layout.contentGap) * -1)",
69
+ },
60
70
  });
61
- const panelHeaderTitle = css({
71
+ const panelHeaderTitle = css(singleLineText, {
62
72
  display: "flex",
63
73
  alignItems: "center",
64
74
  gap: "control.iconGap",
65
- minWidth: "0",
66
75
  margin: "none",
67
76
  font: "inherit",
68
- overflow: "hidden",
69
- textOverflow: "ellipsis",
70
- whiteSpace: "nowrap",
71
77
  });
72
78
  const panelHeaderMeta = css({ color: "fg.subtle", fontSize: "code" });
73
79
  const panelHeaderActions = css({ display: "flex", alignItems: "center", gap: "layout.tightGap" });
@@ -101,7 +107,7 @@ export function PanelHeader({ title, meta, actions, level, render, className, ..
101
107
  className: cx(panelHeader, className),
102
108
  "data-ciridae-ui": "",
103
109
  "data-panel-header": "",
104
- children: (_jsxs(_Fragment, { children: [title !== undefined && title !== null && (_jsxs(Title, { className: panelHeaderTitle, children: [title, meta !== undefined && _jsx("span", { className: panelHeaderMeta, children: meta })] })), actions !== undefined && _jsx("span", { className: panelHeaderActions, children: actions })] })),
110
+ children: (_jsxs(_Fragment, { children: [title !== undefined && title !== null && (_jsx(Title, { className: panelHeaderTitle, children: title })), (meta !== undefined || actions !== undefined) && (_jsxs("span", { className: panelHeaderActions, children: [meta !== undefined && _jsx("span", { className: panelHeaderMeta, children: meta }), actions] }))] })),
105
111
  },
106
112
  });
107
113
  }
@@ -12,4 +12,4 @@ export type ProfileHeaderProps = Omit<ComponentProps<"header">, "children" | "ti
12
12
  description?: ReactNode;
13
13
  actions?: ReactNode;
14
14
  };
15
- export declare function ProfileHeader({ name, kind, src, title, team, email, description, actions, className, ...props }: ProfileHeaderProps): import("@types/react").JSX.Element;
15
+ export declare function ProfileHeader({ name, kind, src, title, team, email, description, actions, className, ...props }: ProfileHeaderProps): import("react").JSX.Element;
@@ -2,4 +2,4 @@ import type { ReactNode } from "react";
2
2
  export declare function Progress({ value, label }: {
3
3
  value: number;
4
4
  label?: ReactNode;
5
- }): import("@types/react").JSX.Element;
5
+ }): import("react").JSX.Element;
@@ -9,4 +9,4 @@ export declare function ProjectAvatar({ projectId, name, size, className, }: {
9
9
  name: string;
10
10
  size?: ComponentProps<typeof Avatar>["size"];
11
11
  className?: string;
12
- }): import("@types/react").JSX.Element;
12
+ }): import("react").JSX.Element;
@@ -9,7 +9,7 @@ export type RadioCardGroupProps = Omit<ComponentProps<typeof BaseRadioGroup>, "d
9
9
  value?: string;
10
10
  onValueChange?: (value: string) => void;
11
11
  };
12
- export declare function RadioCardGroup({ name, label, defaultValue, value, onValueChange, className, ...props }: RadioCardGroupProps): import("@types/react").JSX.Element;
12
+ export declare function RadioCardGroup({ name, label, defaultValue, value, onValueChange, className, ...props }: RadioCardGroupProps): import("react").JSX.Element;
13
13
  export type RadioCardProps = Omit<ComponentProps<typeof BaseRadio.Root>, "children" | "className"> & {
14
14
  value: string;
15
15
  title: ReactNode;
@@ -19,4 +19,4 @@ export type RadioCardProps = Omit<ComponentProps<typeof BaseRadio.Root>, "childr
19
19
  className?: string;
20
20
  };
21
21
  /** One option of a `RadioCardGroup`. */
22
- export declare function RadioCard({ title, detail, source: sourceContent, className, ...props }: RadioCardProps): import("@types/react").JSX.Element;
22
+ export declare function RadioCard({ title, detail, source: sourceContent, className, ...props }: RadioCardProps): import("react").JSX.Element;