@stackone/malachite 2.39.0 → 2.40.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.
- package/COMPONENTS.md +1 -1
- package/dist/components/Sidebar.js +44 -44
- package/dist/components/Sidebar.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/package.json +1 -1
package/COMPONENTS.md
CHANGED
|
@@ -60,7 +60,7 @@ The catalog of components exported from `@stackone/malachite`. **Reach for one o
|
|
|
60
60
|
- **`Breadcrumbs`** — Breadcrumb trail with caret separators, an optional back button (shown only when there is more than one crumb AND the parent — the second-to-last — carries a `url` to target) and a right-aligned `actions` row. A lone crumb marked `isRoot` switches to title mode: plain emphasised text, no trail chrome, but the `actions` row still renders. Renders as a `nav`/`ol` with `aria-current="page"` on the last crumb. Pass `renderLink` to route crumbs through the app's own router instead of a plain `<a>`. Used by `PageLayout`, but standalone too. _Key props:_ `links[]` (`name`, `url`, `isRoot`), `actions[]`, `renderLink`, `className`, `style`.
|
|
61
61
|
- **`ActionMenu`** — Dropdown menu of actions (kebab/overflow style). The trigger is an icon-only `Button` by default, so `size` draws exactly the square a `Button` of that size draws beside it: `xsmall` is Figma's 20px "Button Element - Square (X-Small)", `small` the 28px rung above it. Both squares are fixed rather than read off the `controlHeights` tokens, so re-theming those does not resize the trigger. A supplied `triggerIcon` is held to the tier's glyph size — 11px at `xsmall`, 16px at `small`. At 20px the `xsmall` trigger meets WCAG 2.5.8 through the *Spacing* exception rather than the 24px minimum, so keep at least 4px between adjacent triggers. `showLabel` draws `label` beside the icon instead of leaving it to the accessible name — for a menu that is the point of its corner rather than an overflow for a row that already says what it acts on — and `variant` puts the trigger on any `Button` variant, so a menu handing work to the assistant can wear the assistant ground rather than the overflow-kebab outline. An item's `icon` leads its label: every caller's names the action itself — copy, open, delete — and an icon that is part of an item's identity belongs where the eye starts rather than right-aligned, where it reads as a status column. The menu is Figma's `Dropdown Component - Options List`: a fixed sized to its widest item between a 180px floor and the 280px Figma draws, by default under the trigger's right edge, 14px below it, flipping above or clamping sideways when the viewport has no room, rounding at the library's 12px and padding wider (8px) than the menu a `Dropdown` opens. Items read in the primary text colour, or the secondary one with `tone="muted"` (e.g. a sidebar's menus); destructive ones in red. A ceiling rather than a flat width: taken literally it gave a menu of four short verbs 130px of air and made every kebab in an app the same width whatever it held. `minWidth` only raises it above that ceiling, so it is the one way to go past 280px, and a label too long for the box truncates rather than wrapping. _Key props:_ `ActionMenuItem[]`, `size`, `label`, `triggerIcon`, `minWidth`, `showLabel`, `variant`, `tone` (`default` | `muted`), `trigger` (your own control in place of the kebab, cloned with the menu's ref and aria state), `placement` (`bottom-end` default | `bottom-start` | `right-start` | `top-start` | `top-center`), `offset` (`small` 8px | `medium` 12px | `large` 14px; applies to every placement; without it the default `bottom-end` keeps the options menu's 14px and the others use 8px). An item's `tag` (e.g. an "Early access" `Tag`) follows its label in a lazily loaded shadow host of its own, since the menu renders into `document.body`, and joins its accessible name; `current: true` marks the item for the page the user is on (`aria-current="page"` and the selected row paint; a `danger` item keeps its red text). An item with `type: 'text'` is context rather than an action (an account's email above its actions): secondary text the arrow keys skip. Opened from the keyboard, focus lands on the first item; Up/Down/Home/End move through enabled items, Tab closes the menu and moves on as usual; Escape or a picked item returns focus to the trigger.
|
|
62
62
|
- **`NavItem`** — A row in an app's side navigation. Idle rows read secondary and take the list hover; the `active` row wears the accent tint and sets `aria-current="page"` on a link. `collapsed` shrinks it to a 36px icon tile whose label becomes the accessible name and a right-hand tooltip, with any `badge` pinned to the tile's corner. `variant="subitem"` indents a child row behind a dot instead of an icon; `disclosure` makes a group header button with `aria-expanded` and a rotating chevron, and `hasActiveChild` colours its text while a child is current. Renders an `<a>` with `href`, the element passed with `asChild` (a router `Link`), or a `<button>`, and forwards its ref and extra attributes so it can be a `Popover` or `ActionMenu` trigger. _Key props:_ `label`, `icon`, `active`, `hasActiveChild`, `collapsed`, `variant` (`item` | `subitem`), `danger`, `trailing`, `badge`, `disclosure` (`expanded` | `collapsed`), `tooltip`, `accessibleLabel` (overrides the accessible name; collapsed it defaults to the tooltip text plus `badgeLabel`), `href`, `target`, `rel`, `onClick`, `asChild` + `children`, `className`, `size` (`medium` | `small`, the tighter row for lists inside a popover), `tag` (beside the label, e.g. early access), `badgeLabel` (read in place of the badge and added to the collapsed name). A passed `aria-expanded` (e.g. from a `Popover`) wins over `disclosure`, and a button row forwards a passed `aria-current`.
|
|
63
|
-
- **`Sidebar`** — An app's left navigation shell, pinned to the viewport's left edge: 260px wide, 60px `collapsed`, on the sunken page background. Composed from `Sidebar.Header` (a 56px band for `Sidebar.Switcher`, the logo + workspace + parent trigger), `Sidebar.Body` (the part that scrolls), `Sidebar.Notices`, `Sidebar.Search`, `Sidebar.Section` (rows of `NavItem`s at the gutter), `Sidebar.Group` + `Sidebar.GroupItems` (a disclosure header and its sub-items), `Sidebar.Divider`, `Sidebar.Usage` (a `UsageCard` placed at the sidebar's gutter) and `Sidebar.Footer` holding `Sidebar.Account`. Popovers opened from it (with `padding="none"`) wrap their body in `Sidebar.Panel`, sized so the popover comes to `SIDEBAR_POPOVER_WIDTH_PX`, and build it from the `Popover` parts. `onToggleCollapse` adds the edge toggle, shown in CSS while the pointer is over the sidebar or a keyboard focus is inside it. Notices, the divider and the usage card hide while collapsed. _Key props:_ `collapsed`, `onToggleCollapse`, `expandLabel`, `collapseLabel`, `aria-label`; `Sidebar.Switcher`: `logo`, `title`, `subtitle` + button attributes; `Sidebar.Account`: `avatar` or `initials` (a small chip when there is no photo), `name` + button attributes; `Sidebar.Usage`: the `UsageCard` props; `Sidebar.Notices`: `aria-label` (required). `useSidebarCollapsed()` reads the state from inside; `SIDEBAR_WIDTH_PX` gives the page its offset beside the sidebar.
|
|
63
|
+
- **`Sidebar`** — An app's left navigation shell, pinned to the viewport's left edge: 260px wide, 60px `collapsed`, on the sunken page background. Composed from `Sidebar.Header` (a 56px band for `Sidebar.Switcher`, the logo + workspace + parent trigger), `Sidebar.Body` (the part that scrolls), `Sidebar.Notices`, `Sidebar.Search`, `Sidebar.Section` (rows of `NavItem`s at the gutter), `Sidebar.Group` + `Sidebar.GroupItems` (a disclosure header and its sub-items), `Sidebar.Divider`, `Sidebar.Usage` (a `UsageCard` placed at the sidebar's gutter) and `Sidebar.Footer` holding `Sidebar.Account`. Popovers opened from it (with `padding="none"`) wrap their body in `Sidebar.Panel`, sized so the popover comes to `SIDEBAR_POPOVER_WIDTH_PX`, and build it from the `Popover` parts. `onToggleCollapse` adds the edge toggle, shown in CSS while the pointer is over the sidebar or a keyboard focus is inside it. Notices, the divider and the usage card hide while collapsed. _Key props:_ `collapsed`, `onToggleCollapse`, `expandLabel`, `collapseLabel`, `aria-label`; `Sidebar.Switcher`: `logo`, `title`, `subtitle` + button attributes; `Sidebar.Account`: `avatar` or `initials` (a small chip when there is no photo), `name`, `tooltip` (the tooltip on the collapsed rail, `name` by default; pass a node to wrap it, e.g. to keep it out of session recordings) + button attributes; `Sidebar.Usage`: the `UsageCard` props; `Sidebar.Notices`: `aria-label` (required). `useSidebarCollapsed()` reads the state from inside; `SIDEBAR_WIDTH_PX` gives the page its offset beside the sidebar.
|
|
64
64
|
- **`SearchTrigger`** — A button drawn as a filled search field, for opening a command palette or search dialog from app chrome such as a sidebar. It is not an input — typing happens in what it opens. `shortcut` draws flat `<kbd>` chips at the end (not `Keycap`, whose raised shadow reads as a second button inside a filled field), kept out of the accessible name; `iconOnly` makes a 36px icon tile matching a collapsed `NavItem`, named by `label`. _Key props:_ `label` (default `Search`), `shortcut` (`ReactNode[]`), `iconOnly`, `aria-label`, `className`, plus native button attributes (`onClick`, `aria-haspopup`, `aria-expanded`, `aria-keyshortcuts`).
|
|
65
65
|
- **`FooterNav`** — Footer navigation bar of links. _Key props:_ `FooterNavLink[]`.
|
|
66
66
|
- **`FooterLinks`** — Inline list of footer links (e.g. terms, privacy, support).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as r, jsxs as
|
|
1
|
+
import { jsx as r, jsxs as n } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo as N, forwardRef as u } from "react";
|
|
3
3
|
import w from "./CustomIcons/CaretLeftIcon.js";
|
|
4
4
|
import _ from "./CustomIcons/CaretRightIcon.js";
|
|
@@ -6,32 +6,32 @@ import h from "./CustomIcons/ChevronsUpDownIcon.js";
|
|
|
6
6
|
import f from "./Tooltip.js";
|
|
7
7
|
import { UsageCard as S } from "./UsageCard.js";
|
|
8
8
|
import { isExpanded as $ } from "./ariaState.js";
|
|
9
|
-
import { BORDER as
|
|
10
|
-
import { FOCUS_RING as
|
|
9
|
+
import { BORDER as m, NO_SCROLLBAR as R } from "./chromeStyles.js";
|
|
10
|
+
import { FOCUS_RING as x } from "./focusRing.js";
|
|
11
11
|
import { SIDEBAR_WIDTH_PX as b, SidebarContext as k, SIDEBAR_POPOVER_WIDTH_PX as j, useSidebarCollapsed as E } from "./sidebarContext.js";
|
|
12
12
|
const i = () => ({ collapsed: E() }), I = 1, O = 24, g = { width: 8, height: 14 }, z = "fixed top-[25px] z-[101] invisible opacity-0 [will-change:opacity] transition-[left,opacity,visibility] duration-200 ease-in-out group-hover/sidebar:visible group-hover/sidebar:opacity-100 group-has-[:focus-visible]/sidebar:visible group-has-[:focus-visible]/sidebar:opacity-100", C = ({
|
|
13
13
|
collapsed: e = !1,
|
|
14
14
|
onToggleCollapse: t,
|
|
15
|
-
expandLabel:
|
|
16
|
-
collapseLabel:
|
|
17
|
-
"aria-label":
|
|
18
|
-
children:
|
|
15
|
+
expandLabel: a = "Expand menu",
|
|
16
|
+
collapseLabel: c = "Collapse menu",
|
|
17
|
+
"aria-label": d = "Main",
|
|
18
|
+
children: l
|
|
19
19
|
}) => {
|
|
20
|
-
const
|
|
21
|
-
return /* @__PURE__ */ r(k.Provider, { value:
|
|
20
|
+
const o = e ? a : c, s = N(() => ({ collapsed: e }), [e]), p = e ? b.collapsed : b.expanded;
|
|
21
|
+
return /* @__PURE__ */ r(k.Provider, { value: s, children: /* @__PURE__ */ n(
|
|
22
22
|
"aside",
|
|
23
23
|
{
|
|
24
24
|
className: "group/sidebar fixed top-0 bottom-0 left-0 z-[100] box-border pt-[9px] bg-[var(--malachite-card-sunken-background,rgb(250,250,250))] transition-[width] duration-200 ease-in-out",
|
|
25
|
-
style: { width:
|
|
25
|
+
style: { width: p },
|
|
26
26
|
children: [
|
|
27
|
-
/* @__PURE__ */ r("nav", { "aria-label":
|
|
28
|
-
t && /* @__PURE__ */ r("div", { className: z, style: { left:
|
|
27
|
+
/* @__PURE__ */ r("nav", { "aria-label": d, className: "flex h-full flex-col", children: l }),
|
|
28
|
+
t && /* @__PURE__ */ r("div", { className: z, style: { left: p - O / 2 }, children: /* @__PURE__ */ r(f, { text: o, placement: "right", describesTrigger: !1, children: /* @__PURE__ */ r(
|
|
29
29
|
"button",
|
|
30
30
|
{
|
|
31
31
|
type: "button",
|
|
32
|
-
"aria-label":
|
|
32
|
+
"aria-label": o,
|
|
33
33
|
onClick: t,
|
|
34
|
-
className: `m-0 inline-flex size-6 cursor-pointer items-center justify-center rounded-lg border border-solid p-0 ${
|
|
34
|
+
className: `m-0 inline-flex size-6 cursor-pointer items-center justify-center rounded-lg border border-solid p-0 ${m} 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))] ${x}`,
|
|
35
35
|
children: e ? /* @__PURE__ */ r(_, { size: 12 }) : /* @__PURE__ */ r(w, { size: 12 })
|
|
36
36
|
}
|
|
37
37
|
) }) })
|
|
@@ -43,7 +43,7 @@ const i = () => ({ collapsed: E() }), I = 1, O = 24, g = { width: 8, height: 14
|
|
|
43
43
|
return /* @__PURE__ */ r(
|
|
44
44
|
"div",
|
|
45
45
|
{
|
|
46
|
-
className: `box-border flex h-14 shrink-0 items-center border-0 border-b border-solid ${
|
|
46
|
+
className: `box-border flex h-14 shrink-0 items-center border-0 border-b border-solid ${m} py-[6px] ${t ? "px-1" : "px-2"}`,
|
|
47
47
|
children: e
|
|
48
48
|
}
|
|
49
49
|
);
|
|
@@ -63,33 +63,33 @@ const i = () => ({ collapsed: E() }), I = 1, O = 24, g = { width: 8, height: 14
|
|
|
63
63
|
children: e,
|
|
64
64
|
"aria-label": t
|
|
65
65
|
}) => {
|
|
66
|
-
const { collapsed:
|
|
67
|
-
return
|
|
66
|
+
const { collapsed: a } = i();
|
|
67
|
+
return a ? null : /* @__PURE__ */ r("div", { role: "status", "aria-label": t, className: "flex flex-col gap-2 px-3 pt-4", children: e });
|
|
68
68
|
}, H = () => {
|
|
69
69
|
const { collapsed: e } = i();
|
|
70
|
-
return e ? null : /* @__PURE__ */ r("hr", { className: `m-0 my-2 h-0 shrink-0 border-0 border-t border-solid ${
|
|
70
|
+
return e ? null : /* @__PURE__ */ r("hr", { className: `m-0 my-2 h-0 shrink-0 border-0 border-t border-solid ${m}` });
|
|
71
71
|
}, U = ({ children: e }) => {
|
|
72
72
|
const { collapsed: t } = i();
|
|
73
73
|
return /* @__PURE__ */ r(
|
|
74
74
|
"div",
|
|
75
75
|
{
|
|
76
|
-
className: `mt-1 flex shrink-0 border-0 border-t border-solid ${
|
|
76
|
+
className: `mt-1 flex shrink-0 border-0 border-t border-solid ${m} py-3 ${t ? "justify-center px-2" : "px-4"}`,
|
|
77
77
|
children: e
|
|
78
78
|
}
|
|
79
79
|
);
|
|
80
80
|
}, v = u(
|
|
81
|
-
({ logo: e, title: t, subtitle:
|
|
82
|
-
const { collapsed:
|
|
83
|
-
return /* @__PURE__ */
|
|
81
|
+
({ logo: e, title: t, subtitle: a, className: c = "", ...d }, l) => {
|
|
82
|
+
const { collapsed: o } = i();
|
|
83
|
+
return /* @__PURE__ */ n(
|
|
84
84
|
"button",
|
|
85
85
|
{
|
|
86
|
-
ref:
|
|
86
|
+
ref: l,
|
|
87
87
|
type: "button",
|
|
88
|
-
"aria-label":
|
|
89
|
-
...
|
|
90
|
-
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 ${
|
|
88
|
+
"aria-label": o ? t : void 0,
|
|
89
|
+
...d,
|
|
90
|
+
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 ${o ? "justify-center p-1" : "justify-between px-4 py-[6px]"} ${x} ${c}`.trim(),
|
|
91
91
|
children: [
|
|
92
|
-
/* @__PURE__ */
|
|
92
|
+
/* @__PURE__ */ n("span", { className: "flex min-w-0 items-center gap-4", children: [
|
|
93
93
|
/* @__PURE__ */ r(
|
|
94
94
|
"span",
|
|
95
95
|
{
|
|
@@ -98,44 +98,44 @@ const i = () => ({ collapsed: E() }), I = 1, O = 24, g = { width: 8, height: 14
|
|
|
98
98
|
children: e
|
|
99
99
|
}
|
|
100
100
|
),
|
|
101
|
-
!
|
|
101
|
+
!o && /* @__PURE__ */ n("span", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
102
102
|
/* @__PURE__ */ r("span", { className: "block truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[14px] font-medium text-[var(--malachite-text-primary,rgb(10,10,10))]", children: t }),
|
|
103
|
-
|
|
103
|
+
a && /* @__PURE__ */ r("span", { className: "block truncate text-[12px] leading-[12px] font-normal text-[var(--malachite-text-secondary,rgb(123,123,123))]", children: a })
|
|
104
104
|
] })
|
|
105
105
|
] }),
|
|
106
|
-
!
|
|
106
|
+
!o && /* @__PURE__ */ r("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))]", children: /* @__PURE__ */ r(h, { style: g }) })
|
|
107
107
|
]
|
|
108
108
|
}
|
|
109
109
|
);
|
|
110
110
|
}
|
|
111
111
|
);
|
|
112
112
|
v.displayName = "Sidebar.Switcher";
|
|
113
|
-
const X = `inline-flex items-center justify-center rounded-[var(--malachite-radius-md,6px)] border border-solid ${
|
|
114
|
-
({ avatar: e, initials: t, name:
|
|
115
|
-
const { collapsed:
|
|
113
|
+
const X = `inline-flex items-center justify-center rounded-[var(--malachite-radius-md,6px)] border border-solid ${m} 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))]`, y = u(
|
|
114
|
+
({ avatar: e, initials: t, name: a, tooltip: c, className: d = "", ...l }, o) => {
|
|
115
|
+
const { collapsed: s } = i(), p = /* @__PURE__ */ n(
|
|
116
116
|
"button",
|
|
117
117
|
{
|
|
118
|
-
ref:
|
|
118
|
+
ref: o,
|
|
119
119
|
type: "button",
|
|
120
|
-
"aria-label":
|
|
121
|
-
...
|
|
122
|
-
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 ${
|
|
120
|
+
"aria-label": s ? a : void 0,
|
|
121
|
+
...l,
|
|
122
|
+
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 ${s ? "justify-center p-0" : "justify-between px-2"} ${x} ${d}`.trim(),
|
|
123
123
|
children: [
|
|
124
|
-
/* @__PURE__ */
|
|
125
|
-
/* @__PURE__ */ r("span", { "aria-hidden":
|
|
126
|
-
!
|
|
124
|
+
/* @__PURE__ */ n("span", { className: "flex min-w-0 items-center gap-3", children: [
|
|
125
|
+
/* @__PURE__ */ r("span", { "aria-hidden": s ? void 0 : !0, className: "flex shrink-0", children: e ?? (t ? /* @__PURE__ */ r("span", { className: X, children: t }) : null) }),
|
|
126
|
+
!s && /* @__PURE__ */ r("span", { className: "truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[22px] font-semibold text-[var(--malachite-text-primary,rgb(10,10,10))]", children: a })
|
|
127
127
|
] }),
|
|
128
|
-
!
|
|
128
|
+
!s && /* @__PURE__ */ r("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))]", children: /* @__PURE__ */ r(h, { style: g }) })
|
|
129
129
|
]
|
|
130
130
|
}
|
|
131
131
|
);
|
|
132
|
-
return
|
|
132
|
+
return s ? /* @__PURE__ */ r(
|
|
133
133
|
f,
|
|
134
134
|
{
|
|
135
|
-
text:
|
|
135
|
+
text: a ? c ?? a : void 0,
|
|
136
136
|
placement: "right",
|
|
137
137
|
describesTrigger: !1,
|
|
138
|
-
suppressed: $(
|
|
138
|
+
suppressed: $(l["aria-expanded"]),
|
|
139
139
|
children: p
|
|
140
140
|
}
|
|
141
141
|
) : p;
|
|
@@ -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 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_WIDTH_PX,\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\nconst TOGGLE_LAYER =\n 'fixed top-[25px] z-[101] invisible opacity-0 [will-change:opacity] transition-[left,opacity,visibility] duration-200 ease-in-out group-hover/sidebar:visible group-hover/sidebar:opacity-100 group-has-[:focus-visible]/sidebar:visible group-has-[:focus-visible]/sidebar:opacity-100';\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 z-[100] box-border pt-[9px] bg-[var(--malachite-card-sunken-background,rgb(250,250,250))] transition-[width] duration-200 ease-in-out\"\n style={{ width }}\n >\n <nav aria-label={ariaLabel} className=\"flex h-full flex-col\">\n {children}\n </nav>\n {onToggleCollapse && (\n <div className={TOGGLE_LAYER} style={{ left: width - TOGGLE_SIZE_PX / 2 }}>\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}\n\nconst Switcher = forwardRef<HTMLButtonElement, SidebarSwitcherProps>(\n ({ logo, title, subtitle, className = '', ...rest }, ref) => {\n const { collapsed } = useSidebar();\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 <span className=\"block truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[14px] font-medium text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n {title}\n </span>\n {subtitle && (\n <span className=\"block truncate text-[12px] leading-[12px] font-normal text-[var(--malachite-text-secondary,rgb(123,123,123))]\">\n {subtitle}\n </span>\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}\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, 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 <span className=\"truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[22px] font-semibold text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n {name}\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/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}\n placement=\"right\"\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","SidebarRoot","collapsed","onToggleCollapse","expandLabel","collapseLabel","ariaLabel","children","toggleLabel","context","useMemo","width","SIDEBAR_WIDTH_PX","jsx","SidebarContext","jsxs","Tooltip","BORDER","FOCUS_RING","CaretRightIcon","CaretLeftIcon","Header","Body","NO_SCROLLBAR","Section","Group","GroupItems","Search","Notices","Divider","Footer","Switcher","forwardRef","logo","title","subtitle","className","rest","ref","ChevronsUpDownIcon","INITIALS","Account","avatar","initials","name","button","isExpanded","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 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_WIDTH_PX,\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\nconst TOGGLE_LAYER =\n 'fixed top-[25px] z-[101] invisible opacity-0 [will-change:opacity] transition-[left,opacity,visibility] duration-200 ease-in-out group-hover/sidebar:visible group-hover/sidebar:opacity-100 group-has-[:focus-visible]/sidebar:visible group-has-[:focus-visible]/sidebar:opacity-100';\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 z-[100] box-border pt-[9px] bg-[var(--malachite-card-sunken-background,rgb(250,250,250))] transition-[width] duration-200 ease-in-out\"\n style={{ width }}\n >\n <nav aria-label={ariaLabel} className=\"flex h-full flex-col\">\n {children}\n </nav>\n {onToggleCollapse && (\n <div className={TOGGLE_LAYER} style={{ left: width - TOGGLE_SIZE_PX / 2 }}>\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}\n\nconst Switcher = forwardRef<HTMLButtonElement, SidebarSwitcherProps>(\n ({ logo, title, subtitle, className = '', ...rest }, ref) => {\n const { collapsed } = useSidebar();\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 <span className=\"block truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[14px] font-medium text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n {title}\n </span>\n {subtitle && (\n <span className=\"block truncate text-[12px] leading-[12px] font-normal text-[var(--malachite-text-secondary,rgb(123,123,123))]\">\n {subtitle}\n </span>\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, a node so `name` can be wrapped (it renders outside the button);\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 <span className=\"truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[22px] font-semibold text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n {name}\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/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 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","SidebarRoot","collapsed","onToggleCollapse","expandLabel","collapseLabel","ariaLabel","children","toggleLabel","context","useMemo","width","SIDEBAR_WIDTH_PX","jsx","SidebarContext","jsxs","Tooltip","BORDER","FOCUS_RING","CaretRightIcon","CaretLeftIcon","Header","Body","NO_SCROLLBAR","Section","Group","GroupItems","Search","Notices","Divider","Footer","Switcher","forwardRef","logo","title","subtitle","className","rest","ref","ChevronsUpDownIcon","INITIALS","Account","avatar","initials","name","tooltip","button","isExpanded","Usage","props","UsageCard","Panel","SIDEBAR_POPOVER_WIDTH_PX","Sidebar"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4132,6 +4132,9 @@ export declare interface SidebarAccountProps extends SidebarButtonAttributes {
|
|
|
4132
4132
|
avatar?: default_2.ReactNode;
|
|
4133
4133
|
initials?: string;
|
|
4134
4134
|
name: string;
|
|
4135
|
+
/** Collapsed-rail tooltip, a node so `name` can be wrapped (it renders outside the button);
|
|
4136
|
+
* should read as `name`. Defaults to `name`, `false` hides it; none when `name` is empty. */
|
|
4137
|
+
tooltip?: default_2.ReactNode;
|
|
4135
4138
|
}
|
|
4136
4139
|
|
|
4137
4140
|
declare type SidebarButtonAttributes = Omit<default_2.ButtonHTMLAttributes<HTMLButtonElement>, 'style' | 'color' | 'children' | 'title' | 'name'>;
|
package/package.json
CHANGED