@particle-academy/react-fancy 6.1.1 → 6.3.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +1 -0
  3. package/dist/breadcrumbs.cjs +2 -2
  4. package/dist/breadcrumbs.d.cts +13 -2
  5. package/dist/breadcrumbs.d.ts +13 -2
  6. package/dist/breadcrumbs.js +1 -1
  7. package/dist/chunk-5EW47IH7.js +194 -0
  8. package/dist/chunk-5EW47IH7.js.map +1 -0
  9. package/dist/{chunk-WJHPZS3U.js → chunk-GTS3QA7M.js} +11 -4
  10. package/dist/chunk-GTS3QA7M.js.map +1 -0
  11. package/dist/{chunk-MTDOFZIB.js → chunk-JY2RC6I4.js} +37 -7
  12. package/dist/chunk-JY2RC6I4.js.map +1 -0
  13. package/dist/{chunk-GK7IGL7N.cjs → chunk-KOTUFZJ6.cjs} +37 -7
  14. package/dist/chunk-KOTUFZJ6.cjs.map +1 -0
  15. package/dist/{chunk-EWE776WI.cjs → chunk-SKMORSBO.cjs} +11 -4
  16. package/dist/chunk-SKMORSBO.cjs.map +1 -0
  17. package/dist/chunk-Y3QAEF2P.cjs +196 -0
  18. package/dist/chunk-Y3QAEF2P.cjs.map +1 -0
  19. package/dist/index.cjs +16 -11
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +1 -0
  22. package/dist/index.d.ts +1 -0
  23. package/dist/index.js +5 -4
  24. package/dist/index.js.map +1 -1
  25. package/dist/inputs.cjs +5 -5
  26. package/dist/inputs.js +1 -1
  27. package/dist/sidebar.cjs +7 -3
  28. package/dist/sidebar.d.cts +20 -1
  29. package/dist/sidebar.d.ts +20 -1
  30. package/dist/sidebar.js +5 -1
  31. package/dist/stepper.cjs +14 -0
  32. package/dist/stepper.cjs.map +1 -0
  33. package/dist/stepper.d.cts +72 -0
  34. package/dist/stepper.d.ts +72 -0
  35. package/dist/stepper.js +5 -0
  36. package/dist/stepper.js.map +1 -0
  37. package/docs/Breadcrumbs.md +10 -1
  38. package/docs/Sidebar.md +54 -0
  39. package/docs/Stepper.md +124 -0
  40. package/package.json +11 -1
  41. package/dist/chunk-EWE776WI.cjs.map +0 -1
  42. package/dist/chunk-GK7IGL7N.cjs.map +0 -1
  43. package/dist/chunk-MTDOFZIB.js.map +0 -1
  44. package/dist/chunk-WJHPZS3U.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -11,6 +11,71 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [6.3.0] - 2026-11-01
15
+
16
+ ### Added
17
+
18
+ - **`Stepper`: ordered steps with states (requested by Prism).** An `<ol>` of
19
+ steps, each with a title, optional description and rich content, in one of
20
+ `upcoming` / `current` / `complete` / `error`. Data-driven through a JSON-
21
+ friendly `steps` array, or compound with `Stepper.Step` (read as data, so both
22
+ forms render identically). Controlled (`current` + `onChange`) or
23
+ uncontrolled (`defaultCurrent`); a step's own `state` overrides the derived
24
+ one, which is how `error` is shown. **Pure content by default: no button,
25
+ input or form element at all.** `clickable` opts in to step buttons, with
26
+ arrow-key / Home / End focus movement. `aria-current="step"` on the current
27
+ step; each state is in visually hidden text and in the indicator's glyph,
28
+ never colour alone; `stateLabels` translates the words. Vertical by default,
29
+ `orientation="horizontal"` for short content; `showContent="current"` shows
30
+ only the current step's body. Server-renders without DOM globals. Handles:
31
+ `data-react-fancy-stepper`, `data-react-fancy-stepper-step` with `data-state`,
32
+ `data-index` and `data-step-id`. Subpath: `@particle-academy/react-fancy/stepper`.
33
+
34
+ ### Changed
35
+
36
+ - **`BreadcrumbsItemProps` now accepts the element's HTML attributes.**
37
+ `Breadcrumbs.Item` always forwarded `title`, `id`, `aria-*`, `style` and
38
+ handlers to the element it renders, but the type listed its keys by hand and
39
+ rejected them, so a consumer titling a truncated crumb had to cast. It now
40
+ extends `HTMLAttributes<HTMLElement>` (the attributes valid on every element a
41
+ crumb can be: `<a>`, the `as` component, `<button>`, `<span>`), with
42
+ `onClick` kept at its existing `() => void` signature. The collapsed (below
43
+ `md`) dropdown now carries a crumb's `title` onto its menu entry; other
44
+ attributes stay on the trail, because both trails are in the DOM at once and
45
+ an `id` or `data-*` handle would be duplicated. **No action needed:** this
46
+ only adds accepted props, and every existing usage type-checks unchanged.
47
+
48
+ ## [6.2.0] - 2026-11-01
49
+
50
+ ### Added
51
+
52
+ - **`Sidebar.Item` `dotTooltip`: the dot's words for sighted users.**
53
+ `dotLabel` reached screen readers only, and the item sets its own collapsed
54
+ `title`, so a consumer could not show those words. `dotTooltip` shows
55
+ `dotLabel` in a Fancy `Tooltip` to the right of the item on hover and
56
+ keyboard focus. It reuses `dotLabel` rather than taking separate text, so the
57
+ two audiences cannot be told different things. On a collapsed item it
58
+ replaces the native `title` (one bubble, not two) and shows the label above
59
+ the words. The bubble is `aria-hidden` and not wired as a description, since
60
+ the words are already in the accessible name. Inert without `dot` and
61
+ `dotLabel`. Handle: `data-react-fancy-sidebar-tooltip`.
62
+ - **`Sidebar.Item` `badgeLabel`: words for the badge.** A bare count ("2")
63
+ means nothing on its own to a screen reader. With `badgeLabel="2 agents"` the
64
+ visible badge gets `aria-hidden` and the label is added to the item's
65
+ accessible name as visually hidden text after a comma: "tynn, 2 agents". It
66
+ works expanded and on a collapsed rail with `collapsedBadge`, and composes
67
+ with `dotLabel` ("tynn needs you, 2 agents"). It is ignored while the badge is
68
+ not rendered. Handle: `data-react-fancy-sidebar-badge-label`.
69
+
70
+ ### Fixed
71
+
72
+ - **`Sidebar.Item`: an expanded item's label and badge ran together in the
73
+ accessible name ("tynn2").** A visually hidden space now separates them
74
+ ("tynn 2"). This adds one `<span class="sr-only"> </span>` before the badge
75
+ of an expanded item that has a `badge`; nothing changes visually, and items
76
+ without a badge render byte-identical markup. No consumer action needed,
77
+ unless you snapshot Sidebar markup, in which case expect that one element.
78
+
14
79
  ## [6.1.1] - 2026-11-01
