@estiva-app/ui 0.11.0 → 0.12.1

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 (47) hide show
  1. package/dist/AppShell.d.ts.map +1 -1
  2. package/dist/Breadcrumb.d.ts +7 -1
  3. package/dist/Breadcrumb.d.ts.map +1 -1
  4. package/dist/Chip.d.ts.map +1 -1
  5. package/dist/CollapsibleSection.d.ts +42 -0
  6. package/dist/CollapsibleSection.d.ts.map +1 -0
  7. package/dist/EmptyState.d.ts +19 -5
  8. package/dist/EmptyState.d.ts.map +1 -1
  9. package/dist/NavItem.d.ts.map +1 -1
  10. package/dist/ScrollArea.d.ts.map +1 -1
  11. package/dist/SectionHeader.d.ts +31 -10
  12. package/dist/SectionHeader.d.ts.map +1 -1
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +202 -129
  16. package/dist/index.js.map +4 -4
  17. package/package.json +1 -1
  18. package/src/AppShell.mdx +15 -0
  19. package/src/AppShell.stories.tsx +15 -0
  20. package/src/AppShell.test.tsx +39 -0
  21. package/src/AppShell.tsx +22 -7
  22. package/src/Breadcrumb.mdx +6 -0
  23. package/src/Breadcrumb.stories.tsx +12 -0
  24. package/src/Breadcrumb.test.tsx +10 -0
  25. package/src/Breadcrumb.tsx +17 -2
  26. package/src/Chip.tsx +10 -2
  27. package/src/CollapsibleSection.mdx +72 -0
  28. package/src/CollapsibleSection.stories.tsx +38 -0
  29. package/src/CollapsibleSection.test.tsx +81 -0
  30. package/src/CollapsibleSection.tsx +92 -0
  31. package/src/EmptyState.mdx +30 -10
  32. package/src/EmptyState.stories.tsx +7 -3
  33. package/src/EmptyState.test.tsx +39 -0
  34. package/src/EmptyState.tsx +23 -6
  35. package/src/NavItem.tsx +5 -1
  36. package/src/ScrollArea.mdx +6 -0
  37. package/src/ScrollArea.stories.tsx +29 -0
  38. package/src/ScrollArea.test.tsx +15 -0
  39. package/src/ScrollArea.tsx +17 -4
  40. package/src/SectionHeader.mdx +26 -17
  41. package/src/SectionHeader.stories.tsx +4 -35
  42. package/src/SectionHeader.test.tsx +40 -0
  43. package/src/SectionHeader.tsx +70 -39
  44. package/src/Sidebar.mdx +14 -10
  45. package/src/Sidebar.stories.tsx +17 -15
  46. package/src/index.ts +1 -0
  47. package/stories/Choosing.mdx +2 -1
package/dist/index.js CHANGED
@@ -34,11 +34,36 @@ function cn(...inputs) {
34
34
  return twMerge(clsx(inputs));
35
35
  }
36
36
 
37
- // src/TopBar.tsx
37
+ // src/ScrollArea.tsx
38
+ import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
38
39
  import { jsx, jsxs } from "react/jsx-runtime";
