@stackone/malachite 2.71.0 → 2.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,148 +1,165 @@
1
- import { jsx as e, jsxs as a } from "react/jsx-runtime";
2
- import { useId as k, useState as _, useRef as u, useEffect as q } from "react";
3
- import { createPortal as U } from "react-dom";
4
- import { ShadowRootWrapper as G } from "../ShadowRootWrapper.js";
5
- import H from "./CalloutStrip.js";
6
- import J from "./CustomIcons/ArrowLeftIcon.js";
7
- import K from "./CustomIcons/DismissIcon.js";
8
- import z from "./Typography/EllipsisText.js";
9
- import { useOverlayBehaviour as Q, OVERLAY_ICON_BUTTON_CLASSES as E } from "./overlayBehaviour.js";
10
- import { OVERLAY_ELEVATED_ATTR as Z, overlayIdentity as O } from "./portalOverlay.js";
11
- const P = 200, ee = (t) => typeof t == "number" ? `${t}px` : t, me = ({
12
- open: t,
13
- onClose: c,
14
- title: o,
15
- subtitle: d,
16
- titleExtra: f,
1
+ import { jsx as e, jsxs as r } from "react/jsx-runtime";
2
+ import { useId as V, useState as B, useRef as u, useEffect as Z } from "react";
3
+ import { createPortal as ee } from "react-dom";
4
+ import { ShadowRootWrapper as re } from "../ShadowRootWrapper.js";
5
+ import le from "./CalloutStrip.js";
6
+ import ae from "./CustomIcons/ArrowLeftIcon.js";
7
+ import te from "./CustomIcons/DismissIcon.js";
8
+ import C from "./Typography/EllipsisText.js";
9
+ import { useOverlayBehaviour as ie, OVERLAY_ICON_BUTTON_CLASSES as L } from "./overlayBehaviour.js";
10
+ import { OVERLAY_ELEVATED_ATTR as ne, overlayIdentity as j } from "./portalOverlay.js";
11
+ const M = 200, se = (a) => typeof a == "number" ? `${a}px` : a, ve = ({
12
+ open: a,
13
+ onClose: d,
14
+ title: s,
15
+ subtitle: o,
16
+ subtitlePlacement: W = "inline",
17
+ titleExtra: x,
17
18
  description: m,
18
- headerDivider: V = !1,
19
- icon: x,
19
+ toolbar: f,
20
+ headerDivider: D = !1,
21
+ icon: h,
20
22
  headerExtra: b,
21
- footer: h,
22
- onBack: v,
23
- maxWidth: C = 1080,
24
- "aria-label": L,
23
+ footer: v,
24
+ onBack: N,
25
+ maxWidth: F = 1080,
26
+ "aria-label": X,
25
27
  "aria-labelledby": y,
26
- bodyPadding: N = !0,
27
- stacking: j = "default",
28
+ bodyPadding: g = !0,
29
+ stacking: Y = "default",
28
30
  callouts: p,
29
- renderLink: B,
30
- children: g
31
+ renderLink: q,
32
+ children: w
31
33
  }) => {
32
- const T = k(), I = k(), [w, S] = _(!1), [M, R] = _(!1), i = u(null), r = u(null), $ = u(null), {
33
- ref: W,
34
- isTopmost: D,
35
- zIndex: F,
36
- elevated: X
37
- } = Q({
38
- open: t,
39
- onClose: c,
40
- elevated: j === "above-app-overlays",
34
+ const T = V(), I = V(), [S, k] = B(!1), [U, R] = B(!1), i = u(null), l = u(null), $ = u(null), {
35
+ ref: G,
36
+ isTopmost: H,
37
+ zIndex: J,
38
+ elevated: K
39
+ } = ie({
40
+ open: a,
41
+ onClose: d,
42
+ elevated: Y === "above-app-overlays",
41
43
  hostRef: $
42
44
  });
43
- if (q(() => (t ? (R(!0), r.current && (clearTimeout(r.current), r.current = null), i.current = requestAnimationFrame(() => {
44
- i.current = null, S(!0);
45
- })) : (S(!1), r.current = setTimeout(() => {
46
- r.current = null, R(!1);
47
- }, P)), () => {
48
- i.current !== null && (cancelAnimationFrame(i.current), i.current = null), r.current && (clearTimeout(r.current), r.current = null);
49
- }), [t]), !M)
45
+ if (Z(() => (a ? (R(!0), l.current && (clearTimeout(l.current), l.current = null), i.current = requestAnimationFrame(() => {
46
+ i.current = null, k(!0);
47
+ })) : (k(!1), l.current = setTimeout(() => {
48
+ l.current = null, R(!1);
49
+ }, M)), () => {
50
+ i.current !== null && (cancelAnimationFrame(i.current), i.current = null), l.current && (clearTimeout(l.current), l.current = null);
51
+ }), [a]), !U)
50
52
  return null;
51
- const l = p == null ? void 0 : p.filter((n) => n.message.trim()), A = !!(l != null && l.length), Y = N ? /* @__PURE__ */ e("div", { className: A ? "p-[28px]" : "py-[28px]", children: g }) : g;
52
- return U(
53
+ const t = p == null ? void 0 : p.filter((n) => n.message.trim()), A = !!(t != null && t.length), Q = g ? /* @__PURE__ */ e("div", { className: A ? "p-[28px]" : "py-[28px]", children: w }) : w, E = W === "below" && !!o, _ = /* @__PURE__ */ e(
54
+ "span",
55
+ {
56
+ className: E ? "flex min-w-0 shrink" : "flex min-w-0 max-w-full shrink-0",
57
+ children: /* @__PURE__ */ e(
58
+ C,
59
+ {
60
+ tooltip: s,
61
+ tooltipWhenTruncated: !0,
62
+ tooltipPlacement: "bottom",
63
+ className: "min-w-0 text-[length:var(--malachite-font-size-15,15px)] font-semibold",
64
+ children: s
65
+ }
66
+ )
67
+ }
68
+ ), z = o ? /* @__PURE__ */ e(
69
+ C,
70
+ {
71
+ tooltip: o,
72
+ tooltipWhenTruncated: !0,
73
+ tooltipPlacement: "bottom",
74
+ color: "secondary",
75
+ className: "min-w-0 text-[13px]",
76
+ children: o
77
+ }
78
+ ) : null, O = x ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: x }) : null, P = b ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-baseline", children: b }) : null;
79
+ return ee(
53
80
  // Host carries the stacking context — ShadowRootWrapper's `isolation` would
54
81
  // otherwise flatten our z-index and let sticky page elements paint over us.
55
82
  /* @__PURE__ */ e(
56
- G,
83
+ re,
57
84
  {
58
85
  hostRef: $,
59
- hostStyle: { position: "relative", zIndex: F },
60
- hostProps: X ? { ...O("sidepanel"), [Z]: "" } : O("sidepanel"),
61
- children: /* @__PURE__ */ a("div", { className: "fixed inset-0 z-[1000]", children: [
86
+ hostStyle: { position: "relative", zIndex: J },
87
+ hostProps: K ? { ...j("sidepanel"), [ne]: "" } : j("sidepanel"),
88
+ children: /* @__PURE__ */ r("div", { className: "fixed inset-0 z-[1000]", children: [
62
89
  /* @__PURE__ */ e(
63
90
  "div",
64
91
  {
65
92
  "aria-hidden": "true",
66
- onClick: c,
67
- className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${w ? "opacity-100" : "opacity-0"}`
93
+ onClick: d,
94
+ className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${S ? "opacity-100" : "opacity-0"}`
68
95
  }
69
96
  ),
70
- /* @__PURE__ */ a(
97
+ /* @__PURE__ */ r(
71
98
  "div",
72
99
  {
73
- ref: W,
100
+ ref: G,
74
101
  role: "dialog",
75
- "aria-modal": D ? "true" : void 0,
102
+ "aria-modal": H ? "true" : void 0,
76
103
  "aria-describedby": [
77
- ...(l ?? []).map((n, s) => `${T}-${s}`),
104
+ ...(t ?? []).map((n, c) => `${T}-${c}`),
78
105
  m ? I : null
79
106
  ].filter(Boolean).join(" ") || void 0,
80
107
  tabIndex: -1,
81
- "aria-label": y ? void 0 : L ?? (typeof o == "string" ? o : void 0),
108
+ "aria-label": y ? void 0 : X ?? (typeof s == "string" ? s : void 0),
82
109
  "aria-labelledby": y,
83
110
  className: "absolute top-[8px] right-[8px] bottom-[8px] flex flex-col overflow-hidden rounded-[20px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-lg)]",
84
111
  style: {
85
- width: `min(calc(100% - 16px), ${ee(C)})`,
112
+ width: `min(calc(100% - 16px), ${se(F)})`,
86
113
  // Inline: Tailwind translate utilities silently break inside
87
114
  // shadow roots (see CLAUDE.md Shadow DOM caveats).
88
- transform: w ? "translateX(0)" : "translateX(calc(100% + 16px))",
89
- transition: `transform ${P}ms ease-in-out`
115
+ transform: S ? "translateX(0)" : "translateX(calc(100% + 16px))",
116
+ transition: `transform ${M}ms ease-in-out`
90
117
  },
91
118
  children: [
92
- /* @__PURE__ */ a(
119
+ /* @__PURE__ */ r(
93
120
  "div",
94
121
  {
95
- className: `flex flex-col gap-[20px] px-[20px] py-[18px] ${V ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
122
+ className: `flex flex-col gap-[20px] px-[20px] py-[18px] ${D ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
96
123
  children: [
97
- /* @__PURE__ */ a("div", { className: "flex items-center gap-[12px]", children: [
98
- v ? /* @__PURE__ */ e(
124
+ /* @__PURE__ */ r("div", { className: "flex items-center gap-[12px]", children: [
125
+ N ? /* @__PURE__ */ e(
99
126
  "button",
100
127
  {
101
128
  type: "button",
102
129
  "aria-label": "Back",
103
- onClick: v,
104
- className: E,
105
- children: /* @__PURE__ */ e(J, { size: 16 })
130
+ onClick: N,
131
+ className: L,
132
+ children: /* @__PURE__ */ e(ae, { size: 16 })
106
133
  }
107
134
  ) : null,
108
- x ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: x }) : null,
109
- /* @__PURE__ */ a("div", { className: "flex min-w-0 flex-1 items-baseline gap-[12px]", children: [
110
- /* @__PURE__ */ a("div", { className: "flex min-w-0 flex-1 items-baseline gap-[8px]", children: [
111
- /* @__PURE__ */ a("div", { className: "flex min-w-0 items-baseline gap-[8px]", children: [
112
- /* @__PURE__ */ e("span", { className: "flex min-w-0 max-w-full shrink-0", children: /* @__PURE__ */ e(
113
- z,
114
- {
115
- tooltip: o,
116
- tooltipWhenTruncated: !0,
117
- tooltipPlacement: "bottom",
118
- className: "min-w-0 text-[length:var(--malachite-font-size-15,15px)] font-semibold",
119
- children: o
120
- }
121
- ) }),
122
- d ? /* @__PURE__ */ e(
123
- z,
124
- {
125
- tooltip: d,
126
- tooltipWhenTruncated: !0,
127
- tooltipPlacement: "bottom",
128
- color: "secondary",
129
- className: "min-w-0 text-[13px]",
130
- children: d
131
- }
132
- ) : null
135
+ h ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: h }) : null,
136
+ E ? /* @__PURE__ */ r("div", { className: "flex min-w-0 flex-1 items-center gap-[12px]", children: [
137
+ /* @__PURE__ */ r("div", { className: "flex min-w-0 flex-1 flex-col gap-[2px]", children: [
138
+ /* @__PURE__ */ r("div", { className: "flex min-w-0 items-baseline gap-[8px]", children: [
139
+ _,
140
+ O
133
141
  ] }),
134
- f ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: f }) : null
142
+ z
135
143
  ] }),
136
- b ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-baseline", children: b }) : null
144
+ P
145
+ ] }) : /* @__PURE__ */ r("div", { className: "flex min-w-0 flex-1 items-baseline gap-[12px]", children: [
146
+ /* @__PURE__ */ r("div", { className: "flex min-w-0 flex-1 items-baseline gap-[8px]", children: [
147
+ /* @__PURE__ */ r("div", { className: "flex min-w-0 items-baseline gap-[8px]", children: [
148
+ _,
149
+ z
150
+ ] }),
151
+ O
152
+ ] }),
153
+ P
137
154
  ] }),
138
155
  /* @__PURE__ */ e(
139
156
  "button",
140
157
  {
141
158
  type: "button",
142
159
  "aria-label": "Close",
143
- onClick: c,
144
- className: E,
145
- children: /* @__PURE__ */ e(K, { size: 10 })
160
+ onClick: d,
161
+ className: L,
162
+ children: /* @__PURE__ */ e(te, { size: 10 })
146
163
  }
147
164
  )
148
165
  ] }),
@@ -157,26 +174,27 @@ const P = 200, ee = (t) => typeof t == "number" ? `${t}px` : t, me = ({
157
174
  ]
158
175
  }
159
176
  ),
160
- /* @__PURE__ */ a(
177
+ f ? /* @__PURE__ */ e("div", { className: "shrink-0 px-[16px] pt-[16px] pb-[8px]", children: f }) : null,
178
+ /* @__PURE__ */ r(
161
179
  "div",
162
180
  {
163
- className: `min-h-0 flex-1 overflow-y-auto ${N && !A ? "px-[28px]" : ""}`,
181
+ className: `min-h-0 flex-1 overflow-y-auto ${g && !A ? "px-[28px]" : ""}`,
164
182
  children: [
165
- l == null ? void 0 : l.map((n, s) => /* @__PURE__ */ e(
166
- H,
183
+ t == null ? void 0 : t.map((n, c) => /* @__PURE__ */ e(
184
+ le,
167
185
  {
168
- id: `${T}-${s}`,
186
+ id: `${T}-${c}`,
169
187
  type: n.type,
170
188
  message: n.message,
171
- renderLink: B
189
+ renderLink: q
172
190
  },
173
- s
191
+ c
174
192
  )),
175
- Y
193
+ Q
176
194
  ]
177
195
  }
178
196
  ),
179
- h ? /* @__PURE__ */ e("div", { className: "border-0 border-t border-solid border-[var(--malachite-card-border)] px-[24px] py-[16px]", children: h }) : null
197
+ v ? /* @__PURE__ */ e("div", { className: "border-0 border-t border-solid border-[var(--malachite-card-border)] px-[24px] py-[16px]", children: v }) : null
180
198
  ]
181
199
  }
182
200
  )
@@ -187,7 +205,7 @@ const P = 200, ee = (t) => typeof t == "number" ? `${t}px` : t, me = ({
187
205
  );
188
206
  };
189
207
  export {
190
- me as SidePanel,
191
- me as default
208
+ ve as SidePanel,
209
+ ve as default
192
210
  };
193
211
  //# sourceMappingURL=SidePanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanel.js","sources":["../../src/components/SidePanel.tsx"],"sourcesContent":["import React, { useEffect, useId, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport type { AlertType } from './Alert';\nimport CalloutStrip from './CalloutStrip';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport type { RenderLink } from './PageLayout/types';\nimport EllipsisText from './Typography/EllipsisText';\nimport { OVERLAY_ICON_BUTTON_CLASSES, useOverlayBehaviour } from './overlayBehaviour';\nimport { OVERLAY_ELEVATED_ATTR, overlayIdentity } from './portalOverlay';\n\nexport interface SidePanelProps {\n open: boolean;\n /** Dismiss handler — close button, ESC, or overlay click. */\n onClose: () => void;\n title: React.ReactNode;\n /** Secondary text, inline after the title. */\n subtitle?: React.ReactNode;\n /** Content at the end of the title row, after the subtitle (e.g. a status tag). */\n titleExtra?: React.ReactNode;\n /** Block paragraph below the title row, spanning the header width. Announced as the panel's description. */\n description?: React.ReactNode;\n /** Divider under the header. Default: false. */\n headerDivider?: boolean;\n /** Leading header slot, typically a logo or icon. */\n icon?: React.ReactNode;\n /** Content pinned right in the header, before the close button. */\n headerExtra?: React.ReactNode;\n footer?: React.ReactNode;\n /** Renders a back button before the header icon. */\n onBack?: () => void;\n /** Maximum panel width. Default: 1080. */\n maxWidth?: number | string;\n /** Accessible dialog name; required when `title` isn't a plain string. */\n 'aria-label'?: string;\n /** ID of a visible element naming the dialog (alternative to `aria-label`). */\n 'aria-labelledby'?: string;\n /** Whether the body gets default padding. Default: true. */\n bodyPadding?: boolean;\n /** `above-app-overlays` lifts the overlay stack clear of chrome pinned near max-int. */\n stacking?: 'default' | 'above-app-overlays';\n /** Full-width Alert bands at the top of the body, above `children`, in order. Unaffected by\n * `bodyPadding`, and announced ahead of `description`. The message is markdown. */\n callouts?: { type?: AlertType; message: string }[];\n /** Routes root-relative links in `callouts` through the app's router; see `MarkdownBlock`. */\n renderLink?: RenderLink;\n children: React.ReactNode;\n}\n\nconst TRANSITION_MS = 200;\n\nconst toCssSize = (value: number | string): string =>\n typeof value === 'number' ? `${value}px` : value;\n\n/**\n * A right-hand slide-in overlay panel (drawer) for inspecting or editing an entity\n * without leaving the page. Portals to `document.body`, locks background scroll and\n * traps keyboard focus while open (restoring both on close), dismisses on ESC\n * (topmost open overlay only), overlay click or the close button, and exposes header\n * (back/icon/title/subtitle/extra), scrollable body and optional footer slots.\n */\nconst SidePanel: React.FC<SidePanelProps> = ({\n open,\n onClose,\n title,\n subtitle,\n titleExtra,\n description,\n headerDivider = false,\n icon,\n headerExtra,\n footer,\n onBack,\n maxWidth = 1080,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n bodyPadding = true,\n stacking = 'default',\n callouts,\n renderLink,\n children,\n}) => {\n const calloutId = useId();\n const descriptionId = useId();\n const [isVisible, setIsVisible] = useState(false);\n const [isMounted, setIsMounted] = useState(false);\n const frameRef = useRef<number | null>(null);\n const unmountTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hostRef = useRef<HTMLDivElement | null>(null);\n const {\n ref: handlePanelRef,\n isTopmost,\n zIndex,\n elevated,\n } = useOverlayBehaviour({\n open,\n onClose,\n elevated: stacking === 'above-app-overlays',\n hostRef,\n });\n\n useEffect(() => {\n if (open) {\n setIsMounted(true);\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n frameRef.current = requestAnimationFrame(() => {\n frameRef.current = null;\n setIsVisible(true);\n });\n } else {\n setIsVisible(false);\n unmountTimerRef.current = setTimeout(() => {\n unmountTimerRef.current = null;\n setIsMounted(false);\n }, TRANSITION_MS);\n }\n return () => {\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n };\n }, [open]);\n\n if (!isMounted) {\n return null;\n }\n\n const shownCallouts = callouts?.filter((callout) => callout.message.trim());\n const hasCallouts = !!shownCallouts?.length;\n const paddedBody = bodyPadding ? (\n <div className={hasCallouts ? 'p-[28px]' : 'py-[28px]'}>{children}</div>\n ) : (\n children\n );\n\n return createPortal(\n // Host carries the stacking context — ShadowRootWrapper's `isolation` would\n // otherwise flatten our z-index and let sticky page elements paint over us.\n <ShadowRootWrapper\n hostRef={hostRef}\n hostStyle={{ position: 'relative', zIndex }}\n hostProps={\n elevated\n ? { ...overlayIdentity('sidepanel'), [OVERLAY_ELEVATED_ATTR]: '' }\n : overlayIdentity('sidepanel')\n }\n >\n <div className=\"fixed inset-0 z-[1000]\">\n <div\n aria-hidden=\"true\"\n onClick={onClose}\n className={`absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${\n isVisible ? 'opacity-100' : 'opacity-0'\n }`}\n />\n <div\n ref={handlePanelRef}\n role=\"dialog\"\n // Only the topmost overlay may claim it, or a screen reader can still\n // browse the one underneath.\n aria-modal={isTopmost ? 'true' : undefined}\n aria-describedby={\n [\n ...(shownCallouts ?? []).map((_, index) => `${calloutId}-${index}`),\n description ? descriptionId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n }\n tabIndex={-1}\n // Prefer aria-labelledby; only fall back to aria-label when it's absent.\n aria-label={\n ariaLabelledBy\n ? undefined\n : (ariaLabel ?? (typeof title === 'string' ? title : undefined))\n }\n aria-labelledby={ariaLabelledBy}\n className=\"absolute top-[8px] right-[8px] bottom-[8px] flex flex-col overflow-hidden rounded-[20px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-lg)]\"\n style={{\n width: `min(calc(100% - 16px), ${toCssSize(maxWidth)})`,\n // Inline: Tailwind translate utilities silently break inside\n // shadow roots (see CLAUDE.md Shadow DOM caveats).\n transform: isVisible ? 'translateX(0)' : 'translateX(calc(100% + 16px))',\n transition: `transform ${TRANSITION_MS}ms ease-in-out`,\n }}\n >\n <div\n className={`flex flex-col gap-[20px] px-[20px] py-[18px] ${\n headerDivider\n ? 'border-0 border-b border-solid border-[var(--malachite-card-border)]'\n : ''\n }`}\n >\n <div className=\"flex items-center gap-[12px]\">\n {onBack ? (\n <button\n type=\"button\"\n aria-label=\"Back\"\n onClick={onBack}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <ArrowLeftIcon size={16} />\n </button>\n ) : null}\n {icon ? (\n <span className=\"flex shrink-0 items-center\">{icon}</span>\n ) : null}\n <div className=\"flex min-w-0 flex-1 items-baseline gap-[12px]\">\n <div className=\"flex min-w-0 flex-1 items-baseline gap-[8px]\">\n <div className=\"flex min-w-0 items-baseline gap-[8px]\">\n <span className=\"flex min-w-0 max-w-full shrink-0\">\n <EllipsisText\n tooltip={title}\n tooltipWhenTruncated\n tooltipPlacement=\"bottom\"\n className=\"min-w-0 text-[length:var(--malachite-font-size-15,15px)] font-semibold\"\n >\n {title}\n </EllipsisText>\n </span>\n {subtitle ? (\n <EllipsisText\n tooltip={subtitle}\n tooltipWhenTruncated\n tooltipPlacement=\"bottom\"\n color=\"secondary\"\n className=\"min-w-0 text-[13px]\"\n >\n {subtitle}\n </EllipsisText>\n ) : null}\n </div>\n {titleExtra ? (\n <span className=\"flex shrink-0 items-center\">\n {titleExtra}\n </span>\n ) : null}\n </div>\n {headerExtra ? (\n <span className=\"flex shrink-0 items-baseline\">\n {headerExtra}\n </span>\n ) : null}\n </div>\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={onClose}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <DismissIcon size={10} />\n </button>\n </div>\n {description ? (\n <div\n id={descriptionId}\n className=\"text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]\"\n >\n {description}\n </div>\n ) : null}\n </div>\n {/* Callouts move the horizontal padding inward so their strips run full-bleed. */}\n <div\n className={`min-h-0 flex-1 overflow-y-auto ${bodyPadding && !hasCallouts ? 'px-[28px]' : ''}`}\n >\n {shownCallouts?.map((callout, index) => (\n <CalloutStrip\n key={index}\n id={`${calloutId}-${index}`}\n type={callout.type}\n message={callout.message}\n renderLink={renderLink}\n />\n ))}\n {paddedBody}\n </div>\n {footer ? (\n <div className=\"border-0 border-t border-solid border-[var(--malachite-card-border)] px-[24px] py-[16px]\">\n {footer}\n </div>\n ) : null}\n </div>\n </div>\n </ShadowRootWrapper>,\n document.body,\n );\n};\n\nexport default SidePanel;\nexport { SidePanel };\n"],"names":["TRANSITION_MS","toCssSize","value","SidePanel","open","onClose","title","subtitle","titleExtra","description","headerDivider","icon","headerExtra","footer","onBack","maxWidth","ariaLabel","ariaLabelledBy","bodyPadding","stacking","callouts","renderLink","children","calloutId","useId","descriptionId","isVisible","setIsVisible","useState","isMounted","setIsMounted","frameRef","useRef","unmountTimerRef","hostRef","handlePanelRef","isTopmost","zIndex","elevated","useOverlayBehaviour","useEffect","shownCallouts","callout","hasCallouts","paddedBody","jsx","createPortal","ShadowRootWrapper","overlayIdentity","OVERLAY_ELEVATED_ATTR","jsxs","_","index","OVERLAY_ICON_BUTTON_CLASSES","ArrowLeftIcon","EllipsisText","DismissIcon","CalloutStrip"],"mappings":"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"}
1
+ {"version":3,"file":"SidePanel.js","sources":["../../src/components/SidePanel.tsx"],"sourcesContent":["import React, { useEffect, useId, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport type { AlertType } from './Alert';\nimport CalloutStrip from './CalloutStrip';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport type { RenderLink } from './PageLayout/types';\nimport EllipsisText from './Typography/EllipsisText';\nimport { OVERLAY_ICON_BUTTON_CLASSES, useOverlayBehaviour } from './overlayBehaviour';\nimport { OVERLAY_ELEVATED_ATTR, overlayIdentity } from './portalOverlay';\n\nexport interface SidePanelProps {\n open: boolean;\n /** Dismiss handler — close button, ESC, or overlay click. */\n onClose: () => void;\n title: React.ReactNode;\n subtitle?: React.ReactNode;\n /** `below` stacks the subtitle under the title, so neither truncates the other. */\n subtitlePlacement?: 'inline' | 'below';\n /** Content at the end of the title row, after the subtitle (e.g. a status tag). */\n titleExtra?: React.ReactNode;\n /** Block paragraph below the title row, spanning the header width. Announced as the panel's description. */\n description?: React.ReactNode;\n /** Pinned between the header and the scrolling body. */\n toolbar?: React.ReactNode;\n /** Divider under the header. Default: false. */\n headerDivider?: boolean;\n /** Leading header slot, typically a logo or icon. */\n icon?: React.ReactNode;\n /** Content pinned right in the header, before the close button. */\n headerExtra?: React.ReactNode;\n footer?: React.ReactNode;\n /** Renders a back button before the header icon. */\n onBack?: () => void;\n /** Maximum panel width. Default: 1080. */\n maxWidth?: number | string;\n /** Accessible dialog name; required when `title` isn't a plain string. */\n 'aria-label'?: string;\n /** ID of a visible element naming the dialog (alternative to `aria-label`). */\n 'aria-labelledby'?: string;\n /** Whether the body gets default padding. Default: true. */\n bodyPadding?: boolean;\n /** `above-app-overlays` lifts the overlay stack clear of chrome pinned near max-int. */\n stacking?: 'default' | 'above-app-overlays';\n /** Full-width Alert bands at the top of the body, above `children`, in order. Unaffected by\n * `bodyPadding`, and announced ahead of `description`. The message is markdown. */\n callouts?: { type?: AlertType; message: string }[];\n /** Routes root-relative links in `callouts` through the app's router; see `MarkdownBlock`. */\n renderLink?: RenderLink;\n children: React.ReactNode;\n}\n\nconst TRANSITION_MS = 200;\n\nconst toCssSize = (value: number | string): string =>\n typeof value === 'number' ? `${value}px` : value;\n\n/**\n * A right-hand slide-in overlay panel (drawer) for inspecting or editing an entity\n * without leaving the page. Portals to `document.body`, locks background scroll and\n * traps keyboard focus while open (restoring both on close), dismisses on ESC\n * (topmost open overlay only), overlay click or the close button, and exposes header\n * (back/icon/title/subtitle/extra), scrollable body and optional footer slots.\n */\nconst SidePanel: React.FC<SidePanelProps> = ({\n open,\n onClose,\n title,\n subtitle,\n subtitlePlacement = 'inline',\n titleExtra,\n description,\n toolbar,\n headerDivider = false,\n icon,\n headerExtra,\n footer,\n onBack,\n maxWidth = 1080,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n bodyPadding = true,\n stacking = 'default',\n callouts,\n renderLink,\n children,\n}) => {\n const calloutId = useId();\n const descriptionId = useId();\n const [isVisible, setIsVisible] = useState(false);\n const [isMounted, setIsMounted] = useState(false);\n const frameRef = useRef<number | null>(null);\n const unmountTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hostRef = useRef<HTMLDivElement | null>(null);\n const {\n ref: handlePanelRef,\n isTopmost,\n zIndex,\n elevated,\n } = useOverlayBehaviour({\n open,\n onClose,\n elevated: stacking === 'above-app-overlays',\n hostRef,\n });\n\n useEffect(() => {\n if (open) {\n setIsMounted(true);\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n frameRef.current = requestAnimationFrame(() => {\n frameRef.current = null;\n setIsVisible(true);\n });\n } else {\n setIsVisible(false);\n unmountTimerRef.current = setTimeout(() => {\n unmountTimerRef.current = null;\n setIsMounted(false);\n }, TRANSITION_MS);\n }\n return () => {\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n };\n }, [open]);\n\n if (!isMounted) {\n return null;\n }\n\n const shownCallouts = callouts?.filter((callout) => callout.message.trim());\n const hasCallouts = !!shownCallouts?.length;\n const paddedBody = bodyPadding ? (\n <div className={hasCallouts ? 'p-[28px]' : 'py-[28px]'}>{children}</div>\n ) : (\n children\n );\n\n const subtitleBelow = subtitlePlacement === 'below' && !!subtitle;\n const titleNode = (\n <span\n className={subtitleBelow ? 'flex min-w-0 shrink' : 'flex min-w-0 max-w-full shrink-0'}\n >\n <EllipsisText\n tooltip={title}\n tooltipWhenTruncated\n tooltipPlacement=\"bottom\"\n className=\"min-w-0 text-[length:var(--malachite-font-size-15,15px)] font-semibold\"\n >\n {title}\n </EllipsisText>\n </span>\n );\n const subtitleNode = subtitle ? (\n <EllipsisText\n tooltip={subtitle}\n tooltipWhenTruncated\n tooltipPlacement=\"bottom\"\n color=\"secondary\"\n className=\"min-w-0 text-[13px]\"\n >\n {subtitle}\n </EllipsisText>\n ) : null;\n const titleExtraNode = titleExtra ? (\n <span className=\"flex shrink-0 items-center\">{titleExtra}</span>\n ) : null;\n const headerExtraNode = headerExtra ? (\n <span className=\"flex shrink-0 items-baseline\">{headerExtra}</span>\n ) : null;\n\n return createPortal(\n // Host carries the stacking context — ShadowRootWrapper's `isolation` would\n // otherwise flatten our z-index and let sticky page elements paint over us.\n <ShadowRootWrapper\n hostRef={hostRef}\n hostStyle={{ position: 'relative', zIndex }}\n hostProps={\n elevated\n ? { ...overlayIdentity('sidepanel'), [OVERLAY_ELEVATED_ATTR]: '' }\n : overlayIdentity('sidepanel')\n }\n >\n <div className=\"fixed inset-0 z-[1000]\">\n <div\n aria-hidden=\"true\"\n onClick={onClose}\n className={`absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${\n isVisible ? 'opacity-100' : 'opacity-0'\n }`}\n />\n <div\n ref={handlePanelRef}\n role=\"dialog\"\n // Only the topmost overlay may claim it, or a screen reader can still\n // browse the one underneath.\n aria-modal={isTopmost ? 'true' : undefined}\n aria-describedby={\n [\n ...(shownCallouts ?? []).map((_, index) => `${calloutId}-${index}`),\n description ? descriptionId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n }\n tabIndex={-1}\n // Prefer aria-labelledby; only fall back to aria-label when it's absent.\n aria-label={\n ariaLabelledBy\n ? undefined\n : (ariaLabel ?? (typeof title === 'string' ? title : undefined))\n }\n aria-labelledby={ariaLabelledBy}\n className=\"absolute top-[8px] right-[8px] bottom-[8px] flex flex-col overflow-hidden rounded-[20px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-lg)]\"\n style={{\n width: `min(calc(100% - 16px), ${toCssSize(maxWidth)})`,\n // Inline: Tailwind translate utilities silently break inside\n // shadow roots (see CLAUDE.md Shadow DOM caveats).\n transform: isVisible ? 'translateX(0)' : 'translateX(calc(100% + 16px))',\n transition: `transform ${TRANSITION_MS}ms ease-in-out`,\n }}\n >\n <div\n className={`flex flex-col gap-[20px] px-[20px] py-[18px] ${\n headerDivider\n ? 'border-0 border-b border-solid border-[var(--malachite-card-border)]'\n : ''\n }`}\n >\n <div className=\"flex items-center gap-[12px]\">\n {onBack ? (\n <button\n type=\"button\"\n aria-label=\"Back\"\n onClick={onBack}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <ArrowLeftIcon size={16} />\n </button>\n ) : null}\n {icon ? (\n <span className=\"flex shrink-0 items-center\">{icon}</span>\n ) : null}\n {subtitleBelow ? (\n <div className=\"flex min-w-0 flex-1 items-center gap-[12px]\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-[2px]\">\n <div className=\"flex min-w-0 items-baseline gap-[8px]\">\n {titleNode}\n {titleExtraNode}\n </div>\n {subtitleNode}\n </div>\n {headerExtraNode}\n </div>\n ) : (\n <div className=\"flex min-w-0 flex-1 items-baseline gap-[12px]\">\n <div className=\"flex min-w-0 flex-1 items-baseline gap-[8px]\">\n <div className=\"flex min-w-0 items-baseline gap-[8px]\">\n {titleNode}\n {subtitleNode}\n </div>\n {titleExtraNode}\n </div>\n {headerExtraNode}\n </div>\n )}\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={onClose}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <DismissIcon size={10} />\n </button>\n </div>\n {description ? (\n <div\n id={descriptionId}\n className=\"text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]\"\n >\n {description}\n </div>\n ) : null}\n </div>\n {toolbar ? (\n <div className=\"shrink-0 px-[16px] pt-[16px] pb-[8px]\">{toolbar}</div>\n ) : null}\n {/* Callouts move the horizontal padding inward so their strips run full-bleed. */}\n <div\n className={`min-h-0 flex-1 overflow-y-auto ${bodyPadding && !hasCallouts ? 'px-[28px]' : ''}`}\n >\n {shownCallouts?.map((callout, index) => (\n <CalloutStrip\n key={index}\n id={`${calloutId}-${index}`}\n type={callout.type}\n message={callout.message}\n renderLink={renderLink}\n />\n ))}\n {paddedBody}\n </div>\n {footer ? (\n <div className=\"border-0 border-t border-solid border-[var(--malachite-card-border)] px-[24px] py-[16px]\">\n {footer}\n </div>\n ) : null}\n </div>\n </div>\n </ShadowRootWrapper>,\n document.body,\n );\n};\n\nexport default SidePanel;\nexport { SidePanel };\n"],"names":["TRANSITION_MS","toCssSize","value","SidePanel","open","onClose","title","subtitle","subtitlePlacement","titleExtra","description","toolbar","headerDivider","icon","headerExtra","footer","onBack","maxWidth","ariaLabel","ariaLabelledBy","bodyPadding","stacking","callouts","renderLink","children","calloutId","useId","descriptionId","isVisible","setIsVisible","useState","isMounted","setIsMounted","frameRef","useRef","unmountTimerRef","hostRef","handlePanelRef","isTopmost","zIndex","elevated","useOverlayBehaviour","useEffect","shownCallouts","callout","hasCallouts","paddedBody","jsx","subtitleBelow","titleNode","EllipsisText","subtitleNode","titleExtraNode","headerExtraNode","createPortal","ShadowRootWrapper","overlayIdentity","OVERLAY_ELEVATED_ATTR","jsxs","_","index","OVERLAY_ICON_BUTTON_CLASSES","ArrowLeftIcon","DismissIcon","CalloutStrip"],"mappings":"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"}
@@ -192,14 +192,10 @@ I.displayName = "Sidebar.Account";
192
192
  const Z = (e) => {
193
193
  const { collapsed: t } = i();
194
194
  return t ? null : /* @__PURE__ */ r("div", { className: "shrink-0 px-3 pt-3 pb-4", children: /* @__PURE__ */ r(O, { ...e }) });
195
- }, q = ({ children: e }) => /* @__PURE__ */ r(
196
- "div",
197
- {
198
- className: "flex flex-col",
199
- style: { width: A - 2 * D },
200
- children: e
201
- }
202
- ), ce = Object.assign(L, {
195
+ }, q = ({
196
+ children: e,
197
+ width: t = A
198
+ }) => /* @__PURE__ */ r("div", { className: "flex flex-col", style: { width: t - 2 * D }, children: e }), ce = Object.assign(L, {
203
199
  Header: B,
204
200
  Body: G,
205
201
  Section: U,
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.js","sources":["../../src/components/Sidebar.tsx"],"sourcesContent":["import React, { forwardRef, useMemo } from 'react';\nimport CaretLeftIcon from './CustomIcons/CaretLeftIcon';\nimport CaretRightIcon from './CustomIcons/CaretRightIcon';\nimport ChevronsUpDownIcon from './CustomIcons/ChevronsUpDownIcon';\nimport Tooltip from './Tooltip';\nimport TruncatedTooltip from './TruncatedTooltip';\nimport UsageCard, { type UsageCardProps } from './UsageCard';\nimport { isExpanded } from './ariaState';\nimport { BORDER, NO_SCROLLBAR } from './chromeStyles';\nimport { FOCUS_RING } from './focusRing';\nimport {\n SIDEBAR_POPOVER_WIDTH_PX,\n SIDEBAR_TOOLTIP_DELAY_S,\n SIDEBAR_WIDTH_PX,\n SIDEBAR_Z_INDEX,\n SidebarContext,\n useSidebarCollapsed,\n} from './sidebarContext';\n\nconst useSidebar = () => ({ collapsed: useSidebarCollapsed() });\n\nconst POPOVER_BORDER_PX = 1;\nconst TOGGLE_SIZE_PX = 24;\nconst CHEVRONS = { width: 8, height: 14 } as const;\n\nexport interface SidebarProps {\n collapsed?: boolean;\n onToggleCollapse?: () => void;\n expandLabel?: string;\n collapseLabel?: string;\n 'aria-label'?: string;\n children: React.ReactNode;\n}\n\n// Hidden by opacity, not visibility, so the half over the page can be hovered; touch always shows it.\nconst TOGGLE_LAYER =\n 'fixed top-[25px] opacity-0 [will-change:opacity] transition-[left,opacity] duration-200 ease-in-out group-hover/sidebar:opacity-100 group-has-[:focus-visible]/sidebar:opacity-100 [@media(hover:none)]:opacity-100';\n\n// The rows' ground, which a `NavItem` puts under its tag. A context channel, not a theme token.\nconst NAVITEM_GROUND = {\n '--malachite-ctx-navitem-ground': 'var(--malachite-card-sunken-background, rgb(250,250,250))',\n} as React.CSSProperties;\n\nconst SidebarRoot: React.FC<SidebarProps> = ({\n collapsed = false,\n onToggleCollapse,\n expandLabel = 'Expand menu',\n collapseLabel = 'Collapse menu',\n 'aria-label': ariaLabel = 'Main',\n children,\n}) => {\n const toggleLabel = collapsed ? expandLabel : collapseLabel;\n const context = useMemo(() => ({ collapsed }), [collapsed]);\n const width = collapsed ? SIDEBAR_WIDTH_PX.collapsed : SIDEBAR_WIDTH_PX.expanded;\n\n return (\n <SidebarContext.Provider value={context}>\n <aside\n className=\"group/sidebar fixed top-0 bottom-0 left-0 box-border pt-[9px] bg-[var(--malachite-card-sunken-background,rgb(250,250,250))] transition-[width] duration-200 ease-in-out\"\n style={{ width, zIndex: SIDEBAR_Z_INDEX, ...NAVITEM_GROUND }}\n >\n <nav aria-label={ariaLabel} className=\"flex h-full flex-col\">\n {children}\n </nav>\n {onToggleCollapse && (\n <div\n className={TOGGLE_LAYER}\n style={{ left: width - TOGGLE_SIZE_PX / 2, zIndex: SIDEBAR_Z_INDEX + 1 }}\n >\n <Tooltip text={toggleLabel} placement=\"right\" describesTrigger={false}>\n <button\n type=\"button\"\n aria-label={toggleLabel}\n onClick={onToggleCollapse}\n className={`m-0 inline-flex size-6 cursor-pointer items-center justify-center rounded-lg border border-solid p-0 ${BORDER} bg-[var(--malachite-card-background,rgb(255,255,255))] text-[var(--malachite-text-secondary,rgb(123,123,123))] [box-shadow:var(--malachite-shadow-default,0px_1px_0px_0px_rgba(0,0,0,0.15))] transition-colors duration-200 hover:border-[var(--malachite-text-placeholder,rgb(187,187,187))] hover:text-[var(--malachite-text-primary,rgb(10,10,10))] ${FOCUS_RING}`}\n >\n {collapsed ? (\n <CaretRightIcon size={12} />\n ) : (\n <CaretLeftIcon size={12} />\n )}\n </button>\n </Tooltip>\n </div>\n )}\n </aside>\n </SidebarContext.Provider>\n );\n};\n\nconst Header: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div\n className={`box-border flex h-14 shrink-0 items-center border-0 border-b border-solid ${BORDER} py-[6px] ${collapsed ? 'px-1' : 'px-2'}`}\n >\n {children}\n </div>\n );\n};\n\nconst Body: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className={`min-h-0 flex-1 overflow-x-hidden overflow-y-auto ${NO_SCROLLBAR}`}>\n {children}\n </div>\n);\n\nconst Section: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div\n className={`flex flex-col gap-[2px] py-[2px] ${collapsed ? 'items-center px-3' : 'px-4'}`}\n >\n {children}\n </div>\n );\n};\n\nconst Group: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"my-[2px] flex flex-col gap-[6px]\">{children}</div>\n);\n\nconst GroupItems: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"flex flex-col gap-[6px]\">{children}</div>\n);\n\nconst Search: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div className={`flex pt-5 pb-[18px] ${collapsed ? 'justify-center px-3' : 'px-4'}`}>\n {children}\n </div>\n );\n};\n\nconst Notices: React.FC<{ children: React.ReactNode; 'aria-label': string }> = ({\n children,\n 'aria-label': ariaLabel,\n}) => {\n const { collapsed } = useSidebar();\n if (collapsed) {\n return null;\n }\n return (\n <div role=\"status\" aria-label={ariaLabel} className=\"flex flex-col gap-2 px-3 pt-4\">\n {children}\n </div>\n );\n};\n\nconst Divider: React.FC = () => {\n const { collapsed } = useSidebar();\n if (collapsed) {\n return null;\n }\n return <hr className={`m-0 my-2 h-0 shrink-0 border-0 border-t border-solid ${BORDER}`} />;\n};\n\nconst Footer: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div\n className={`mt-1 flex shrink-0 border-0 border-t border-solid ${BORDER} py-3 ${collapsed ? 'justify-center px-2' : 'px-4'}`}\n >\n {children}\n </div>\n );\n};\n\ntype SidebarButtonAttributes = Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'style' | 'color' | 'children' | 'title' | 'name'\n>;\n\nexport interface SidebarSwitcherProps extends SidebarButtonAttributes {\n logo: React.ReactNode;\n title: string;\n subtitle?: string;\n /** Shown when `title` is cut off; a node so it can be wrapped. Defaults to `title`. */\n titleTooltip?: React.ReactNode;\n /** As `titleTooltip`, for `subtitle`. */\n subtitleTooltip?: React.ReactNode;\n}\n\nconst Switcher = forwardRef<HTMLButtonElement, SidebarSwitcherProps>(\n ({ logo, title, subtitle, titleTooltip, subtitleTooltip, className = '', ...rest }, ref) => {\n const { collapsed } = useSidebar();\n const open = isExpanded(rest['aria-expanded']);\n return (\n <button\n ref={ref}\n type=\"button\"\n aria-label={collapsed ? title : undefined}\n {...rest}\n className={`group/switcher m-0 box-border flex h-full w-full min-w-0 cursor-pointer items-center gap-3 rounded-lg border-0 bg-transparent font-sans text-left ${collapsed ? 'justify-center p-1' : 'justify-between px-4 py-[6px]'} ${FOCUS_RING} ${className}`.trim()}\n >\n <span className=\"flex min-w-0 items-center gap-4\">\n <span\n aria-hidden=\"true\"\n className=\"relative top-[-2.5px] flex size-6 shrink-0 items-center justify-center overflow-hidden rounded-md [&_img]:size-6 [&_img]:object-contain\"\n >\n {logo}\n </span>\n {!collapsed && (\n <span className=\"flex min-w-0 flex-col gap-1\">\n <TruncatedTooltip\n text={titleTooltip ?? title}\n placement=\"right\"\n delay={SIDEBAR_TOOLTIP_DELAY_S}\n triggerAs=\"span\"\n describesTrigger={false}\n suppressed={open}\n className=\"text-[length:var(--malachite-font-size-medium,14px)] leading-[14px] font-medium text-[var(--malachite-text-primary,rgb(10,10,10))]\"\n >\n {title}\n </TruncatedTooltip>\n {subtitle && (\n <TruncatedTooltip\n text={subtitleTooltip ?? subtitle}\n placement=\"right\"\n delay={SIDEBAR_TOOLTIP_DELAY_S}\n triggerAs=\"span\"\n describesTrigger={false}\n suppressed={open}\n className=\"text-[12px] leading-[12px] font-normal text-[var(--malachite-text-secondary,rgb(123,123,123))]\"\n >\n {subtitle}\n </TruncatedTooltip>\n )}\n </span>\n )}\n </span>\n {!collapsed && (\n <span className=\"flex shrink-0 text-[var(--malachite-text-secondary,rgb(123,123,123))] transition-colors group-hover/switcher:text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n <ChevronsUpDownIcon style={CHEVRONS} />\n </span>\n )}\n </button>\n );\n },\n);\nSwitcher.displayName = 'Sidebar.Switcher';\n\nexport interface SidebarAccountProps extends SidebarButtonAttributes {\n avatar?: React.ReactNode;\n initials?: string;\n name: string;\n /** Collapsed-rail tooltip, and expanded when `name` is cut off; a node so `name` can be wrapped.\n * Should read as `name`. Defaults to `name`, `false` hides it; none when `name` is empty. */\n tooltip?: React.ReactNode;\n}\n\nconst INITIALS = `inline-flex items-center justify-center rounded-[var(--malachite-radius-md,6px)] border border-solid ${BORDER} bg-[var(--malachite-pillbutton-background,rgb(241,241,241))] supports-[color:color-mix(in_srgb,red,red)]:border-[color-mix(in_srgb,var(--malachite-text-placeholder,rgb(187,187,187))_20%,transparent)] supports-[color:color-mix(in_srgb,red,red)]:bg-[color-mix(in_srgb,var(--malachite-text-placeholder,rgb(187,187,187))_10%,transparent)] px-1 py-[3px] text-[length:var(--malachite-font-size-small,13px)] leading-[12px] font-semibold text-[var(--malachite-text-secondary,rgb(123,123,123))]`;\n\nconst Account = forwardRef<HTMLButtonElement, SidebarAccountProps>(\n ({ avatar, initials, name, tooltip, className = '', ...rest }, ref) => {\n const { collapsed } = useSidebar();\n const button = (\n <button\n ref={ref}\n type=\"button\"\n aria-label={collapsed ? name : undefined}\n {...rest}\n className={`group/account m-0 box-border flex min-h-8 w-full cursor-pointer items-center gap-3 rounded-lg border-0 bg-transparent font-sans ${collapsed ? 'justify-center p-0' : 'justify-between px-2'} ${FOCUS_RING} ${className}`.trim()}\n >\n <span className=\"flex min-w-0 items-center gap-3\">\n <span aria-hidden={collapsed ? undefined : true} className=\"flex shrink-0\">\n {avatar ?? (initials ? <span className={INITIALS}>{initials}</span> : null)}\n </span>\n {!collapsed && (\n <TruncatedTooltip\n text={name ? (tooltip ?? name) : undefined}\n placement=\"right\"\n delay={SIDEBAR_TOOLTIP_DELAY_S}\n triggerAs=\"span\"\n describesTrigger={false}\n suppressed={isExpanded(rest['aria-expanded'])}\n className=\"min-w-0 text-[length:var(--malachite-font-size-medium,14px)] leading-[22px] font-semibold text-[var(--malachite-text-primary,rgb(10,10,10))]\"\n >\n {name}\n </TruncatedTooltip>\n )}\n </span>\n {!collapsed && (\n <span className=\"flex shrink-0 text-[var(--malachite-text-secondary,rgb(123,123,123))] transition-colors group-hover/account:text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n <ChevronsUpDownIcon style={CHEVRONS} />\n </span>\n )}\n </button>\n );\n return collapsed ? (\n <Tooltip\n text={name ? (tooltip ?? name) : undefined}\n placement=\"right\"\n delay={SIDEBAR_TOOLTIP_DELAY_S}\n describesTrigger={false}\n suppressed={isExpanded(rest['aria-expanded'])}\n >\n {button}\n </Tooltip>\n ) : (\n button\n );\n },\n);\nAccount.displayName = 'Sidebar.Account';\n\nconst Usage: React.FC<UsageCardProps> = (props) => {\n const { collapsed } = useSidebar();\n if (collapsed) {\n return null;\n }\n return (\n <div className=\"shrink-0 px-3 pt-3 pb-4\">\n <UsageCard {...props} />\n </div>\n );\n};\n\nconst Panel: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div\n className=\"flex flex-col\"\n style={{ width: SIDEBAR_POPOVER_WIDTH_PX - 2 * POPOVER_BORDER_PX }}\n >\n {children}\n </div>\n);\n\nexport const Sidebar = Object.assign(SidebarRoot, {\n Header,\n Body,\n Section,\n Group,\n GroupItems,\n Search,\n Notices,\n Divider,\n Footer,\n Switcher,\n Account,\n Usage,\n Panel,\n});\n\nexport default Sidebar;\n"],"names":["useSidebar","useSidebarCollapsed","POPOVER_BORDER_PX","TOGGLE_SIZE_PX","CHEVRONS","TOGGLE_LAYER","NAVITEM_GROUND","SidebarRoot","collapsed","onToggleCollapse","expandLabel","collapseLabel","ariaLabel","children","toggleLabel","context","useMemo","width","SIDEBAR_WIDTH_PX","jsx","SidebarContext","jsxs","SIDEBAR_Z_INDEX","Tooltip","BORDER","FOCUS_RING","CaretRightIcon","CaretLeftIcon","Header","Body","NO_SCROLLBAR","Section","Group","GroupItems","Search","Notices","Divider","Footer","Switcher","forwardRef","logo","title","subtitle","titleTooltip","subtitleTooltip","className","rest","ref","open","isExpanded","TruncatedTooltip","SIDEBAR_TOOLTIP_DELAY_S","ChevronsUpDownIcon","INITIALS","Account","avatar","initials","name","tooltip","button","Usage","props","UsageCard","Panel","SIDEBAR_POPOVER_WIDTH_PX","Sidebar"],"mappings":"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"}
1
+ {"version":3,"file":"Sidebar.js","sources":["../../src/components/Sidebar.tsx"],"sourcesContent":["import React, { forwardRef, useMemo } from 'react';\nimport CaretLeftIcon from './CustomIcons/CaretLeftIcon';\nimport CaretRightIcon from './CustomIcons/CaretRightIcon';\nimport ChevronsUpDownIcon from './CustomIcons/ChevronsUpDownIcon';\nimport Tooltip from './Tooltip';\nimport TruncatedTooltip from './TruncatedTooltip';\nimport UsageCard, { type UsageCardProps } from './UsageCard';\nimport { isExpanded } from './ariaState';\nimport { BORDER, NO_SCROLLBAR } from './chromeStyles';\nimport { FOCUS_RING } from './focusRing';\nimport {\n SIDEBAR_POPOVER_WIDTH_PX,\n SIDEBAR_TOOLTIP_DELAY_S,\n SIDEBAR_WIDTH_PX,\n SIDEBAR_Z_INDEX,\n SidebarContext,\n useSidebarCollapsed,\n} from './sidebarContext';\n\nconst useSidebar = () => ({ collapsed: useSidebarCollapsed() });\n\nconst POPOVER_BORDER_PX = 1;\nconst TOGGLE_SIZE_PX = 24;\nconst CHEVRONS = { width: 8, height: 14 } as const;\n\nexport interface SidebarProps {\n collapsed?: boolean;\n onToggleCollapse?: () => void;\n expandLabel?: string;\n collapseLabel?: string;\n 'aria-label'?: string;\n children: React.ReactNode;\n}\n\n// Hidden by opacity, not visibility, so the half over the page can be hovered; touch always shows it.\nconst TOGGLE_LAYER =\n 'fixed top-[25px] opacity-0 [will-change:opacity] transition-[left,opacity] duration-200 ease-in-out group-hover/sidebar:opacity-100 group-has-[:focus-visible]/sidebar:opacity-100 [@media(hover:none)]:opacity-100';\n\n// The rows' ground, which a `NavItem` puts under its tag. A context channel, not a theme token.\nconst NAVITEM_GROUND = {\n '--malachite-ctx-navitem-ground': 'var(--malachite-card-sunken-background, rgb(250,250,250))',\n} as React.CSSProperties;\n\nconst SidebarRoot: React.FC<SidebarProps> = ({\n collapsed = false,\n onToggleCollapse,\n expandLabel = 'Expand menu',\n collapseLabel = 'Collapse menu',\n 'aria-label': ariaLabel = 'Main',\n children,\n}) => {\n const toggleLabel = collapsed ? expandLabel : collapseLabel;\n const context = useMemo(() => ({ collapsed }), [collapsed]);\n const width = collapsed ? SIDEBAR_WIDTH_PX.collapsed : SIDEBAR_WIDTH_PX.expanded;\n\n return (\n <SidebarContext.Provider value={context}>\n <aside\n className=\"group/sidebar fixed top-0 bottom-0 left-0 box-border pt-[9px] bg-[var(--malachite-card-sunken-background,rgb(250,250,250))] transition-[width] duration-200 ease-in-out\"\n style={{ width, zIndex: SIDEBAR_Z_INDEX, ...NAVITEM_GROUND }}\n >\n <nav aria-label={ariaLabel} className=\"flex h-full flex-col\">\n {children}\n </nav>\n {onToggleCollapse && (\n <div\n className={TOGGLE_LAYER}\n style={{ left: width - TOGGLE_SIZE_PX / 2, zIndex: SIDEBAR_Z_INDEX + 1 }}\n >\n <Tooltip text={toggleLabel} placement=\"right\" describesTrigger={false}>\n <button\n type=\"button\"\n aria-label={toggleLabel}\n onClick={onToggleCollapse}\n className={`m-0 inline-flex size-6 cursor-pointer items-center justify-center rounded-lg border border-solid p-0 ${BORDER} bg-[var(--malachite-card-background,rgb(255,255,255))] text-[var(--malachite-text-secondary,rgb(123,123,123))] [box-shadow:var(--malachite-shadow-default,0px_1px_0px_0px_rgba(0,0,0,0.15))] transition-colors duration-200 hover:border-[var(--malachite-text-placeholder,rgb(187,187,187))] hover:text-[var(--malachite-text-primary,rgb(10,10,10))] ${FOCUS_RING}`}\n >\n {collapsed ? (\n <CaretRightIcon size={12} />\n ) : (\n <CaretLeftIcon size={12} />\n )}\n </button>\n </Tooltip>\n </div>\n )}\n </aside>\n </SidebarContext.Provider>\n );\n};\n\nconst Header: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div\n className={`box-border flex h-14 shrink-0 items-center border-0 border-b border-solid ${BORDER} py-[6px] ${collapsed ? 'px-1' : 'px-2'}`}\n >\n {children}\n </div>\n );\n};\n\nconst Body: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className={`min-h-0 flex-1 overflow-x-hidden overflow-y-auto ${NO_SCROLLBAR}`}>\n {children}\n </div>\n);\n\nconst Section: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div\n className={`flex flex-col gap-[2px] py-[2px] ${collapsed ? 'items-center px-3' : 'px-4'}`}\n >\n {children}\n </div>\n );\n};\n\nconst Group: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"my-[2px] flex flex-col gap-[6px]\">{children}</div>\n);\n\nconst GroupItems: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"flex flex-col gap-[6px]\">{children}</div>\n);\n\nconst Search: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div className={`flex pt-5 pb-[18px] ${collapsed ? 'justify-center px-3' : 'px-4'}`}>\n {children}\n </div>\n );\n};\n\nconst Notices: React.FC<{ children: React.ReactNode; 'aria-label': string }> = ({\n children,\n 'aria-label': ariaLabel,\n}) => {\n const { collapsed } = useSidebar();\n if (collapsed) {\n return null;\n }\n return (\n <div role=\"status\" aria-label={ariaLabel} className=\"flex flex-col gap-2 px-3 pt-4\">\n {children}\n </div>\n );\n};\n\nconst Divider: React.FC = () => {\n const { collapsed } = useSidebar();\n if (collapsed) {\n return null;\n }\n return <hr className={`m-0 my-2 h-0 shrink-0 border-0 border-t border-solid ${BORDER}`} />;\n};\n\nconst Footer: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div\n className={`mt-1 flex shrink-0 border-0 border-t border-solid ${BORDER} py-3 ${collapsed ? 'justify-center px-2' : 'px-4'}`}\n >\n {children}\n </div>\n );\n};\n\ntype SidebarButtonAttributes = Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'style' | 'color' | 'children' | 'title' | 'name'\n>;\n\nexport interface SidebarSwitcherProps extends SidebarButtonAttributes {\n logo: React.ReactNode;\n title: string;\n subtitle?: string;\n /** Shown when `title` is cut off; a node so it can be wrapped. Defaults to `title`. */\n titleTooltip?: React.ReactNode;\n /** As `titleTooltip`, for `subtitle`. */\n subtitleTooltip?: React.ReactNode;\n}\n\nconst Switcher = forwardRef<HTMLButtonElement, SidebarSwitcherProps>(\n ({ logo, title, subtitle, titleTooltip, subtitleTooltip, className = '', ...rest }, ref) => {\n const { collapsed } = useSidebar();\n const open = isExpanded(rest['aria-expanded']);\n return (\n <button\n ref={ref}\n type=\"button\"\n aria-label={collapsed ? title : undefined}\n {...rest}\n className={`group/switcher m-0 box-border flex h-full w-full min-w-0 cursor-pointer items-center gap-3 rounded-lg border-0 bg-transparent font-sans text-left ${collapsed ? 'justify-center p-1' : 'justify-between px-4 py-[6px]'} ${FOCUS_RING} ${className}`.trim()}\n >\n <span className=\"flex min-w-0 items-center gap-4\">\n <span\n aria-hidden=\"true\"\n className=\"relative top-[-2.5px] flex size-6 shrink-0 items-center justify-center overflow-hidden rounded-md [&_img]:size-6 [&_img]:object-contain\"\n >\n {logo}\n </span>\n {!collapsed && (\n <span className=\"flex min-w-0 flex-col gap-1\">\n <TruncatedTooltip\n text={titleTooltip ?? title}\n placement=\"right\"\n delay={SIDEBAR_TOOLTIP_DELAY_S}\n triggerAs=\"span\"\n describesTrigger={false}\n suppressed={open}\n className=\"text-[length:var(--malachite-font-size-medium,14px)] leading-[14px] font-medium text-[var(--malachite-text-primary,rgb(10,10,10))]\"\n >\n {title}\n </TruncatedTooltip>\n {subtitle && (\n <TruncatedTooltip\n text={subtitleTooltip ?? subtitle}\n placement=\"right\"\n delay={SIDEBAR_TOOLTIP_DELAY_S}\n triggerAs=\"span\"\n describesTrigger={false}\n suppressed={open}\n className=\"text-[12px] leading-[12px] font-normal text-[var(--malachite-text-secondary,rgb(123,123,123))]\"\n >\n {subtitle}\n </TruncatedTooltip>\n )}\n </span>\n )}\n </span>\n {!collapsed && (\n <span className=\"flex shrink-0 text-[var(--malachite-text-secondary,rgb(123,123,123))] transition-colors group-hover/switcher:text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n <ChevronsUpDownIcon style={CHEVRONS} />\n </span>\n )}\n </button>\n );\n },\n);\nSwitcher.displayName = 'Sidebar.Switcher';\n\nexport interface SidebarAccountProps extends SidebarButtonAttributes {\n avatar?: React.ReactNode;\n initials?: string;\n name: string;\n /** Collapsed-rail tooltip, and expanded when `name` is cut off; a node so `name` can be wrapped.\n * Should read as `name`. Defaults to `name`, `false` hides it; none when `name` is empty. */\n tooltip?: React.ReactNode;\n}\n\nconst INITIALS = `inline-flex items-center justify-center rounded-[var(--malachite-radius-md,6px)] border border-solid ${BORDER} bg-[var(--malachite-pillbutton-background,rgb(241,241,241))] supports-[color:color-mix(in_srgb,red,red)]:border-[color-mix(in_srgb,var(--malachite-text-placeholder,rgb(187,187,187))_20%,transparent)] supports-[color:color-mix(in_srgb,red,red)]:bg-[color-mix(in_srgb,var(--malachite-text-placeholder,rgb(187,187,187))_10%,transparent)] px-1 py-[3px] text-[length:var(--malachite-font-size-small,13px)] leading-[12px] font-semibold text-[var(--malachite-text-secondary,rgb(123,123,123))]`;\n\nconst Account = forwardRef<HTMLButtonElement, SidebarAccountProps>(\n ({ avatar, initials, name, tooltip, className = '', ...rest }, ref) => {\n const { collapsed } = useSidebar();\n const button = (\n <button\n ref={ref}\n type=\"button\"\n aria-label={collapsed ? name : undefined}\n {...rest}\n className={`group/account m-0 box-border flex min-h-8 w-full cursor-pointer items-center gap-3 rounded-lg border-0 bg-transparent font-sans ${collapsed ? 'justify-center p-0' : 'justify-between px-2'} ${FOCUS_RING} ${className}`.trim()}\n >\n <span className=\"flex min-w-0 items-center gap-3\">\n <span aria-hidden={collapsed ? undefined : true} className=\"flex shrink-0\">\n {avatar ?? (initials ? <span className={INITIALS}>{initials}</span> : null)}\n </span>\n {!collapsed && (\n <TruncatedTooltip\n text={name ? (tooltip ?? name) : undefined}\n placement=\"right\"\n delay={SIDEBAR_TOOLTIP_DELAY_S}\n triggerAs=\"span\"\n describesTrigger={false}\n suppressed={isExpanded(rest['aria-expanded'])}\n className=\"min-w-0 text-[length:var(--malachite-font-size-medium,14px)] leading-[22px] font-semibold text-[var(--malachite-text-primary,rgb(10,10,10))]\"\n >\n {name}\n </TruncatedTooltip>\n )}\n </span>\n {!collapsed && (\n <span className=\"flex shrink-0 text-[var(--malachite-text-secondary,rgb(123,123,123))] transition-colors group-hover/account:text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n <ChevronsUpDownIcon style={CHEVRONS} />\n </span>\n )}\n </button>\n );\n return collapsed ? (\n <Tooltip\n text={name ? (tooltip ?? name) : undefined}\n placement=\"right\"\n delay={SIDEBAR_TOOLTIP_DELAY_S}\n describesTrigger={false}\n suppressed={isExpanded(rest['aria-expanded'])}\n >\n {button}\n </Tooltip>\n ) : (\n button\n );\n },\n);\nAccount.displayName = 'Sidebar.Account';\n\nconst Usage: React.FC<UsageCardProps> = (props) => {\n const { collapsed } = useSidebar();\n if (collapsed) {\n return null;\n }\n return (\n <div className=\"shrink-0 px-3 pt-3 pb-4\">\n <UsageCard {...props} />\n </div>\n );\n};\n\n/** `width` widens a popover past the sidebar's, for a menu wider than the control it opens from. */\nconst Panel: React.FC<{ children: React.ReactNode; width?: number }> = ({\n children,\n width = SIDEBAR_POPOVER_WIDTH_PX,\n}) => (\n <div className=\"flex flex-col\" style={{ width: width - 2 * POPOVER_BORDER_PX }}>\n {children}\n </div>\n);\n\nexport const Sidebar = Object.assign(SidebarRoot, {\n Header,\n Body,\n Section,\n Group,\n GroupItems,\n Search,\n Notices,\n Divider,\n Footer,\n Switcher,\n Account,\n Usage,\n Panel,\n});\n\nexport default Sidebar;\n"],"names":["useSidebar","useSidebarCollapsed","POPOVER_BORDER_PX","TOGGLE_SIZE_PX","CHEVRONS","TOGGLE_LAYER","NAVITEM_GROUND","SidebarRoot","collapsed","onToggleCollapse","expandLabel","collapseLabel","ariaLabel","children","toggleLabel","context","useMemo","width","SIDEBAR_WIDTH_PX","jsx","SidebarContext","jsxs","SIDEBAR_Z_INDEX","Tooltip","BORDER","FOCUS_RING","CaretRightIcon","CaretLeftIcon","Header","Body","NO_SCROLLBAR","Section","Group","GroupItems","Search","Notices","Divider","Footer","Switcher","forwardRef","logo","title","subtitle","titleTooltip","subtitleTooltip","className","rest","ref","open","isExpanded","TruncatedTooltip","SIDEBAR_TOOLTIP_DELAY_S","ChevronsUpDownIcon","INITIALS","Account","avatar","initials","name","tooltip","button","Usage","props","UsageCard","Panel","SIDEBAR_POPOVER_WIDTH_PX","Sidebar"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -51,6 +51,11 @@ declare interface AccordionBaseProps {
51
51
  * be interactive (e.g. a Checkbox) without nesting a button inside a button.
52
52
  */
53
53
  trailing?: default_2.ReactNode;
54
+ /** Before the title, outside the toggle button. */
55
+ leading?: default_2.ReactNode;
56
+ arrowPosition?: 'start' | 'end';
57
+ /** `false` keeps an open row on the card ground. */
58
+ highlightExpanded?: boolean;
54
59
  defaultExpanded?: boolean;
55
60
  isExpanded?: boolean;
56
61
  onToggle?: (expanded: boolean) => void;
@@ -203,6 +208,8 @@ declare interface AlertProps {
203
208
  renderLink?: RenderLink;
204
209
  /** `banner`: a 48px page-wide band. Applies only without `children`. */
205
210
  layout?: AlertLayout;
211
+ /** `center` gathers a banner's icon and text in the middle of the band, for a wide page. */
212
+ align?: 'start' | 'center';
206
213
  /** A bold sentence the message runs on from. Plain text, not markdown. */
207
214
  lead?: string;
208
215
  }
@@ -408,6 +415,8 @@ declare interface ButtonProps extends default_2.ButtonHTMLAttributes<HTMLButtonE
408
415
  contentAlign?: 'center' | 'start';
409
416
  /** Fills the container's width. */
410
417
  flexGrow?: boolean;
418
+ /** `wide` holds a 120px floor for a primary action. */
419
+ width?: 'auto' | 'wide';
411
420
  fill?: boolean;
412
421
  tooltip?: string;
413
422
  tooltipPlacement?: 'top' | 'bottom' | 'left' | 'right';
@@ -438,7 +447,9 @@ export declare type ButtonVariant = 'filled' | 'outline'
438
447
  * acts on what it produced. Provenance, not a severity: it says who is being asked, not
439
448
  * that anything is wrong.
440
449
  */
441
- | 'assistant' | 'destructive' | 'success' | 'warning' | 'error' | 'ghost' | 'no-style';
450
+ | 'assistant' | 'destructive' | 'success' | 'warning' | 'error' | 'ghost'
451
+ /** Text only, in the accent colour, for a secondary action beside a primary one. */
452
+ | 'quiet' | 'no-style';
442
453
 
443
454
  export declare const Card: default_2.FC<CardProps>;
444
455
 
@@ -4613,6 +4624,7 @@ export declare const Sidebar: default_2.FC<SidebarProps> & {
4613
4624
  Usage: default_2.FC<UsageCardProps>;
4614
4625
  Panel: default_2.FC<{
4615
4626
  children: default_2.ReactNode;
4627
+ width?: number;
4616
4628
  }>;
4617
4629
  };
4618
4630
 
@@ -4680,12 +4692,15 @@ export declare interface SidePanelProps {
4680
4692
  /** Dismiss handler — close button, ESC, or overlay click. */
4681
4693
  onClose: () => void;
4682
4694
  title: default_2.ReactNode;
4683
- /** Secondary text, inline after the title. */
4684
4695
  subtitle?: default_2.ReactNode;
4696
+ /** `below` stacks the subtitle under the title, so neither truncates the other. */
4697
+ subtitlePlacement?: 'inline' | 'below';
4685
4698
  /** Content at the end of the title row, after the subtitle (e.g. a status tag). */
4686
4699
  titleExtra?: default_2.ReactNode;
4687
4700
  /** Block paragraph below the title row, spanning the header width. Announced as the panel's description. */
4688
4701
  description?: default_2.ReactNode;
4702
+ /** Pinned between the header and the scrolling body. */
4703
+ toolbar?: default_2.ReactNode;
4689
4704
  /** Divider under the header. Default: false. */
4690
4705
  headerDivider?: boolean;
4691
4706
  /** Leading header slot, typically a logo or icon. */