15
80
 
16
81
  ### Fixed
package/README.md CHANGED
@@ -130,6 +130,7 @@ npx vite build # Build demo app (verifies imports work)
130
130
  | Card | Container with Header, Body, Footer compound slots | [docs](docs/Card.md) |
131
131
  | Callout | Alert/info box with icon, color, and dismissible support | [docs](docs/Callout.md) |
132
132
  | Timeline | Stacked, alternating, and horizontal timeline with data-driven or compound API | [docs](docs/Timeline.md) |
133
+ | Stepper | Ordered steps with upcoming / current / complete / error states; pure content by default, opt-in clickable steps | [docs](docs/Stepper.md) |
133
134
  | Marquee | Auto-scrolling ticker strip with seamless wrap, px/s speed, fade edges, reduced-motion gate | [docs](docs/Marquee.md) |
134
135
 
135
136
  ### Overlay & Floating
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkEWE776WI_cjs = require('./chunk-EWE776WI.cjs');
3
+ var chunkSKMORSBO_cjs = require('./chunk-SKMORSBO.cjs');
4
4
  require('./chunk-57FQGQJK.cjs');
5
5
  require('./chunk-OUYC6EIL.cjs');
6
6
  require('./chunk-ZU5Q77OT.cjs');
@@ -9,7 +9,7 @@ require('./chunk-ZU5Q77OT.cjs');
9
9
 
10
10
  Object.defineProperty(exports, "Breadcrumbs", {
11
11
  enumerable: true,
12
- get: function () { return chunkEWE776WI_cjs.Breadcrumbs; }
12
+ get: function () { return chunkSKMORSBO_cjs.Breadcrumbs; }
13
13
  });
14
14
  //# sourceMappingURL=breadcrumbs.cjs.map
15
15
  //# sourceMappingURL=breadcrumbs.cjs.map
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, HTMLAttributes } from 'react';
3
3
  import { N as NavigableProps } from './types-DJI492iY.cjs';
4
4
 