40
+ var BAR = "flex touch-none select-none rounded-full opacity-0 transition-opacity delay-300 data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0";
41
+ var THUMB = "rounded-full bg-border-strong";
42
+ function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, children }) {
43
+ const vertical = orientation !== "horizontal";
44
+ const horizontal = orientation !== "vertical";
45
+ return /* @__PURE__ */ jsxs(BaseScrollArea.Root, { className: cn("relative min-h-0 min-w-0", className), children: [
46
+ /* @__PURE__ */ jsx(
47
+ BaseScrollArea.Viewport,
48
+ {
49
+ className: cn(
50
+ "h-full w-full outline-none data-[has-overflow-x]:overscroll-x-contain data-[has-overflow-y]:overscroll-y-contain",
51
+ viewportClassName
52
+ ),
53
+ children: /* @__PURE__ */ jsx(BaseScrollArea.Content, { className: contentClassName, style: horizontal ? void 0 : { minWidth: 0 }, children })
54
+ }
55
+ ),
56
+ vertical && /* @__PURE__ */ jsx(BaseScrollArea.Scrollbar, { orientation: "vertical", className: cn(BAR, "w-1.5 justify-center py-0.5 pr-0.5"), children: /* @__PURE__ */ jsx(BaseScrollArea.Thumb, { className: cn(THUMB, "w-full") }) }),
57
+ horizontal && /* @__PURE__ */ jsx(BaseScrollArea.Scrollbar, { orientation: "horizontal", className: cn(BAR, "h-1.5 flex-col justify-center px-0.5 pb-0.5"), children: /* @__PURE__ */ jsx(BaseScrollArea.Thumb, { className: cn(THUMB, "h-full") }) }),
58
+ vertical && horizontal && /* @__PURE__ */ jsx(BaseScrollArea.Corner, {})
59
+ ] });
60
+ }
61
+
62
+ // src/TopBar.tsx
63
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
39
64
  function TopBar({ variant = "solid", menu, logo, search, right, className }) {
40
65
  const floating = variant === "floating";
41
- return /* @__PURE__ */ jsxs(
66
+ return /* @__PURE__ */ jsxs2(
42
67
  "header",
43
68
  {
44
69
  className: cn(
@@ -47,27 +72,27 @@ function TopBar({ variant = "solid", menu, logo, search, right, className }) {
47
72
  className
48
73
  ),
49
74
  children: [
50
- (menu || logo) && /* @__PURE__ */ jsxs("div", { className: cn("flex shrink-0 items-center gap-2", floating && "pointer-events-auto"), children: [
75
+ (menu || logo) && /* @__PURE__ */ jsxs2("div", { className: cn("flex shrink-0 items-center gap-2", floating && "pointer-events-auto"), children: [
51
76
  menu,
52
- logo && /* @__PURE__ */ jsx("div", { className: "flex items-center text-body-2-strong text-text-primary", children: logo })
77
+ logo && /* @__PURE__ */ jsx2("div", { className: "flex items-center text-body-2-strong text-text-primary", children: logo })
53
78
  ] }),
54
- /* @__PURE__ */ jsx("div", { className: cn("flex min-w-0 flex-1 items-center justify-center", floating && "pointer-events-auto"), children: search }),
55
- /* @__PURE__ */ jsx("div", { className: cn("flex shrink-0 items-center gap-[6px]", floating && "pointer-events-auto"), children: right })
79
+ /* @__PURE__ */ jsx2("div", { className: cn("flex min-w-0 flex-1 items-center justify-center", floating && "pointer-events-auto"), children: search }),
80
+ /* @__PURE__ */ jsx2("div", { className: cn("flex shrink-0 items-center gap-[6px]", floating && "pointer-events-auto"), children: right })
56
81
  ]
57
82
  }
58
83
  );
59
84
  }
60
85
 
61
86
  // src/AppShell.tsx
62
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
87
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
63
88
  function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav, children }) {
64
- const bar = /* @__PURE__ */ jsx2(TopBar, { variant, menu, logo, search, right: identity });
89
+ const bar = /* @__PURE__ */ jsx3(TopBar, { variant, menu, logo, search, right: identity });
65
90
  if (variant === "floating") {
66
- return /* @__PURE__ */ jsxs2("div", { className: "relative h-full min-h-0 overflow-hidden bg-bg-base", children: [
91
+ return /* @__PURE__ */ jsxs3("div", { className: "relative h-full min-h-0 overflow-hidden bg-bg-base", children: [
67
92
  bar,
68
- /* @__PURE__ */ jsxs2("div", { className: "flex h-full pb-4 pr-4 pt-[52px]", children: [
93
+ /* @__PURE__ */ jsxs3("div", { className: "flex h-full pb-4 pr-4 pt-[52px]", children: [
69
94
  nav,
70
- /* @__PURE__ */ jsxs2(
95
+ /* @__PURE__ */ jsxs3(
71
96
  "div",
72
97
  {
73
98
  className: cn(
@@ -76,7 +101,7 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
76
101
  ),
77
102
  children: [
78
103
  banner,
79
- /* @__PURE__ */ jsx2("main", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children })
104
+ /* @__PURE__ */ jsx3("main", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children })
80
105
  ]
81
106
  }
82
107
  )
@@ -84,20 +109,22 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
84
109
  ] });
85
110
  }
86
111
  return (
87
- /* `relative overflow-hidden` is the seal the floating manner already has,
112
+ /* `relative overflow-hidden` is the seal the floating manner already has
113
+ (and the ScrollArea's own root is `relative`, so an absolutely placed
114
+ stray inside a page now belongs to the region and scrolls with it),
88
115
  and it takes both halves: an absolutely positioned descendant with no
89
116
  positioned ancestor belongs to the *viewport*, so a scroll container
90
117
  never clips it and the document itself gains its position as scroll
91
118
  range — the whole page scrolls, navigation and top bar included.
92
119
  `relative` claims such strays for the shell; `overflow-hidden` clips
93
120
  them at its edge. Either alone seals nothing. */
94
- /* @__PURE__ */ jsxs2("div", { className: "relative flex h-full min-h-0 flex-col overflow-hidden bg-bg-base text-text-primary", children: [
121
+ /* @__PURE__ */ jsxs3("div", { className: "relative flex h-full min-h-0 flex-col overflow-hidden bg-bg-base text-text-primary", children: [
95
122
  bar,
96
- /* @__PURE__ */ jsxs2("div", { className: "flex min-h-0 flex-1", children: [
123
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-h-0 flex-1", children: [
97
124
  nav,
98
- /* @__PURE__ */ jsxs2("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [
125
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [
99
126
  banner,
100
- /* @__PURE__ */ jsx2("main", { className: "min-w-0 flex-1 overflow-y-auto", children })
127
+ /* @__PURE__ */ jsx3(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex min-h-full flex-col", children: /* @__PURE__ */ jsx3("main", { className: "flex min-w-0 flex-1 flex-col", children }) })
101
128
  ] })
102
129
  ] })
103
130
  ] })
@@ -107,7 +134,7 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
107
134
  // src/Avatar.tsx
108
135
  import { useState } from "react";
109
136
  import { IconUserFilled } from "@tabler/icons-react";
110
- import { jsx as jsx3 } from "react/jsx-runtime";
137
+ import { jsx as jsx4 } from "react/jsx-runtime";
111
138
  var HUES = ["#56c8ff", "#ff8f6b", "#4ade8c", "#b18cff", "#ffc94d", "#ff7eb0", "#7ea8ff", "#5fdfd6"];
112
139
  var hueFor = (key) => {
113
140
  let h = 0;
@@ -123,13 +150,13 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
123
150
  const [broken, setBroken] = useState(false);
124
151
  const label = name || alt;
125
152
  const picture = src && !broken ? src : void 0;
126
- return /* @__PURE__ */ jsx3(
153
+ return /* @__PURE__ */ jsx4(
127
154
  "div",
128
155
  {
129
156
  ...spoken ? { role: "img", "aria-label": spoken } : { "aria-hidden": true },
130
157
  className: cn("rounded-sm overflow-hidden shrink-0 bg-bg-inset", className),
131
158
  style: { width: size, height: size },
132
- children: picture ? /* @__PURE__ */ jsx3("img", { src: picture, alt: "", className: "w-full h-full object-cover", onError: () => setBroken(true) }) : label ? /* @__PURE__ */ jsx3(
159
+ children: picture ? /* @__PURE__ */ jsx4("img", { src: picture, alt: "", className: "w-full h-full object-cover", onError: () => setBroken(true) }) : label ? /* @__PURE__ */ jsx4(
133
160
  "div",
134
161
  {
135
162
  className: "w-full h-full flex items-center justify-center font-semibold leading-none",
@@ -143,29 +170,29 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
143
170
  },
144
171
  children: initialsFor(label)
145
172
  }
146
- ) : /* @__PURE__ */ jsx3("div", { className: "w-full h-full bg-accent-muted flex items-center justify-center text-text-muted", children: /* @__PURE__ */ jsx3(IconUserFilled, { size: Math.round(size * 0.5) }) })
173
+ ) : /* @__PURE__ */ jsx4("div", { className: "w-full h-full bg-accent-muted flex items-center justify-center text-text-muted", children: /* @__PURE__ */ jsx4(IconUserFilled, { size: Math.round(size * 0.5) }) })
147
174
  }
148
175
  );
149
176
  }
150
177
 
151
178
  // src/AvatarGroup.tsx
152
- import { jsx as jsx4 } from "react/jsx-runtime";
179
+ import { jsx as jsx5 } from "react/jsx-runtime";
153
180
  function AvatarGroup({ members, size = 24 }) {
154
181
  const visible = members.slice(0, 3);
155
182
  const overlap = Math.round(size / 3);
156
183
  const ring = size / 12;
157
- return /* @__PURE__ */ jsx4("div", { className: "flex items-center", style: { paddingRight: overlap }, children: visible.map((member, i) => (
184
+ return /* @__PURE__ */ jsx5("div", { className: "flex items-center", style: { paddingRight: overlap }, children: visible.map((member, i) => (
158
185
  /*
159
186
  The wrapper carries the overlap and the ring; the face carries
160
187
  neither. It must never clip — see the note at the top of the file —
161
188
  so it has the avatar's own radius and no overflow of its own.
162
189
  */
163
- /* @__PURE__ */ jsx4(
190
+ /* @__PURE__ */ jsx5(
164
191
  "span",
165
192
  {
166
193
  className: "relative flex rounded-sm",
167
194
  style: { marginRight: -overlap, boxShadow: `0 0 0 ${ring}px var(--bg-surface)` },
168
- children: /* @__PURE__ */ jsx4(Avatar, { size, name: member.name, src: member.picture, label: member.name })
195
+ children: /* @__PURE__ */ jsx5(Avatar, { size, name: member.name, src: member.picture, label: member.name })
169
196
  },
170
197
  i
171
198
  )
@@ -182,9 +209,9 @@ import { Button as BaseButton } from "@base-ui/react/button";
182
209
  import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
183
210
 
184
211
  // src/Kbd.tsx
185
- import { jsx as jsx5 } from "react/jsx-runtime";
212
+ import { jsx as jsx6 } from "react/jsx-runtime";
186
213
  function Kbd({ children, className }) {
187
- return /* @__PURE__ */ jsx5(
214
+ return /* @__PURE__ */ jsx6(
188
215
  "kbd",
189
216
  {
190
217
  className: cn(
@@ -199,21 +226,21 @@ function Kbd({ children, className }) {
199
226
  }
200
227
 
201
228
  // src/Tooltip.tsx
202
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
229
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
203
230
  var OPEN_DELAY = 300;
204
231
  function TooltipProvider({ delay = OPEN_DELAY, closeDelay, timeout, children }) {
205
- return /* @__PURE__ */ jsx6(BaseTooltip.Provider, { delay, closeDelay, timeout, children });
232
+ return /* @__PURE__ */ jsx7(BaseTooltip.Provider, { delay, closeDelay, timeout, children });
206
233
  }
207
234
  function Tooltip({ label, shortcut, className, ...props }) {
208
- return /* @__PURE__ */ jsxs3("div", { role: "tooltip", className: cn("bg-bg-elevated border border-border-default rounded-lg h-[30px] flex items-center justify-center gap-1.5 px-2 shadow-lg", className), ...props, children: [
209
- /* @__PURE__ */ jsx6("span", { className: "text-caption text-text-primary whitespace-nowrap", children: label }),
210
- shortcut && /* @__PURE__ */ jsx6(Kbd, { children: shortcut })
235
+ return /* @__PURE__ */ jsxs4("div", { role: "tooltip", className: cn("bg-bg-elevated border border-border-default rounded-lg h-[30px] flex items-center justify-center gap-1.5 px-2 shadow-lg", className), ...props, children: [
236
+ /* @__PURE__ */ jsx7("span", { className: "text-caption text-text-primary whitespace-nowrap", children: label }),
237
+ shortcut && /* @__PURE__ */ jsx7(Kbd, { children: shortcut })
211
238
  ] });
212
239
  }
213
240
  var GAP = 6;
214
241
  var VIEWPORT_PAD = 8;
215
242
  function TooltipSurface({ label, shortcut, placement }) {
216
- return /* @__PURE__ */ jsx6(BaseTooltip.Portal, { children: /* @__PURE__ */ jsx6(
243
+ return /* @__PURE__ */ jsx7(BaseTooltip.Portal, { children: /* @__PURE__ */ jsx7(
217
244
  BaseTooltip.Positioner,
218
245
  {
219
246
  side: placement,
@@ -222,10 +249,10 @@ function TooltipSurface({ label, shortcut, placement }) {
222
249
  collisionPadding: VIEWPORT_PAD,
223
250
  positionMethod: "fixed",
224
251
  className: "pointer-events-none z-[9999]",
225
- children: /* @__PURE__ */ jsx6(
252
+ children: /* @__PURE__ */ jsx7(
226
253
  BaseTooltip.Popup,
227
254
  {
228
- render: /* @__PURE__ */ jsx6(
255
+ render: /* @__PURE__ */ jsx7(
229
256
  Tooltip,
230
257
  {
231
258
  label,
@@ -245,20 +272,20 @@ function TooltipSurface({ label, shortcut, placement }) {
245
272
  ) });
246
273
  }
247
274
  function WithTooltip({ label, shortcut, placement = "top", wrapperClassName, children }) {
248
- return /* @__PURE__ */ jsxs3(BaseTooltip.Root, { disableHoverablePopup: true, children: [
249
- /* @__PURE__ */ jsx6(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: /* @__PURE__ */ jsx6("div", { className: cn("inline-flex shrink-0", wrapperClassName) }), children }),
250
- /* @__PURE__ */ jsx6(TooltipSurface, { label, shortcut, placement })
275
+ return /* @__PURE__ */ jsxs4(BaseTooltip.Root, { disableHoverablePopup: true, children: [
276
+ /* @__PURE__ */ jsx7(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: /* @__PURE__ */ jsx7("div", { className: cn("inline-flex shrink-0", wrapperClassName) }), children }),
277
+ /* @__PURE__ */ jsx7(TooltipSurface, { label, shortcut, placement })
251
278
  ] });
252
279
  }
253
280
  function TooltipTrigger({ label, shortcut, placement = "top", children }) {
254
- return /* @__PURE__ */ jsxs3(BaseTooltip.Root, { disableHoverablePopup: true, children: [
255
- /* @__PURE__ */ jsx6(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: children }),
256
- /* @__PURE__ */ jsx6(TooltipSurface, { label, shortcut, placement })
281
+ return /* @__PURE__ */ jsxs4(BaseTooltip.Root, { disableHoverablePopup: true, children: [
282
+ /* @__PURE__ */ jsx7(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: children }),
283
+ /* @__PURE__ */ jsx7(TooltipSurface, { label, shortcut, placement })
257
284
  ] });
258
285
  }
259
286
 
260
287
  // src/IconButton.tsx
261
- import { jsx as jsx7 } from "react/jsx-runtime";
288
+ import { jsx as jsx8 } from "react/jsx-runtime";
262
289
  function IconButton({
263
290
  variant = "muted",
264
291
  className,
@@ -271,7 +298,7 @@ function IconButton({
271
298
  type = "button",
272
299
  ...props
273
300
  }) {
274
- const button = /* @__PURE__ */ jsx7(
301
+ const button = /* @__PURE__ */ jsx8(
275
302
  BaseButton,
276
303
  {
277
304
  type,
@@ -299,13 +326,13 @@ function IconButton({
299
326
  );
300
327
  const label = disabledReason ?? tooltip;
301
328
  if (label) {
302
- return /* @__PURE__ */ jsx7(TooltipTrigger, { label, shortcut: disabledReason ? void 0 : tooltipShortcut, placement: tooltipPlacement, children: button });
329
+ return /* @__PURE__ */ jsx8(TooltipTrigger, { label, shortcut: disabledReason ? void 0 : tooltipShortcut, placement: tooltipPlacement, children: button });
303
330
  }
304
331
  return button;
305
332
  }
306
333
 
307
334
  // src/Banner.tsx
308
- import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
335
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
309
336
  var TONE_STYLES = {
310
337
  ok: "bg-success-muted text-success-default",
311
338
  error: "bg-error-muted text-error-default",
@@ -315,17 +342,17 @@ var TONE_STYLES = {
315
342
  function Banner({ tone, children, onDismiss, dismissLabel = "Dismiss", className }) {
316
343
  const role = tone === "error" ? "alert" : "status";
317
344
  if (!onDismiss) {
318
- return /* @__PURE__ */ jsx8("div", { role, className: cn("px-4 py-2 text-body-2", TONE_STYLES[tone], className), children });
345
+ return /* @__PURE__ */ jsx9("div", { role, className: cn("px-4 py-2 text-body-2", TONE_STYLES[tone], className), children });
319
346
  }
320
- return /* @__PURE__ */ jsxs4("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
321
- /* @__PURE__ */ jsx8("span", { className: "min-w-0 flex-1", children }),
322
- /* @__PURE__ */ jsx8(IconButton, { "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0 text-current hover:text-current", children: /* @__PURE__ */ jsx8(IconX, { size: 16, stroke: 1.5 }) })
347
+ return /* @__PURE__ */ jsxs5("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
348
+ /* @__PURE__ */ jsx9("span", { className: "min-w-0 flex-1", children }),
349
+ /* @__PURE__ */ jsx9(IconButton, { "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0 text-current hover:text-current", children: /* @__PURE__ */ jsx9(IconX, { size: 16, stroke: 1.5 }) })
323
350
  ] });
324
351
  }
325
352
 
326
353
  // src/Button.tsx
327
354
  import { Button as BaseButton2 } from "@base-ui/react/button";
328
- import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
355
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
329
356
  function Button({
330
357
  variant = "muted",
331
358
  size = "default",
@@ -338,7 +365,7 @@ function Button({
338
365
  ...props
339
366
  }) {
340
367
  const hasLeadingIcon = !!leadingIcon;
341
- const button = /* @__PURE__ */ jsxs5(
368
+ const button = /* @__PURE__ */ jsxs6(
342
369
  BaseButton2,
343
370
  {
344
371
  type,
@@ -372,13 +399,13 @@ function Button({
372
399
  ]
373
400
  }
374
401
  );
375
- return disabledReason ? /* @__PURE__ */ jsx9(TooltipTrigger, { label: disabledReason, children: button }) : button;
402
+ return disabledReason ? /* @__PURE__ */ jsx10(TooltipTrigger, { label: disabledReason, children: button }) : button;
376
403
  }
377
404
 
378
405
  // src/Checkbox.tsx
379
406
  import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
380
407
  import { IconCheck } from "@tabler/icons-react";
381
- import { jsx as jsx10 } from "react/jsx-runtime";
408
+ import { jsx as jsx11 } from "react/jsx-runtime";
382
409
  function squareClasses(checked, disabled, interactive, className) {
383
410
  return cn(
384
411
  "inline-flex items-center justify-center size-4 shrink-0 rounded-[4px] border transition-colors",
@@ -391,9 +418,9 @@ function squareClasses(checked, disabled, interactive, className) {
391
418
  var tickClasses = (checked) => cn("flex", !checked && "invisible");
392
419
  function Checkbox({ checked, onChange, disabled = false, className, ...aria }) {
393
420
  if (!onChange) {
394
- return /* @__PURE__ */ jsx10("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx10("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx10(IconCheck, { size: 12, stroke: 3 }) }) });
421
+ return /* @__PURE__ */ jsx11("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx11("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx11(IconCheck, { size: 12, stroke: 3 }) }) });
395
422
  }
396
- return /* @__PURE__ */ jsx10(
423
+ return /* @__PURE__ */ jsx11(
397
424
  BaseCheckbox.Root,
398
425
  {
399
426
  checked,
@@ -403,13 +430,13 @@ function Checkbox({ checked, onChange, disabled = false, className, ...aria }) {
403
430
  onCheckedChange: (next) => onChange(next),
404
431
  onClick: (e) => e.stopPropagation(),
405
432
  className: (state) => squareClasses(state.checked, state.disabled, true, className),
406
- children: /* @__PURE__ */ jsx10(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx10(IconCheck, { size: 12, stroke: 3 }) })
433
+ children: /* @__PURE__ */ jsx11(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx11(IconCheck, { size: 12, stroke: 3 }) })
407
434
  }
408
435
  );
409
436
  }
410
437
 
411
438
  // src/Chip.tsx
412
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
439
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
413
440
  var typeStyles = {
414
441
  neutral: "bg-bg-inset text-text-primary",
415
442
  brand: "bg-accent-muted text-accent-primary signal:border signal:border-accent-outline",
@@ -419,10 +446,18 @@ var typeStyles = {
419
446
  error: "bg-error-muted text-error-default signal:border signal:border-error-outline"
420
447
  };
421
448
  function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className }) {
422
- return /* @__PURE__ */ jsxs6("div", { className: cn("inline-flex items-center justify-center gap-1.5 rounded-full max-h-[20px] min-w-[16px] px-2 py-1", typeStyles[type], className), children: [
423
- leadingIcon && /* @__PURE__ */ jsx11("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
424
- label && /* @__PURE__ */ jsx11("span", { className: "text-chip whitespace-nowrap signal:font-mono signal:text-[10px] signal:font-semibold signal:tracking-[0.02em] signal:tabular-nums", children: label }),
425
- trailingIcon && /* @__PURE__ */ jsx11("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
449
+ return /* @__PURE__ */ jsxs7("div", { className: cn("inline-flex min-w-0 items-center justify-center gap-1.5 rounded-full max-h-[20px] px-2 py-1", typeStyles[type], className), children: [
450
+ leadingIcon && /* @__PURE__ */ jsx12("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
451
+ label && // A chip given a `max-w-*` cuts a long label with an ellipsis instead
452
+ // of growing past it Ship's project chip on an issue row
453
+ // (2026-09-09). Clipped sideways only: `overflow-x-clip`, not
454
+ // `truncate`, because `truncate` is `overflow: hidden` on both axes and
455
+ // the label's line box (11px under Signal) is tighter than its glyphs —
456
+ // the screenshot diff caught every descender cut off. `clip` is the
457
+ // one overflow that leaves the other axis visible. A chip with no cap
458
+ // draws exactly as before.
459
+ /* @__PURE__ */ jsx12("span", { className: "min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tracking-[0.02em] signal:tabular-nums", children: label }),
460
+ trailingIcon && /* @__PURE__ */ jsx12("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
426
461
  ] });
427
462
  }
428
463
 
@@ -459,22 +494,6 @@ function triggerDisabled(trigger) {
459
494
  return !!(props.disabled || props.disabledReason);
460
495
  }
461
496
 
462
- // src/ScrollArea.tsx
463
- import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
464
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
465
- var BAR = "flex touch-none select-none rounded-full opacity-0 transition-opacity delay-300 data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0";
466
- var THUMB = "rounded-full bg-border-strong";
467
- function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, children }) {
468
- const vertical = orientation !== "horizontal";
469
- const horizontal = orientation !== "vertical";
470
- return /* @__PURE__ */ jsxs7(BaseScrollArea.Root, { className: cn("relative min-h-0 min-w-0", className), children: [
471
- /* @__PURE__ */ jsx12(BaseScrollArea.Viewport, { className: cn("h-full w-full overscroll-contain outline-none", viewportClassName), children: /* @__PURE__ */ jsx12(BaseScrollArea.Content, { className: contentClassName, style: horizontal ? void 0 : { minWidth: 0 }, children }) }),
472
- vertical && /* @__PURE__ */ jsx12(BaseScrollArea.Scrollbar, { orientation: "vertical", className: cn(BAR, "w-1.5 justify-center py-0.5 pr-0.5"), children: /* @__PURE__ */ jsx12(BaseScrollArea.Thumb, { className: cn(THUMB, "w-full") }) }),
473
- horizontal && /* @__PURE__ */ jsx12(BaseScrollArea.Scrollbar, { orientation: "horizontal", className: cn(BAR, "h-1.5 flex-col justify-center px-0.5 pb-0.5"), children: /* @__PURE__ */ jsx12(BaseScrollArea.Thumb, { className: cn(THUMB, "h-full") }) }),
474
- vertical && horizontal && /* @__PURE__ */ jsx12(BaseScrollArea.Corner, {})
475
- ] });
476
- }
477
-
478
497
  // src/SectionLabel.tsx
479
498
  import { jsx as jsx13 } from "react/jsx-runtime";
480
499
  function SectionLabel({ children, className }) {
@@ -1428,8 +1447,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1428
1447
  // src/EmptyState.tsx
1429
1448
  import { IconMessage2 } from "@tabler/icons-react";
1430
1449
  import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
1431
- function EmptyState({ icon, message, className }) {
1432
- return /* @__PURE__ */ jsxs18("div", { className: cn("flex flex-col gap-2 items-center", className), children: [
1450
+ function EmptyState({ icon, message, scope = "page", className }) {
1451
+ if (scope === "section") {
1452
+ return /* @__PURE__ */ jsx27("p", { className: cn("text-body-2 text-text-secondary", className), children: message });
1453
+ }
1454
+ return /* @__PURE__ */ jsxs18("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
1433
1455
  /* @__PURE__ */ jsx27("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx27(IconMessage2, { size: 16, stroke: 1.5 }) }),
1434
1456
  /* @__PURE__ */ jsx27("p", { className: "text-body-2 text-text-secondary text-center", children: message })
1435
1457
  ] });
@@ -1475,13 +1497,14 @@ function Breadcrumb({ items, className }) {
1475
1497
  }, [measure, items]);
1476
1498
  return /* @__PURE__ */ jsx29("nav", { ref: navRef, "aria-label": "Breadcrumb", className: cn("flex min-w-0 items-center gap-1.5 text-[14px] leading-[140%]", className), children: items.map((item, index) => {
1477
1499
  const last = index === items.length - 1;
1500
+ const tone = item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary";
1478
1501
  const text = cn(
1479
1502
  "truncate",
1480
1503
  // A mono crumb is a ref — the identity. It never gives up width to a
1481
1504
  // long name beside it (the LongName story always claimed "the ref
1482
1505
  // stays"; flexbox was squeezing it anyway until this line).
1483
1506
  item.mono && "shrink-0 font-mono text-[12px] leading-[120%]",
1484
- item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary"
1507
+ tone
1485
1508
  );
1486
1509
  const setLabelRef = (el) => {
1487
1510
  labelRefs.current[index] = el;
@@ -1489,6 +1512,7 @@ function Breadcrumb({ items, className }) {
1489
1512
  const crumb = item.href ? /* @__PURE__ */ jsx29("a", { ref: setLabelRef, href: item.href, onClick: item.onClick, className: cn(text, "hover:text-text-primary"), children: item.label }) : /* @__PURE__ */ jsx29("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
1490
1513
  return /* @__PURE__ */ jsxs20(Fragment4, { children: [
1491
1514
  index > 0 && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
1515
+ item.icon && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
1492
1516
  truncated.has(index) ? (
1493
1517
  // `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
1494
1518
  // must keep truncating inside it, or wrapping it would widen the
@@ -1519,7 +1543,7 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
1519
1543
  children: [
1520
1544
  icon && /* @__PURE__ */ jsx30("span", { className: "flex shrink-0 items-center", children: icon }),
1521
1545
  /* @__PURE__ */ jsx30("span", { className: "flex-1 truncate", children: label }),
1522
- count ? /* @__PURE__ */ jsx30(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx30("span", { className: "shrink-0 font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
1546
+ count ? /* @__PURE__ */ jsx30(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx30("span", { className: "min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
1523
1547
  ]
1524
1548
  }
1525
1549
  );
@@ -1818,58 +1842,106 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
1818
1842
  }
1819
1843
 
1820
1844
  // src/SectionHeader.tsx
1821
- import { useState as useState6 } from "react";
1822
1845
  import { IconChevronRight as IconChevronRight2 } from "@tabler/icons-react";
1823
- import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
1824
- function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, actions, showActions = "hover", className }) {
1825
- const [isHovered, setIsHovered] = useState6(false);
1846
+ import { useRender } from "@base-ui/react/use-render";
1847
+ import { Fragment as Fragment5, jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
1848
+ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, actions, showActions = "hover", render, className }) {
1849
+ const titleElement = useRender({
1850
+ render: render ?? (chevron ? /* @__PURE__ */ jsx41("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx41("span", {})),
1851
+ props: {
1852
+ // `text-left`: a button centres its text. `h-full` and `flex-1`: the
1853
+ // whole row up to the actions is the hit target, as it was when the
1854
+ // row itself carried the click.
1855
+ className: "flex h-full min-w-0 flex-1 items-center gap-1 text-left",
1856
+ children: /* @__PURE__ */ jsxs28(Fragment5, { children: [
1857
+ chevron && /* @__PURE__ */ jsx41(
1858
+ IconChevronRight2,
1859
+ {
1860
+ size: 12,
1861
+ stroke: 1.5,
1862
+ className: cn("shrink-0 text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
1863
+ }
1864
+ ),
1865
+ /* @__PURE__ */ jsx41(SectionLabel, { children: title })
1866
+ ] })
1867
+ }
1868
+ });
1826
1869
  return /* @__PURE__ */ jsxs28(
1827
1870
  "div",
1828
1871
  {
1829
1872
  className: cn(
1830
- "flex h-[32px] items-center justify-between rounded-lg px-2 transition-colors",
1831
- isHovered && "bg-bg-hover",
1832
- chevron && "cursor-pointer",
1873
+ "group flex h-[32px] items-center gap-1 rounded-lg px-2 transition-colors",
1874
+ // The fill says "this does something": a row with a toggle or actions
1875
+ // lights up, a fixed heading over rows does not (2026-09-09, the
1876
+ // Sidebar's fixed group).
1877
+ (chevron || actions && actions.length > 0) && "hover:bg-bg-hover",
1833
1878
  className
1834
1879
  ),
1835
- onClick: chevron ? onToggle : void 0,
1836
- onMouseEnter: () => setIsHovered(true),
1837
- onMouseLeave: () => setIsHovered(false),
1838
1880
  children: [
1839
- /* @__PURE__ */ jsxs28("div", { className: "flex shrink-0 items-center gap-1", children: [
1840
- chevron && /* @__PURE__ */ jsx41(
1841
- IconChevronRight2,
1842
- {
1843
- size: 12,
1844
- stroke: 1.5,
1845
- className: cn("text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
1846
- }
1847
- ),
1848
- /* @__PURE__ */ jsx41(SectionLabel, { children: title })
1849
- ] }),
1850
- (showActions === "always" || isHovered) && actions && actions.length > 0 && /* @__PURE__ */ jsx41("div", { className: "flex items-center gap-1", children: actions.map((action) => /* @__PURE__ */ jsx41(
1851
- IconButton,
1881
+ titleElement,
1882
+ actions && actions.length > 0 && /* @__PURE__ */ jsx41(
1883
+ "div",
1852
1884
  {
1853
- tooltip: action.tooltip,
1854
- "aria-label": action.tooltip,
1855
- onClick: (event) => {
1856
- event.stopPropagation();
1857
- action.onClick();
1858
- },
1859
- children: action.icon
1860
- },
1861
- action.tooltip
1862
- )) })
1885
+ className: cn(
1886
+ "-mr-1 flex shrink-0 items-center gap-1",
1887
+ showActions === "hover" && "opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100"
1888
+ ),
1889
+ children: actions.map((action) => /* @__PURE__ */ jsx41(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip))
1890
+ }
1891
+ )
1863
1892
  ]
1864
1893
  }
1865
1894
  );
1866
1895
  }
1867
1896
 
1897
+ // src/CollapsibleSection.tsx
1898
+ import { useState as useState6 } from "react";
1899
+ import { Collapsible } from "@base-ui/react/collapsible";
1900
+ import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
1901
+ var OPEN = "open";
1902
+ var CLOSED = "closed";
1903
+ function readStored(key) {
1904
+ if (!key) return void 0;
1905
+ try {
1906
+ const value = window.localStorage.getItem(key);
1907
+ return value === OPEN ? true : value === CLOSED ? false : void 0;
1908
+ } catch {
1909
+ return void 0;
1910
+ }
1911
+ }
1912
+ function writeStored(key, open) {
1913
+ if (!key) return;
1914
+ try {
1915
+ window.localStorage.setItem(key, open ? OPEN : CLOSED);
1916
+ } catch {
1917
+ }
1918
+ }
1919
+ function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, storageKey, actions, showActions, children, className, contentClassName }) {
1920
+ const [openState, setOpenState] = useState6(() => readStored(storageKey) ?? defaultOpen);
1921
+ const open = openProp ?? openState;
1922
+ const setOpen = (next) => {
1923
+ setOpenState(next);
1924
+ writeStored(storageKey, next);
1925
+ onOpenChange?.(next);
1926
+ };
1927
+ return /* @__PURE__ */ jsxs29(Collapsible.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
1928
+ /* @__PURE__ */ jsx42(SectionHeader, { title, chevron: true, isExpanded: open, actions, showActions, className: "shrink-0", render: /* @__PURE__ */ jsx42(Collapsible.Trigger, {}) }),
1929
+ /* @__PURE__ */ jsx42(
1930
+ Collapsible.Panel,
1931
+ {
1932
+ hiddenUntilFound: true,
1933
+ className: "h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none data-[starting-style]:h-0 data-[ending-style]:h-0",
1934
+ children: /* @__PURE__ */ jsx42("div", { className: cn("flex flex-col", contentClassName), children })
1935
+ }
1936
+ )
1937
+ ] });
1938
+ }
1939
+
1868
1940
  // src/Tabs.tsx
1869
1941
  import { Tabs as BaseTabs } from "@base-ui/react/tabs";
1870
- import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
1942
+ import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
1871
1943
  function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
1872
- return /* @__PURE__ */ jsx42(
1944
+ return /* @__PURE__ */ jsx43(
1873
1945
  BaseTabs.Root,
1874
1946
  {
1875
1947
  value: active,
@@ -1877,14 +1949,14 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
1877
1949
  if (details.reason === "none") onChange(value);
1878
1950
  },
1879
1951
  className,
1880
- children: /* @__PURE__ */ jsx42(
1952
+ children: /* @__PURE__ */ jsx43(
1881
1953
  BaseTabs.List,
1882
1954
  {
1883
1955
  activateOnFocus: true,
1884
1956
  "aria-label": aria["aria-label"],
1885
1957
  "aria-labelledby": aria["aria-labelledby"],
1886
1958
  className: "flex items-center gap-2",
1887
- children: tabs.map((tab) => /* @__PURE__ */ jsxs29(
1959
+ children: tabs.map((tab) => /* @__PURE__ */ jsxs30(
1888
1960
  BaseTabs.Tab,
1889
1961
  {
1890
1962
  value: tab.id,
@@ -1897,9 +1969,9 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
1897
1969
  ),
1898
1970
  children: [
1899
1971
  tab.icon,
1900
- /* @__PURE__ */ jsxs29("span", { className: "flex items-baseline", children: [
1972
+ /* @__PURE__ */ jsxs30("span", { className: "flex items-baseline", children: [
1901
1973
  tab.label,
1902
- tab.count !== void 0 ? /* @__PURE__ */ jsx42("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
1974
+ tab.count !== void 0 ? /* @__PURE__ */ jsx43("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
1903
1975
  ] })
1904
1976
  ]
1905
1977
  },
@@ -1915,7 +1987,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
1915
1987
  import { createContext as createContext2, useCallback as useCallback3, useContext as useContext2, useEffect as useEffect3, useMemo as useMemo3, useState as useState7 } from "react";
1916
1988
  import { createPortal as createPortal2 } from "react-dom";
1917
1989
  import { IconCircleCheck } from "@tabler/icons-react";
1918
- import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
1990
+ import { jsx as jsx44, jsxs as jsxs31 } from "react/jsx-runtime";
1919
1991
  var SURFACE_STYLES = {
1920
1992
  success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
1921
1993
  brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
@@ -1933,7 +2005,7 @@ var ACTION_BORDER_STYLES = {
1933
2005
  };
1934
2006
  function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
1935
2007
  const hasAction = !!(actionLabel && onAction);
1936
- return /* @__PURE__ */ jsxs30(
2008
+ return /* @__PURE__ */ jsxs31(
1937
2009
  "div",
1938
2010
  {
1939
2011
  className: cn(
@@ -1945,11 +2017,11 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
1945
2017
  className
1946
2018
  ),
1947
2019
  children: [
1948
- /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2 shrink-0", children: [
1949
- leadingIcon && /* @__PURE__ */ jsx43(IconCircleCheck, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) }),
1950
- /* @__PURE__ */ jsx43("span", { className: "font-normal text-[14px] leading-[1.4] text-text-primary whitespace-nowrap", children: label })
2020
+ /* @__PURE__ */ jsxs31("div", { className: "flex items-center gap-2 shrink-0", children: [
2021
+ leadingIcon && /* @__PURE__ */ jsx44(IconCircleCheck, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) }),
2022
+ /* @__PURE__ */ jsx44("span", { className: "font-normal text-[14px] leading-[1.4] text-text-primary whitespace-nowrap", children: label })
1951
2023
  ] }),
1952
- hasAction && /* @__PURE__ */ jsx43(
2024
+ hasAction && /* @__PURE__ */ jsx44(
1953
2025
  "button",
1954
2026
  {
1955
2027
  type: "button",
@@ -1959,7 +2031,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
1959
2031
  ACTION_BORDER_STYLES[type],
1960
2032
  type === "neutral" ? "hover:border-border-strong" : "hover:opacity-80"
1961
2033
  ),
1962
- children: /* @__PURE__ */ jsx43("span", { className: "font-medium text-[12px] leading-[12px] text-text-primary whitespace-nowrap", children: actionLabel })
2034
+ children: /* @__PURE__ */ jsx44("span", { className: "font-medium text-[12px] leading-[12px] text-text-primary whitespace-nowrap", children: actionLabel })
1963
2035
  }
1964
2036
  )
1965
2037
  ]
@@ -1986,10 +2058,10 @@ function ToastProvider({ children }) {
1986
2058
  return () => clearTimeout(timer);
1987
2059
  }, [toast]);
1988
2060
  const value = useMemo3(() => ({ showToast, dismissToast }), [showToast, dismissToast]);
1989
- return /* @__PURE__ */ jsxs30(ToastContext.Provider, { value, children: [
2061
+ return /* @__PURE__ */ jsxs31(ToastContext.Provider, { value, children: [
1990
2062
  children,
1991
2063
  toast && createPortal2(
1992
- /* @__PURE__ */ jsx43("div", { className: "fixed bottom-4 left-4 z-[100] pointer-events-none", children: /* @__PURE__ */ jsx43(
2064
+ /* @__PURE__ */ jsx44("div", { className: "fixed bottom-4 left-4 z-[100] pointer-events-none", children: /* @__PURE__ */ jsx44(
1993
2065
  Toast,
1994
2066
  {
1995
2067
  className: "pointer-events-auto",
@@ -2022,6 +2094,7 @@ export {
2022
2094
  Checkbox,
2023
2095
  Chip,
2024
2096
  ChipInput,
2097
+ CollapsibleSection,
2025
2098
  ConfirmDialog,
2026
2099
  DialogShell,
2027
2100
  Divider,