5
5
  interface BreadcrumbsProps {
@@ -8,7 +8,18 @@ interface BreadcrumbsProps {
8
8
  shrink?: boolean;
9
9
  className?: string;
10
10
  }
11
- interface BreadcrumbsItemProps extends NavigableProps {
11
+ /**
12
+ * A crumb accepts the HTML attributes common to every element it can render as
13
+ * (`<a>`, the `as` component, `<button>` or `<span>`), so `title`, `id`,
14
+ * `aria-*`, `style` and handlers are typed as well as forwarded. Typed against
15
+ * `HTMLElement` rather than one element because the crumb's element depends on
16
+ * its props; anchor-only attributes such as `target` are not offered, since the
17
+ * same crumb renders as a `<span>` once it is `active`.
18
+ *
19
+ * `onClick` is omitted from the element's attributes and redeclared below with
20
+ * its existing `() => void` signature.
21
+ */
22
+ interface BreadcrumbsItemProps extends NavigableProps, Omit<HTMLAttributes<HTMLElement>, "onClick" | "children"> {
12
23
  children: ReactNode;
13
24
  active?: boolean;
14
25
  /**
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, HTMLAttributes } from 'react';
3
3
  import { N as NavigableProps } from './types-DJI492iY.js';
4
4
 
5
5
  interface BreadcrumbsProps {
@@ -8,7 +8,18 @@ interface BreadcrumbsProps {
8
8
  shrink?: boolean;
9
9
  className?: string;
10
10
  }
11
- interface BreadcrumbsItemProps extends NavigableProps {
11
+ /**
12
+ * A crumb accepts the HTML attributes common to every element it can render as
13
+ * (`<a>`, the `as` component, `<button>` or `<span>`), so `title`, `id`,
14
+ * `aria-*`, `style` and handlers are typed as well as forwarded. Typed against
15
+ * `HTMLElement` rather than one element because the crumb's element depends on
16
+ * its props; anchor-only attributes such as `target` are not offered, since the
17
+ * same crumb renders as a `<span>` once it is `active`.
18
+ *
19
+ * `onClick` is omitted from the element's attributes and redeclared below with
20
+ * its existing `() => void` signature.
21
+ */
22
+ interface BreadcrumbsItemProps extends NavigableProps, Omit<HTMLAttributes<HTMLElement>, "onClick" | "children"> {
12
23
  children: ReactNode;
13
24
  active?: boolean;
14
25
  /**
@@ -1,4 +1,4 @@
1
- export { Breadcrumbs } from './chunk-WJHPZS3U.js';
1
+ export { Breadcrumbs } from './chunk-GTS3QA7M.js';
2
2
  import './chunk-RGANGU7X.js';
3
3
  import './chunk-YX6FTJ6N.js';
4
4
  import './chunk-MMW2JGKZ.js';
@@ -0,0 +1,194 @@
1
+ import { useControllableState } from './chunk-EDYAXGUM.js';
2
+ import { cn } from './chunk-MMW2JGKZ.js';
3
+ import { forwardRef, Children, isValidElement } from 'react';
4
+ import { Check } from 'lucide-react';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+
7
+ var DEFAULT_STATE_LABELS = {
8
+ upcoming: "Not started",
9
+ current: "Current",
10
+ complete: "Completed",
11
+ error: "Error"
12
+ };
13
+ function StepperStep(_props) {
14
+ return null;
15
+ }
16
+ StepperStep.displayName = "StepperStep";
17
+ function stepsFromChildren(children) {
18
+ const out = [];
19
+ for (const child of Children.toArray(children)) {
20
+ if (!isValidElement(child) || child.type !== StepperStep) continue;
21
+ const { children: content, ...rest } = child.props;
22
+ out.push({ ...rest, content });
23
+ }
24
+ return out;
25
+ }
26
+ var indicatorClass = {
27
+ complete: "border-transparent bg-zinc-900 text-white dark:bg-white dark:text-zinc-900",
28
+ current: "border-2 border-zinc-900 bg-[color:var(--fancy-surface,var(--color-white))] text-zinc-900 ring-4 ring-zinc-900/10 dark:border-white dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))] dark:text-white dark:ring-white/15",
29
+ upcoming: "border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-surface,var(--color-white))] text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]",
30
+ error: "border-transparent bg-red-600 text-white dark:bg-red-500"
31
+ };
32
+ var titleClass = {
33
+ complete: "font-medium text-zinc-900 dark:text-white",
34
+ current: "font-semibold text-zinc-900 dark:text-white",
35
+ upcoming: "font-medium text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]",
36
+ error: "font-semibold text-red-700 dark:text-red-400"
37
+ };
38
+ function Indicator({ state, index }) {
39
+ return /* @__PURE__ */ jsx(
40
+ "span",
41
+ {
42
+ "aria-hidden": "true",
43
+ "data-react-fancy-stepper-indicator": "",
44
+ className: cn(
45
+ "relative z-10 flex h-8 w-8 shrink-0 items-center justify-center rounded-full border text-sm font-semibold",
46
+ indicatorClass[state]
47
+ ),
48
+ children: state === "complete" ? /* @__PURE__ */ jsx(Check, { size: 16, strokeWidth: 3 }) : state === "error" ? "!" : index + 1
49
+ }
50
+ );
51
+ }
52
+ var StepperRoot = forwardRef(
53
+ ({
54
+ steps: stepsProp,
55
+ children,
56
+ current: currentProp,
57
+ defaultCurrent = 0,
58
+ onChange,
59
+ orientation = "vertical",
60
+ clickable = false,
61
+ showContent = "all",
62
+ stateLabels,
63
+ className,
64
+ onKeyDown,
65
+ ...rest
66
+ }, ref) => {
67
+ const [current, setCurrent] = useControllableState(currentProp, defaultCurrent, onChange);
68
+ const steps = stepsProp ?? stepsFromChildren(children);
69
+ const labels = { ...DEFAULT_STATE_LABELS, ...stateLabels };
70
+ const horizontal = orientation === "horizontal";
71
+ const handleKeyDown = (e) => {
72
+ onKeyDown?.(e);
73
+ if (!clickable || e.defaultPrevented) return;
74
+ const prevKey = horizontal ? "ArrowLeft" : "ArrowUp";
75
+ const nextKey = horizontal ? "ArrowRight" : "ArrowDown";
76
+ if (![prevKey, nextKey, "Home", "End"].includes(e.key)) return;
77
+ const list = e.currentTarget;
78
+ const target = e.target.closest("[data-react-fancy-stepper-trigger]");
79
+ if (!target || target.closest("[data-react-fancy-stepper]") !== list) return;
80
+ const buttons = Array.from(
81
+ list.querySelectorAll("[data-react-fancy-stepper-trigger]")
82
+ ).filter((b) => b.closest("[data-react-fancy-stepper]") === list && !b.disabled);
83
+ const at = buttons.indexOf(target);
84
+ let next;
85
+ if (e.key === "Home") next = buttons[0];
86
+ else if (e.key === "End") next = buttons[buttons.length - 1];
87
+ else if (e.key === nextKey) next = buttons[at + 1] ?? target;
88
+ else next = at > 0 ? buttons[at - 1] : target;
89
+ e.preventDefault();
90
+ next?.focus();
91
+ };
92
+ return /* @__PURE__ */ jsx(
93
+ "ol",
94
+ {
95
+ ref,
96
+ "data-react-fancy-stepper": "",
97
+ "data-orientation": orientation,
98
+ "data-current": current,
99
+ className: cn(horizontal ? "flex items-start" : "flex flex-col", className),
100
+ onKeyDown: handleKeyDown,
101
+ ...rest,
102
+ children: steps.map((step, index) => {
103
+ const derived = index < current ? "complete" : index === current ? "current" : "upcoming";
104
+ const state = step.state ?? derived;
105
+ const isCurrent = index === current;
106
+ const isLast = index === steps.length - 1;
107
+ const showBody = step.content != null && (showContent === "all" || isCurrent);
108
+ const headerInner = /* @__PURE__ */ jsxs(Fragment, { children: [
109
+ /* @__PURE__ */ jsx(Indicator, { state, index }),
110
+ /* @__PURE__ */ jsxs("span", { className: "sr-only", "data-react-fancy-stepper-state": "", children: [
111
+ labels[state],
112
+ ":",
113
+ " "
114
+ ] }),
115
+ /* @__PURE__ */ jsx("span", { "data-react-fancy-stepper-title": "", className: cn("text-sm", titleClass[state]), children: step.title })
116
+ ] });
117
+ const headerClass = horizontal ? "flex flex-col items-center gap-2 text-center" : "flex items-center gap-x-4 text-left";
118
+ const header = clickable ? /* @__PURE__ */ jsx(
119
+ "button",
120
+ {
121
+ type: "button",
122
+ "data-react-fancy-stepper-trigger": "",
123
+ disabled: step.disabled,
124
+ onClick: () => {
125
+ if (index !== current) setCurrent(index);
126
+ },
127
+ className: cn(
128
+ headerClass,
129
+ "cursor-pointer rounded-md border-0 bg-transparent p-0",
130
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
131
+ "focus-visible:ring-[color:var(--fancy-focus,var(--color-blue-500))] focus-visible:ring-offset-[color:var(--fancy-surface,var(--color-white))]",
132
+ "dark:focus-visible:ring-[color:var(--fancy-focus-dark,var(--color-blue-400))] dark:focus-visible:ring-offset-[color:var(--fancy-surface-dark,var(--color-zinc-900))]",
133
+ "disabled:cursor-not-allowed disabled:opacity-50"
134
+ ),
135
+ children: headerInner
136
+ }
137
+ ) : /* @__PURE__ */ jsx("div", { className: headerClass, children: headerInner });
138
+ return /* @__PURE__ */ jsxs(
139
+ "li",
140
+ {
141
+ "data-react-fancy-stepper-step": "",
142
+ "data-state": state,
143
+ "data-index": index,
144
+ "data-step-id": step.id,
145
+ "data-disabled": step.disabled ? "true" : void 0,
146
+ "aria-current": isCurrent ? "step" : void 0,
147
+ className: cn("relative", horizontal ? "min-w-0 flex-1" : !isLast && "pb-8"),
148
+ children: [
149
+ !isLast && /* @__PURE__ */ jsx(
150
+ "span",
151
+ {
152
+ "aria-hidden": "true",
153
+ "data-react-fancy-stepper-connector": "",
154
+ className: cn(
155
+ "absolute",
156
+ horizontal ? "top-4 left-[calc(50%+1.5rem)] h-px w-[calc(100%-3rem)]" : "top-10 bottom-2 left-4 w-px -translate-x-1/2",
157
+ index < current ? "bg-zinc-900 dark:bg-white" : "bg-[color:var(--fancy-border,var(--color-zinc-200))] dark:bg-[color:var(--fancy-border-dark,var(--color-zinc-700))]"
158
+ )
159
+ }
160
+ ),
161
+ header,
162
+ (step.description != null || showBody) && /* @__PURE__ */ jsxs("div", { className: horizontal ? "mt-1 px-2 text-center" : "pl-12", children: [
163
+ step.description != null && /* @__PURE__ */ jsx(
164
+ "div",
165
+ {
166
+ "data-react-fancy-stepper-description": "",
167
+ className: "text-sm text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]",
168
+ children: step.description
169
+ }
170
+ ),
171
+ showBody && /* @__PURE__ */ jsx(
172
+ "div",
173
+ {
174
+ "data-react-fancy-stepper-content": "",
175
+ className: "mt-2 text-sm text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))]",
176
+ children: step.content
177
+ }
178
+ )
179
+ ] })
180
+ ]
181
+ },
182
+ step.id ?? index
183
+ );
184
+ })
185
+ }
186
+ );
187
+ }
188
+ );
189
+ StepperRoot.displayName = "Stepper";
190
+ var Stepper = Object.assign(StepperRoot, { Step: StepperStep });
191
+
192
+ export { Stepper };
193
+ //# sourceMappingURL=chunk-5EW47IH7.js.map
194
+ //# sourceMappingURL=chunk-5EW47IH7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Stepper/Stepper.tsx"],"names":[],"mappings":"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","file":"chunk-5EW47IH7.js","sourcesContent":["import {\n Children,\n forwardRef,\n isValidElement,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\nimport { Check } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type {\n StepperProps,\n StepperStep as StepperStepData,\n StepperStepProps,\n StepperStepState,\n} from \"./Stepper.types\";\n\nconst DEFAULT_STATE_LABELS: Record<StepperStepState, string> = {\n upcoming: \"Not started\",\n current: \"Current\",\n complete: \"Completed\",\n error: \"Error\",\n};\n\n/**\n * Declarative step. Renders nothing itself: `Stepper` reads its props as data\n * and renders it through the same path as an entry in `steps`, so the two forms\n * cannot drift apart in markup, states or handles. Its children are the step's\n * content. It must be a DIRECT child of `Stepper` (not wrapped in another\n * component) for the same reason `Breadcrumbs.Item` must.\n */\nfunction StepperStep(_props: StepperStepProps): null {\n return null;\n}\nStepperStep.displayName = \"StepperStep\";\n\nfunction stepsFromChildren(children: ReactNode): StepperStepData[] {\n const out: StepperStepData[] = [];\n for (const child of Children.toArray(children)) {\n if (!isValidElement<StepperStepProps>(child) || child.type !== StepperStep) continue;\n const { children: content, ...rest } = child.props;\n out.push({ ...rest, content });\n }\n return out;\n}\n\nconst indicatorClass: Record<StepperStepState, string> = {\n complete:\n \"border-transparent bg-zinc-900 text-white dark:bg-white dark:text-zinc-900\",\n current:\n \"border-2 border-zinc-900 bg-[color:var(--fancy-surface,var(--color-white))] text-zinc-900 ring-4 ring-zinc-900/10 dark:border-white dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))] dark:text-white dark:ring-white/15\",\n upcoming:\n \"border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-surface,var(--color-white))] text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]\",\n error: \"border-transparent bg-red-600 text-white dark:bg-red-500\",\n};\n\nconst titleClass: Record<StepperStepState, string> = {\n complete: \"font-medium text-zinc-900 dark:text-white\",\n current: \"font-semibold text-zinc-900 dark:text-white\",\n upcoming:\n \"font-medium text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]\",\n error: \"font-semibold text-red-700 dark:text-red-400\",\n};\n\n/** The glyph differs per state, so state reads without colour: number, tick, \"!\". */\nfunction Indicator({ state, index }: { state: StepperStepState; index: number }) {\n return (\n <span\n aria-hidden=\"true\"\n data-react-fancy-stepper-indicator=\"\"\n className={cn(\n \"relative z-10 flex h-8 w-8 shrink-0 items-center justify-center rounded-full border text-sm font-semibold\",\n indicatorClass[state],\n )}\n >\n {state === \"complete\" ? <Check size={16} strokeWidth={3} /> : state === \"error\" ? \"!\" : index + 1}\n </span>\n );\n}\n\nconst StepperRoot = forwardRef<HTMLOListElement, StepperProps>(\n (\n {\n steps: stepsProp,\n children,\n current: currentProp,\n defaultCurrent = 0,\n onChange,\n orientation = \"vertical\",\n clickable = false,\n showContent = \"all\",\n stateLabels,\n className,\n onKeyDown,\n ...rest\n },\n ref,\n ) => {\n const [current, setCurrent] = useControllableState(currentProp, defaultCurrent, onChange);\n const steps = stepsProp ?? stepsFromChildren(children);\n const labels = { ...DEFAULT_STATE_LABELS, ...stateLabels };\n const horizontal = orientation === \"horizontal\";\n\n // Arrow keys move focus between step buttons; Enter / Space activate them\n // natively. Focus only -- the current step changes on activation, never on\n // arrowing past it. DOM is read in the handler, never during render.\n const handleKeyDown = (e: KeyboardEvent<HTMLOListElement>) => {\n onKeyDown?.(e);\n if (!clickable || e.defaultPrevented) return;\n\n const prevKey = horizontal ? \"ArrowLeft\" : \"ArrowUp\";\n const nextKey = horizontal ? \"ArrowRight\" : \"ArrowDown\";\n if (![prevKey, nextKey, \"Home\", \"End\"].includes(e.key)) return;\n\n const list = e.currentTarget;\n const target = (e.target as HTMLElement).closest<HTMLButtonElement>(\"[data-react-fancy-stepper-trigger]\");\n if (!target || target.closest(\"[data-react-fancy-stepper]\") !== list) return;\n\n // Only this stepper's own buttons: a stepper nested in step content is\n // its own list.\n const buttons = Array.from(\n list.querySelectorAll<HTMLButtonElement>(\"[data-react-fancy-stepper-trigger]\"),\n ).filter((b) => b.closest(\"[data-react-fancy-stepper]\") === list && !b.disabled);\n const at = buttons.indexOf(target);\n\n let next: HTMLButtonElement | undefined;\n if (e.key === \"Home\") next = buttons[0];\n else if (e.key === \"End\") next = buttons[buttons.length - 1];\n else if (e.key === nextKey) next = buttons[at + 1] ?? target;\n else next = at > 0 ? buttons[at - 1] : target;\n\n e.preventDefault();\n next?.focus();\n };\n\n return (\n <ol\n ref={ref}\n data-react-fancy-stepper=\"\"\n data-orientation={orientation}\n data-current={current}\n className={cn(horizontal ? \"flex items-start\" : \"flex flex-col\", className)}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {steps.map((step, index) => {\n const derived: StepperStepState =\n index < current ? \"complete\" : index === current ? \"current\" : \"upcoming\";\n const state = step.state ?? derived;\n const isCurrent = index === current;\n const isLast = index === steps.length - 1;\n const showBody = step.content != null && (showContent === \"all\" || isCurrent);\n\n const headerInner = (\n <>\n <Indicator state={state} index={index} />\n {/* State in words, before the title so it is read first. A\n sibling of the title, so the title handle reads the title. */}\n <span className=\"sr-only\" data-react-fancy-stepper-state=\"\">\n {labels[state]}:{\" \"}\n </span>\n <span data-react-fancy-stepper-title=\"\" className={cn(\"text-sm\", titleClass[state])}>\n {step.title}\n </span>\n </>\n );\n\n const headerClass = horizontal\n ? \"flex flex-col items-center gap-2 text-center\"\n : \"flex items-center gap-x-4 text-left\";\n\n const header = clickable ? (\n <button\n type=\"button\"\n data-react-fancy-stepper-trigger=\"\"\n disabled={step.disabled}\n onClick={() => {\n if (index !== current) setCurrent(index);\n }}\n className={cn(\n headerClass,\n \"cursor-pointer rounded-md border-0 bg-transparent p-0\",\n \"focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2\",\n \"focus-visible:ring-[color:var(--fancy-focus,var(--color-blue-500))] focus-visible:ring-offset-[color:var(--fancy-surface,var(--color-white))]\",\n \"dark:focus-visible:ring-[color:var(--fancy-focus-dark,var(--color-blue-400))] dark:focus-visible:ring-offset-[color:var(--fancy-surface-dark,var(--color-zinc-900))]\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n )}\n >\n {headerInner}\n </button>\n ) : (\n <div className={headerClass}>{headerInner}</div>\n );\n\n return (\n <li\n key={step.id ?? index}\n data-react-fancy-stepper-step=\"\"\n data-state={state}\n data-index={index}\n data-step-id={step.id}\n data-disabled={step.disabled ? \"true\" : undefined}\n aria-current={isCurrent ? \"step\" : undefined}\n className={cn(\"relative\", horizontal ? \"min-w-0 flex-1\" : !isLast && \"pb-8\")}\n >\n {!isLast && (\n <span\n aria-hidden=\"true\"\n data-react-fancy-stepper-connector=\"\"\n className={cn(\n \"absolute\",\n horizontal\n ? \"top-4 left-[calc(50%+1.5rem)] h-px w-[calc(100%-3rem)]\"\n : \"top-10 bottom-2 left-4 w-px -translate-x-1/2\",\n index < current\n ? \"bg-zinc-900 dark:bg-white\"\n : \"bg-[color:var(--fancy-border,var(--color-zinc-200))] dark:bg-[color:var(--fancy-border-dark,var(--color-zinc-700))]\",\n )}\n />\n )}\n {header}\n {(step.description != null || showBody) && (\n <div className={horizontal ? \"mt-1 px-2 text-center\" : \"pl-12\"}>\n {step.description != null && (\n <div\n data-react-fancy-stepper-description=\"\"\n className=\"text-sm text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]\"\n >\n {step.description}\n </div>\n )}\n {showBody && (\n <div\n data-react-fancy-stepper-content=\"\"\n className=\"mt-2 text-sm text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))]\"\n >\n {step.content}\n </div>\n )}\n </div>\n )}\n </li>\n );\n })}\n </ol>\n );\n },\n);\n\nStepperRoot.displayName = \"Stepper\";\n\nexport const Stepper = Object.assign(StepperRoot, { Step: StepperStep });\n"]}
@@ -78,6 +78,7 @@ function BreadcrumbsDropdown({ items, activeLabel }) {
78
78
  Link,
79
79
  {
80
80
  ...item.href ? { href: item.href } : {},
81
+ title: item.title,
81
82
  className: cls,
82
83
  onClick: () => {
83
84
  item.onClick?.();
@@ -94,6 +95,7 @@ function BreadcrumbsDropdown({ items, activeLabel }) {
94
95
  "button",
95
96
  {
96
97
  type: "button",
98
+ title: item.title,
97
99
  className: cn(cls, "cursor-pointer border-0 bg-transparent"),
98
100
  onClick: () => {
99
101
  onClick();
@@ -104,7 +106,7 @@ function BreadcrumbsDropdown({ items, activeLabel }) {
104
106
  i
105
107
  );
106
108
  }
107
- return /* @__PURE__ */ jsx("span", { className: cls, children: item.label }, i);
109
+ return /* @__PURE__ */ jsx("span", { title: item.title, className: cls, children: item.label }, i);
108
110
  }) })
109
111
  ] });
110
112
  }
@@ -126,7 +128,12 @@ function BreadcrumbsRoot({
126
128
  href: el.props?.href,
127
129
  as: el.props?.as,
128
130
  onClick: el.props?.onClick,
129
- active: el.props?.active
131
+ active: el.props?.active,
132
+ // Only `title` crosses into the menu. It is the full text of a crumb the
133
+ // consumer truncated, and the narrow menu is where labels get cut. Other
134
+ // attributes stay on the trail: both trails are in the DOM at once (CSS
135
+ // hides one), so an `id` or a `data-*` handle would be duplicated.
136
+ title: el.props?.title
130
137
  };
131
138
  });
132
139
  const activeLabel = dropdownItems[dropdownItems.length - 1]?.label ?? "Menu";
@@ -166,5 +173,5 @@ var Breadcrumbs = Object.assign(BreadcrumbsRoot, {
166
173
  });
167
174
 
168
175
  export { Breadcrumbs };
169
- //# sourceMappingURL=chunk-WJHPZS3U.js.map
170
- //# sourceMappingURL=chunk-WJHPZS3U.js.map
176
+ //# sourceMappingURL=chunk-GTS3QA7M.js.map
177
+ //# sourceMappingURL=chunk-GTS3QA7M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Breadcrumbs/BreadcrumbsItem.tsx","../src/components/Breadcrumbs/BreadcrumbsDropdown.tsx","../src/components/Breadcrumbs/Breadcrumbs.tsx"],"names":["jsx","useState","jsxs","Fragment"],"mappings":"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","file":"chunk-GTS3QA7M.js","sourcesContent":["import type { ElementType } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport type { BreadcrumbsItemProps } from \"./Breadcrumbs.types\";\n\nexport function BreadcrumbsItem({\n children,\n href,\n as: As,\n active = false,\n onClick,\n className,\n ...rest\n}: BreadcrumbsItemProps) {\n const baseClass = cn(\n \"text-sm\",\n active\n ? \"font-medium text-zinc-900 dark:text-white\"\n : \"text-[color:var(--fancy-text-muted,var(--color-zinc-500))] hover:text-[color:var(--fancy-text-soft,var(--color-zinc-700))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))] dark:hover:text-[color:var(--fancy-text-soft-dark,var(--color-zinc-300))]\",\n className,\n );\n\n // The CURRENT crumb stays a <span> even with `as`: it is the page you are on,\n // so a link to it is a link to nowhere, and `aria-current=\"page\"` is the point.\n if ((href || As) && !active) {\n const Link = (As ?? \"a\") as ElementType;\n\n return (\n <Link\n data-react-fancy-breadcrumbs-item=\"\"\n {...(href ? { href } : {})}\n onClick={onClick}\n className={baseClass}\n {...rest}\n >\n {children}\n </Link>\n );\n }\n\n // A crumb that navigates through a callback rather than a URL. Controlled\n // components own their navigation and have no href to give — a repository\n // browser walking directories, a wizard stepping back — and until this\n // existed the only way to make such a crumb clickable was to nest a button\n // inside the span below, which is interactive content inside a non-\n // interactive element.\n if (onClick && !active) {\n return (\n <button\n type=\"button\"\n data-react-fancy-breadcrumbs-item=\"\"\n onClick={onClick}\n className={cn(baseClass, \"cursor-pointer border-0 bg-transparent p-0\")}\n {...rest}\n >\n {children}\n </button>\n );\n }\n\n return (\n <span data-react-fancy-breadcrumbs-item=\"\" className={baseClass} aria-current={active ? \"page\" : undefined} {...rest}>\n {children}\n </span>\n );\n}\n\nBreadcrumbsItem.displayName = \"BreadcrumbsItem\";\n","import { useState, useRef, type ElementType, type ReactNode } from \"react\";\nimport { ChevronDown } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { useOutsideClick } from \"../../hooks/use-outside-click\";\nimport { useEscapeKey } from \"../../hooks/use-escape-key\";\n\ninterface BreadcrumbsDropdownItem {\n label: ReactNode;\n href?: string;\n as?: ElementType;\n onClick?: () => void;\n active?: boolean;\n title?: string;\n}\n\ninterface BreadcrumbsDropdownProps {\n items: BreadcrumbsDropdownItem[];\n activeLabel: ReactNode;\n}\n\nexport function BreadcrumbsDropdown({ items, activeLabel }: BreadcrumbsDropdownProps) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useOutsideClick(ref, () => setOpen(false), open);\n useEscapeKey(() => setOpen(false), open);\n\n return (\n <div ref={ref} data-react-fancy-breadcrumbs-dropdown=\"\" className=\"relative flex md:hidden\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"flex items-center gap-1 rounded-lg px-2 py-1 text-sm font-medium text-zinc-900 hover:bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:text-white dark:hover:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\"\n >\n {activeLabel}\n <ChevronDown size={14} className={cn(\"transition-transform\", open && \"rotate-180\")} />\n </button>\n {open && (\n <div className=\"absolute top-full left-0 z-50 mt-1 min-w-[180px] rounded-lg border border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-surface,var(--color-white))] py-1 shadow-lg dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))]\">\n {items.map((item, i) => {\n const cls = cn(\n \"block w-full px-3 py-1.5 text-left text-sm\",\n item.active\n ? \"font-medium text-zinc-900 dark:text-white\"\n : \"text-[color:var(--fancy-text-muted,var(--color-zinc-500))] hover:bg-zinc-50 hover:text-[color:var(--fancy-text-soft,var(--color-zinc-700))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))] dark:hover:bg-zinc-800 dark:hover:text-[color:var(--fancy-text-soft-dark,var(--color-zinc-300))]\",\n );\n\n // Mirrors BreadcrumbsItem: href / `as` wins, then onClick, and the\n // active crumb stays inert whatever it carries.\n if ((item.href || item.as) && !item.active) {\n const Link = (item.as ?? \"a\") as ElementType;\n return (\n <Link\n key={i}\n {...(item.href ? { href: item.href } : {})}\n title={item.title}\n className={cls}\n onClick={() => {\n item.onClick?.();\n setOpen(false);\n }}\n >\n {item.label}\n </Link>\n );\n }\n\n if (item.onClick && !item.active) {\n const onClick = item.onClick;\n return (\n <button\n key={i}\n type=\"button\"\n title={item.title}\n className={cn(cls, \"cursor-pointer border-0 bg-transparent\")}\n onClick={() => {\n onClick();\n setOpen(false);\n }}\n >\n {item.label}\n </button>\n );\n }\n\n return (\n <span key={i} title={item.title} className={cls}>\n {item.label}\n </span>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\nBreadcrumbsDropdown.displayName = \"BreadcrumbsDropdown\";\n","import { Children, Fragment, useState, type ReactElement } from \"react\";\nimport { ChevronRight } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { BreadcrumbsItem } from \"./BreadcrumbsItem\";\nimport { BreadcrumbsDropdown } from \"./BreadcrumbsDropdown\";\nimport type { BreadcrumbsProps, BreadcrumbsItemProps } from \"./Breadcrumbs.types\";\n\nfunction BreadcrumbsRoot({\n children,\n separator,\n shrink,\n className,\n}: BreadcrumbsProps) {\n const items = Children.toArray(children);\n const [expanded, setExpanded] = useState(false);\n\n const sep = separator ?? (\n <ChevronRight size={12} className=\"text-zinc-400\" />\n );\n\n const lastItem = items[items.length - 1];\n\n // Extract info from children for mobile dropdown\n const dropdownItems = items.map((child) => {\n const el = child as ReactElement<BreadcrumbsItemProps>;\n return {\n label: el.props?.children,\n href: el.props?.href,\n as: el.props?.as,\n onClick: el.props?.onClick,\n active: el.props?.active,\n // Only `title` crosses into the menu. It is the full text of a crumb the\n // consumer truncated, and the narrow menu is where labels get cut. Other\n // attributes stay on the trail: both trails are in the DOM at once (CSS\n // hides one), so an `id` or a `data-*` handle would be duplicated.\n title: el.props?.title,\n };\n });\n\n const activeLabel = dropdownItems[dropdownItems.length - 1]?.label ?? \"Menu\";\n\n const showShrunk = shrink && !expanded && items.length > 1;\n\n return (\n <>\n {/* Desktop trail */}\n <nav\n data-react-fancy-breadcrumbs=\"\"\n aria-label=\"Breadcrumb\"\n className={cn(\"hidden items-center gap-2 md:flex\", className)}\n onMouseLeave={() => shrink && setExpanded(false)}\n >\n {showShrunk ? (\n <>\n <button\n type=\"button\"\n onClick={() => setExpanded(true)}\n onMouseEnter={() => setExpanded(true)}\n className=\"text-sm text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300\"\n >\n ...\n </button>\n <span aria-hidden=\"true\">{sep}</span>\n {lastItem}\n </>\n ) : (\n items.map((child, i) => (\n <Fragment key={i}>\n {i > 0 && <span aria-hidden=\"true\">{sep}</span>}\n {child}\n </Fragment>\n ))\n )}\n </nav>\n\n {/* Mobile dropdown */}\n <BreadcrumbsDropdown items={dropdownItems} activeLabel={activeLabel} />\n </>\n );\n}\n\nexport const Breadcrumbs = Object.assign(BreadcrumbsRoot, {\n Item: BreadcrumbsItem,\n});\n"]}
@@ -1,3 +1,4 @@
1
+ import { Tooltip } from './chunk-GR2WKBER.js';
1
2
  import { badgeDot } from './chunk-S53A6JIE.js';
2
3
  import { useControllableState } from './chunk-EDYAXGUM.js';
3
4
  import { cn } from './chunk-MMW2JGKZ.js';
@@ -118,9 +119,11 @@ function SidebarItem({
118
119
  active = false,
119
120
  disabled = false,
120
121
  badge,
122
+ badgeLabel,
121
123
  collapsedBadge = false,
122
124
  dot,
123
125
  dotLabel,
126
+ dotTooltip = false,
124
127
  onClick,
125
128
  className,
126
129
  ...rest
@@ -135,13 +138,19 @@ function SidebarItem({
135
138
  const dotColor = dot === true ? "red" : dot || null;
136
139
  const showCollapsedBadge = collapsed && collapsedBadge && Boolean(badge);
137
140
  const hasMarks = dotColor !== null || showCollapsedBadge;
141
+ const badgeShown = Boolean(badge) && (!collapsed || showCollapsedBadge);
142
+ const badgeLabelEl = badgeShown && badgeLabel ? (
143
+ // The comma is the separator, so whatever renders before this must not
144
+ // end in a space ("tynn , 2 agents"); see the two trailing spaces below.
145
+ /* @__PURE__ */ jsx("span", { className: "sr-only", "data-react-fancy-sidebar-badge-label": "", children: `, ${badgeLabel}` })
146
+ ) : null;
138
147
  const dotLabelEl = dotColor && dotLabel ? (
139
148
  // The spaces are load-bearing: adjacent inline elements concatenate in
140
149
  // the accessible name, so without them it reads "Inbox3 unread".
141
150
  /* @__PURE__ */ jsxs("span", { className: "sr-only", "data-react-fancy-sidebar-dot-label": "", children: [
142
151
  " ",
143
152
  dotLabel,
144
- " "
153
+ badgeLabelEl ? null : " "
145
154
  ] })
146
155
  ) : null;
147
156
  const needsHiddenLabel = collapsed && (dotLabelEl !== null || showCollapsedBadge);
@@ -150,6 +159,7 @@ function SidebarItem({
150
159
  "span",
151
160
  {
152
161
  "data-react-fancy-sidebar-badge": "",
162
+ "aria-hidden": badgeLabelEl ? "true" : void 0,
153
163
  className: "pointer-events-none absolute -right-3 -top-2.5 whitespace-nowrap",
154
164
  children: badge
155
165
  }
@@ -173,7 +183,8 @@ function SidebarItem({
173
183
  "flex h-5 w-5 shrink-0 items-center justify-center",
174
184
  hasMarks && "relative"
175
185
  );
176
- return /* @__PURE__ */ jsxs(
186
+ const showDotTooltip = dotTooltip && dotLabelEl !== null;
187
+ const node = /* @__PURE__ */ jsxs(
177
188
  Tag,
178
189
  {
179
190
  ...tagProps,
@@ -182,7 +193,7 @@ function SidebarItem({
182
193
  "data-active": active || void 0,
183
194
  "aria-current": active ? "page" : void 0,
184
195
  "aria-disabled": disabled || void 0,
185
- title: collapsed ? title : void 0,
196
+ title: collapsed && !showDotTooltip ? title : void 0,
186
197
  className: cn(
187
198
  // `w-full` matters when the Tag is a <button>: form controls size to
188
199
  // FIT-CONTENT, not to their parent, so a long label made the item wider
@@ -203,9 +214,10 @@ function SidebarItem({
203
214
  children: [
204
215
  needsHiddenLabel && /* @__PURE__ */ jsxs("span", { className: "sr-only", "data-react-fancy-sidebar-label": "", children: [
205
216
  children,
206
- " "
217
+ badgeLabelEl && !dotLabelEl ? null : " "
207
218
  ] }),
208
219
  collapsed && dotLabelEl,
220
+ collapsed && badgeLabelEl,
209
221
  showIconOnly && /* @__PURE__ */ jsxs("span", { className: iconClass, children: [
210
222
  icon,
211
223
  renderMarks(false)
@@ -229,11 +241,29 @@ function SidebarItem({
229
241
  !icon && renderMarks(true),
230
242
  /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-left", children }),
231
243
  dotLabelEl,
232
- badge && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: badge })
244
+ badge && (badgeLabelEl ?? /* @__PURE__ */ jsx("span", { className: "sr-only", children: " " })),
245
+ badge && /* @__PURE__ */ jsx("span", { className: "shrink-0", "aria-hidden": badgeLabelEl ? "true" : void 0, children: badge })
233
246
  ] })
234
247
  ]
235
248
  }
236
249
  );
250
+ if (!showDotTooltip) return node;
251
+ return /* @__PURE__ */ jsx(
252
+ Tooltip,
253
+ {
254
+ placement: "right",
255
+ content: (
256
+ // aria-hidden, and deliberately NOT linked with aria-describedby:
257
+ // the same words are already in the item's accessible name via
258
+ // `dotLabel`, so exposing the bubble would read them twice.
259
+ /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", "data-react-fancy-sidebar-tooltip": "", children: [
260
+ collapsed && /* @__PURE__ */ jsx("span", { className: "block font-medium", "data-react-fancy-sidebar-tooltip-label": "", children }),
261
+ dotLabel
262
+ ] })
263
+ ),
264
+ children: node
265
+ }
266
+ );
237
267
  }
238
268
  SidebarItem.displayName = "SidebarItem";
239
269
  function SidebarGroup({ children, label, className }) {
@@ -403,5 +433,5 @@ var Sidebar = Object.assign(SidebarRoot, {
403
433
  });
404
434
 
405
435
  export { Sidebar, useSidebar };
406
- //# sourceMappingURL=chunk-MTDOFZIB.js.map
407
- //# sourceMappingURL=chunk-MTDOFZIB.js.map
436
+ //# sourceMappingURL=chunk-JY2RC6I4.js.map
437
+ //# sourceMappingURL=chunk-JY2RC6I4.js.map