@dust-tt/sparkle 0.5.11 → 0.5.13

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 (92) hide show
  1. package/dist/cjs/index.js +11 -14
  2. package/dist/cjs/index.js.map +4 -4
  3. package/dist/esm/components/AnimatedText.d.ts +1 -1
  4. package/dist/esm/components/AnimatedText.d.ts.map +1 -1
  5. package/dist/esm/components/AnimatedText.js +3 -0
  6. package/dist/esm/components/AnimatedText.js.map +1 -1
  7. package/dist/esm/components/Avatar.d.ts +2 -3
  8. package/dist/esm/components/Avatar.d.ts.map +1 -1
  9. package/dist/esm/components/Avatar.js +11 -3
  10. package/dist/esm/components/Avatar.js.map +1 -1
  11. package/dist/esm/components/Card.d.ts +1 -1
  12. package/dist/esm/components/Card.d.ts.map +1 -1
  13. package/dist/esm/components/Card.js +2 -1
  14. package/dist/esm/components/Card.js.map +1 -1
  15. package/dist/esm/components/Chip.d.ts +1 -1
  16. package/dist/esm/components/Chip.d.ts.map +1 -1
  17. package/dist/esm/components/Chip.js +8 -3
  18. package/dist/esm/components/Chip.js.map +1 -1
  19. package/dist/esm/components/Citation.js +1 -1
  20. package/dist/esm/components/Collapsible.d.ts.map +1 -1
  21. package/dist/esm/components/Collapsible.js +3 -4
  22. package/dist/esm/components/Collapsible.js.map +1 -1
  23. package/dist/esm/components/DataTable.d.ts.map +1 -1
  24. package/dist/esm/components/DataTable.js +2 -2
  25. package/dist/esm/components/DataTable.js.map +1 -1
  26. package/dist/esm/components/NavigationList.d.ts +2 -8
  27. package/dist/esm/components/NavigationList.d.ts.map +1 -1
  28. package/dist/esm/components/NavigationList.js +33 -31
  29. package/dist/esm/components/NavigationList.js.map +1 -1
  30. package/dist/esm/icons/app/Inbox.d.ts +5 -0
  31. package/dist/esm/icons/app/Inbox.d.ts.map +1 -0
  32. package/dist/esm/icons/app/Inbox.js +7 -0
  33. package/dist/esm/icons/app/Inbox.js.map +1 -0
  34. package/dist/esm/icons/app/SpaceClosed.d.ts +5 -0
  35. package/dist/esm/icons/app/SpaceClosed.d.ts.map +1 -0
  36. package/dist/esm/icons/app/SpaceClosed.js +5 -0
  37. package/dist/esm/icons/app/SpaceClosed.js.map +1 -0
  38. package/dist/esm/icons/app/SpaceOpen.d.ts +5 -0
  39. package/dist/esm/icons/app/SpaceOpen.d.ts.map +1 -0
  40. package/dist/esm/icons/app/SpaceOpen.js +5 -0
  41. package/dist/esm/icons/app/SpaceOpen.js.map +1 -0
  42. package/dist/esm/icons/app/Spaces.d.ts +5 -0
  43. package/dist/esm/icons/app/Spaces.d.ts.map +1 -0
  44. package/dist/esm/icons/app/Spaces.js +5 -0
  45. package/dist/esm/icons/app/Spaces.js.map +1 -0
  46. package/dist/esm/icons/app/index.d.ts +4 -0
  47. package/dist/esm/icons/app/index.d.ts.map +1 -1
  48. package/dist/esm/icons/app/index.js +4 -0
  49. package/dist/esm/icons/app/index.js.map +1 -1
  50. package/dist/esm/icons/src/app/inbox.svg +5 -0
  51. package/dist/esm/icons/src/app/space-closed.svg +3 -0
  52. package/dist/esm/icons/src/app/space-open.svg +3 -0
  53. package/dist/esm/icons/src/app/spaces.svg +3 -0
  54. package/dist/esm/lottie/collapseBar.d.ts +21 -21
  55. package/dist/esm/lottie/dragArea.d.ts +37 -37
  56. package/dist/esm/lottie/spinnerColor.d.ts +64 -64
  57. package/dist/esm/lottie/spinnerDark.d.ts +64 -64
  58. package/dist/esm/lottie/spinnerDarkLG.d.ts +134 -134
  59. package/dist/esm/lottie/spinnerLightLG.d.ts +134 -134
  60. package/dist/esm/lottie/spinnerLightXS.d.ts +38 -38
  61. package/dist/esm/stories/Avatar.stories.d.ts +1 -1
  62. package/dist/esm/stories/Avatar.stories.d.ts.map +1 -1
  63. package/dist/esm/stories/Avatar.stories.js +10 -4
  64. package/dist/esm/stories/Avatar.stories.js.map +1 -1
  65. package/dist/esm/stories/Card.stories.d.ts +1 -1
  66. package/dist/esm/stories/Chip.stories.d.ts +1 -1
  67. package/dist/esm/stories/NavigationList.stories.d.ts.map +1 -1
  68. package/dist/esm/stories/NavigationList.stories.js +61 -31
  69. package/dist/esm/stories/NavigationList.stories.js.map +1 -1
  70. package/dist/sparkle.css +1578 -1601
  71. package/package.json +8 -8
  72. package/src/components/AnimatedText.tsx +6 -0
  73. package/src/components/Avatar.tsx +10 -9
  74. package/src/components/Card.tsx +2 -1
  75. package/src/components/Chip.tsx +45 -11
  76. package/src/components/Citation.tsx +1 -1
  77. package/src/components/Collapsible.tsx +17 -13
  78. package/src/components/DataTable.tsx +1 -2
  79. package/src/components/NavigationList.tsx +83 -128
  80. package/src/icons/app/Inbox.tsx +17 -0
  81. package/src/icons/app/SpaceClosed.tsx +18 -0
  82. package/src/icons/app/SpaceOpen.tsx +20 -0
  83. package/src/icons/app/Spaces.tsx +20 -0
  84. package/src/icons/app/index.ts +4 -0
  85. package/src/icons/src/app/inbox.svg +5 -0
  86. package/src/icons/src/app/space-closed.svg +3 -0
  87. package/src/icons/src/app/space-open.svg +3 -0
  88. package/src/icons/src/app/spaces.svg +3 -0
  89. package/src/stories/Avatar.stories.tsx +6 -4
  90. package/src/stories/NavigationList.stories.tsx +111 -62
  91. package/dist/esm/icons/src/app/brain copie.svg +0 -3
  92. package/src/icons/src/app/brain copie.svg +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dust-tt/sparkle",
3
- "version": "0.5.11",
3
+ "version": "0.5.13",
4
4
  "scripts": {
5
5
  "build": "rm -rf dist && npm run tailwind && npm run build:esm && npm run build:cjs",
6
6
  "tailwind": "tailwindcss -i ./src/styles/tailwind.css -o dist/sparkle.css",
@@ -48,6 +48,7 @@
48
48
  "@babel/preset-react": "^7.22.5",
49
49
  "@babel/preset-typescript": "^7.22.5",
50
50
  "@chromatic-com/storybook": "^3.2.5",
51
+ "@radix-ui/react-focus-scope": "^1.0.3",
51
52
  "@storybook/addon-essentials": "^8.6.4",
52
53
  "@storybook/addon-interactions": "^8.6.4",
53
54
  "@storybook/addon-links": "^8.6.4",
@@ -68,14 +69,12 @@
68
69
  "@types/uuid": "^9.0.6",
69
70
  "@typescript-eslint/eslint-plugin": "^8.48.0",
70
71
  "@typescript-eslint/parser": "^8.48.0",
71
- "@typescript/native-preview": "^7.0.0-dev.20251201.1",
72
- "@tanstack/react-virtual": "^3.5.0",
73
- "@radix-ui/react-focus-scope": "^1.0.3",
74
- "autoprefixer": "^10.4.14",
72
+ "@typescript/native-preview": "^7.0.0-dev.20260105.1",
73
+ "autoprefixer": "^10.4.23",
75
74
  "babel-loader": "^9.1.3",
76
75
  "babel-preset-react-app": "^10.0.1",
77
76
  "copyfiles": "^2.4.1",
78
- "esbuild": "^0.25.0",
77
+ "esbuild": "^0.25.12",
79
78
  "esbuild-plugin-postcss2": "^0.1.2",
80
79
  "eslint": "^9.18.0",
81
80
  "eslint-config-prettier": "^9.1.0",
@@ -89,10 +88,10 @@
89
88
  "react-dom": "^18.3.1",
90
89
  "sass-loader": "^13.3.2",
91
90
  "storybook": "^8.6.4",
92
- "tailwindcss": "^3.2.4",
91
+ "tailwindcss": "^3.4.19",
93
92
  "tailwindcss-animate": "^1.0.7",
94
93
  "tsc-alias": "^1.8.10",
95
- "typescript": "^5.4.5",
94
+ "typescript": "^5.9.3",
96
95
  "typescript-eslint": "^8.48.0",
97
96
  "typescript-transform-paths": "^3.4.7",
98
97
  "uuid": "^9.0.1"
@@ -130,6 +129,7 @@
130
129
  "@radix-ui/react-tabs": "^1.1.1",
131
130
  "@radix-ui/react-tooltip": "^1.1.3",
132
131
  "@tanstack/react-table": "^8.13.0",
132
+ "@tanstack/react-virtual": "^3.5.0",
133
133
  "class-variance-authority": "^0.7.1",
134
134
  "clsx": "^2.1.1",
135
135
  "emoji-mart": "^5.5.2",
@@ -14,6 +14,7 @@ const ANIMATED_TEXT_VARIANTS = [
14
14
  "blue",
15
15
  "rose",
16
16
  "golden",
17
+ "white",
17
18
  ] as const;
18
19
 
19
20
  type AnimatedTextVariantType = (typeof ANIMATED_TEXT_VARIANTS)[number];
@@ -59,6 +60,10 @@ const animatedVariants: Record<AnimatedTextVariantType, string> = {
59
60
  "s-from-golden-800 s-via-golden-950 s-via-50% s-to-golden-800",
60
61
  "dark:s-from-golden-800-night dark:s-via-golden-950-night dark:s-via-50% dark:s-to-golden-800-night"
61
62
  ),
63
+ white: cn(
64
+ "s-from-primary-800 s-via-primary-950 s-via-50% s-to-primary-800",
65
+ "dark:s-from-primary-800-night dark:s-via-primary-950-night dark:s-via-50% dark:s-to-primary-800-night"
66
+ ),
62
67
  };
63
68
 
64
69
  const animVariants = cva(
@@ -84,6 +89,7 @@ const animatedTextVariants: Record<AnimatedTextVariantType, string> = {
84
89
  blue: "s-text-sky-800 dark:s-text-sky-800-night",
85
90
  rose: "s-text-rose-800 dark:s-text-rose-800-night",
86
91
  golden: "s-text-golden-800 dark:s-text-rose-golden-night",
92
+ white: "s-text-primary-800 dark:s-text-primary-800-night",
87
93
  };
88
94
 
89
95
  const textVariants = cva("s-absolute s-inset-0", {
@@ -7,6 +7,7 @@ import { getEmojiAndBackgroundFromUrl } from "@sparkle/lib/avatar/utils";
7
7
  import { cn } from "@sparkle/lib/utils";
8
8
 
9
9
  export const AVATAR_SIZES = [
10
+ "xxs",
10
11
  "xs",
11
12
  "sm",
12
13
  "md",
@@ -25,6 +26,7 @@ const avatarVariants = cva(
25
26
  {
26
27
  variants: {
27
28
  size: {
29
+ xxs: "s-h-5 s-w-5",
28
30
  xs: "s-h-6 s-w-6",
29
31
  sm: "s-h-8 s-w-8",
30
32
  md: "s-h-10 s-w-10",
@@ -45,6 +47,11 @@ const avatarVariants = cva(
45
47
  },
46
48
  },
47
49
  compoundVariants: [
50
+ {
51
+ rounded: false,
52
+ size: "xxs",
53
+ className: "s-rounded",
54
+ },
48
55
  {
49
56
  rounded: false,
50
57
  size: "xs",
@@ -92,6 +99,7 @@ const avatarVariants = cva(
92
99
  const textVariants = cva("s-select-none s-font-semibold", {
93
100
  variants: {
94
101
  size: {
102
+ xxs: "s-text-[10px]",
95
103
  xs: "s-text-xs",
96
104
  sm: "s-text-sm",
97
105
  md: "s-text-base",
@@ -254,7 +262,6 @@ interface AvatarStackProps {
254
262
  avatars: AvatarProps[];
255
263
  nbVisibleItems?: number;
256
264
  size?: AvatarStackSizeType;
257
- isRounded?: boolean;
258
265
  hasMagnifier?: boolean;
259
266
  tooltipTriggerAsChild?: boolean;
260
267
  orientation?: "horizontal" | "vertical";
@@ -270,7 +277,6 @@ Avatar.Stack = function ({
270
277
  avatars,
271
278
  nbVisibleItems,
272
279
  size = "sm",
273
- isRounded = false,
274
280
  hasMagnifier = true,
275
281
  tooltipTriggerAsChild = false,
276
282
  orientation = "horizontal",
@@ -376,14 +382,10 @@ Avatar.Stack = function ({
376
382
  })`,
377
383
  }}
378
384
  >
379
- <Avatar
380
- {...avatarProps}
381
- size={size}
382
- isRounded={isRounded}
383
- />
385
+ <Avatar {...avatarProps} size={size} />
384
386
  </div>
385
387
  ) : (
386
- <Avatar {...avatarProps} size={size} isRounded={isRounded} />
388
+ <Avatar {...avatarProps} size={size} />
387
389
  )}
388
390
  </div>
389
391
  ))}
@@ -407,7 +409,6 @@ Avatar.Stack = function ({
407
409
  "+" +
408
410
  String(Number(remainingCount) < 10 ? remainingCount : "")
409
411
  }
410
- isRounded={isRounded}
411
412
  clickable
412
413
  />
413
414
  </div>
@@ -14,7 +14,7 @@ import { cn } from "@sparkle/lib/utils";
14
14
  export const CARD_VARIANTS = ["primary", "secondary", "tertiary"] as const;
15
15
  export type CardVariantType = (typeof CARD_VARIANTS)[number];
16
16
 
17
- export const CARD_SIZES = ["sm", "md", "lg"] as const;
17
+ export const CARD_SIZES = ["xs", "sm", "md", "lg"] as const;
18
18
  export type CardSizeType = (typeof CARD_SIZES)[number];
19
19
 
20
20
  const interactiveClasses = cn(
@@ -56,6 +56,7 @@ const cardVariants = cva(
56
56
  ),
57
57
  },
58
58
  size: {
59
+ xs: "s-px-2 s-py-1.5 s-rounded-lg",
59
60
  sm: "s-p-3 s-rounded-xl",
60
61
  md: "s-p-4 s-rounded-2xl",
61
62
  lg: "s-p-5 s-rounded-3xl",
@@ -25,6 +25,7 @@ export const CHIP_COLORS = [
25
25
  "blue",
26
26
  "rose",
27
27
  "golden",
28
+ "white",
28
29
  ] as const;
29
30
 
30
31
  type ChipColorType = (typeof CHIP_COLORS)[number];
@@ -91,6 +92,12 @@ const chipVariants = cva("s-inline-flex s-box-border s-items-center", {
91
92
  "dark:s-bg-golden-100-night dark:s-border-golden-200-night",
92
93
  "dark:s-text-golden-900-night"
93
94
  ),
95
+ white: cn(
96
+ "s-border s-bg-white s-border-border",
97
+ "s-text-primary-900",
98
+ "dark:s-bg-background-night dark:s-border-border-night",
99
+ "dark:s-text-primary-900-night"
100
+ ),
94
101
  },
95
102
  },
96
103
  defaultVariants: {
@@ -136,8 +143,40 @@ const closeIconVariants: Record<ChipColorType, string> = {
136
143
  "s-text-golden-900 hover:s-text-golden-700 active:s-text-golden-950",
137
144
  "dark:s-text-golden-900-night dark:hover:s-text-golden-700-night dark:active:s-text-golden-950-night"
138
145
  ),
146
+ white: cn(
147
+ "s-text-primary-700 hover:s-text-primary-500 active:s-text-primary-950",
148
+ "dark:s-text-primary-700-night dark:hover:s-text-primary-500-night dark:active:s-text-primary-950-night"
149
+ ),
139
150
  };
140
151
 
152
+ interface ChipInternalButtonProps {
153
+ icon: ComponentType;
154
+ onClick?: React.MouseEventHandler<HTMLButtonElement>;
155
+ className?: string;
156
+ size?: "xs" | "sm";
157
+ "aria-label"?: string;
158
+ }
159
+
160
+ const ChipButton = React.forwardRef<HTMLButtonElement, ChipInternalButtonProps>(
161
+ ({ icon, onClick, className, size = "xs", "aria-label": ariaLabel }, ref) => (
162
+ <button
163
+ ref={ref}
164
+ type="button"
165
+ onClick={onClick}
166
+ aria-label={ariaLabel}
167
+ className={cn(
168
+ "s-rounded-md s-p-0.5",
169
+ "s-transition-colors s-duration-200",
170
+ "focus-visible:s-outline-none focus-visible:s-ring-2 focus-visible:s-ring-ring",
171
+ className
172
+ )}
173
+ >
174
+ <Icon visual={icon} size={size} />
175
+ </button>
176
+ )
177
+ );
178
+ ChipButton.displayName = "ChipButton";
179
+
141
180
  type ChipBaseProps = {
142
181
  size?: ChipSizeType;
143
182
  color?: ChipColorType;
@@ -225,21 +264,16 @@ const Chip = React.forwardRef<HTMLDivElement, ChipProps>(
225
264
  </span>
226
265
  )}
227
266
  {onRemove && (
228
- <button
267
+ <ChipButton
268
+ icon={XMarkIcon}
269
+ size={size === "mini" ? "xs" : "sm"}
270
+ className={cn("-s-mr-1", closeIconVariants[color || "primary"])}
271
+ aria-label="Remove"
229
272
  onClick={(e) => {
230
273
  e.stopPropagation();
231
274
  onRemove();
232
275
  }}
233
- >
234
- <Icon
235
- visual={XMarkIcon}
236
- size={size === "mini" ? "xs" : (size as IconProps["size"])}
237
- className={cn(
238
- "s-transition-color -s-mr-1 s-duration-200",
239
- closeIconVariants[color || "primary"]
240
- )}
241
- />
242
- </button>
276
+ />
243
277
  )}
244
278
  </div>
245
279
  );
@@ -53,7 +53,7 @@ const Citation = React.forwardRef<HTMLDivElement, CitationProps>(
53
53
  variant={variant}
54
54
  size="sm"
55
55
  className={cn(
56
- "s-min-w-24 s-relative s-flex s-flex-none s-flex-col s-overflow-hidden",
56
+ "s-relative s-flex s-min-w-24 s-flex-none s-flex-col s-overflow-hidden",
57
57
  // Use min() to maintain aspect ratio in grid mode (8% of width) while capping
58
58
  // padding at 3 (0.75rem) for list mode to prevent excessive top padding on wide items.
59
59
  "s-pt-[min(8%,theme(spacing.3))]",
@@ -97,21 +97,25 @@ const CollapsibleTrigger = React.forwardRef<
97
97
  )}
98
98
  {...props}
99
99
  >
100
- <span
101
- className={cn(
102
- "s-transition-transform s-duration-200",
103
- chevronVariants({ variant, disabled })
104
- )}
105
- >
106
- <Icon
107
- visual={isOpen ? ChevronDownIcon : ChevronRightIcon}
108
- size="sm"
109
- />
110
- </span>
111
100
  {children ? (
112
101
  children
113
102
  ) : (
114
- <span className={labelVariants({ variant, disabled })}>{label}</span>
103
+ <>
104
+ <span
105
+ className={cn(
106
+ "s-transition-transform s-duration-200",
107
+ chevronVariants({ variant, disabled })
108
+ )}
109
+ >
110
+ <Icon
111
+ visual={isOpen ? ChevronDownIcon : ChevronRightIcon}
112
+ size="sm"
113
+ />
114
+ </span>
115
+ <span className={labelVariants({ variant, disabled })}>
116
+ {label}
117
+ </span>
118
+ </>
115
119
  )}
116
120
  </CollapsiblePrimitive.Trigger>
117
121
  );
@@ -148,7 +152,7 @@ const CollapsibleContent = React.forwardRef<
148
152
  )}
149
153
  {...props}
150
154
  >
151
- <div className="s-py-2">{children}</div>
155
+ {children}
152
156
  </CollapsiblePrimitive.Content>
153
157
  ));
154
158
  CollapsibleContent.displayName = "CollapsibleContent";
@@ -900,7 +900,7 @@ const renderSubmenuItem = (
900
900
  <DropdownMenuPortal>
901
901
  <DropdownMenuSubContent>
902
902
  <ScrollArea
903
- className="s-min-w-24 s-flex s-max-h-72 s-flex-col"
903
+ className="s-flex s-max-h-72 s-min-w-24 s-flex-col"
904
904
  hideScrollBar
905
905
  >
906
906
  {item.items.map((subItem) => (
@@ -1096,7 +1096,6 @@ DataTable.CellContent = function CellContent({
1096
1096
  avatars={avatarStack.items}
1097
1097
  nbVisibleItems={avatarStack.nbVisibleItems}
1098
1098
  size="xs"
1099
- isRounded={roundedAvatar ?? false}
1100
1099
  />
1101
1100
  )}
1102
1101
  {icon && (
@@ -1,4 +1,3 @@
1
- import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
2
1
  import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
3
2
  import { cva, type VariantProps } from "class-variance-authority";
4
3
  import * as React from "react";
@@ -14,8 +13,9 @@ import { Button } from "@sparkle/components/Button";
14
13
  import {
15
14
  Collapsible,
16
15
  CollapsibleContent,
16
+ CollapsibleTrigger,
17
17
  } from "@sparkle/components/Collapsible";
18
- import { ArrowDownSIcon, ArrowRightSIcon, MoreIcon } from "@sparkle/icons/app";
18
+ import { MoreIcon } from "@sparkle/icons/app";
19
19
  import { cn } from "@sparkle/lib/utils";
20
20
 
21
21
  const NavigationListItemStyles = cva(
@@ -75,6 +75,7 @@ interface NavigationListItemProps
75
75
  selected?: boolean;
76
76
  label?: string;
77
77
  icon?: React.ComponentType;
78
+ avatar?: React.ReactNode;
78
79
  moreMenu?: React.ReactNode;
79
80
  status?: "idle" | "unread" | "blocked";
80
81
  }
@@ -89,6 +90,7 @@ const NavigationListItem = React.forwardRef<
89
90
  selected,
90
91
  label,
91
92
  icon,
93
+ avatar,
92
94
  href,
93
95
  target,
94
96
  rel,
@@ -162,8 +164,9 @@ const NavigationListItem = React.forwardRef<
162
164
  />
163
165
  )}
164
166
  {icon && <Icon visual={icon} size="sm" />}
167
+ {avatar}
165
168
  {label && (
166
- <span className="s-grow s-overflow-hidden s-text-ellipsis s-whitespace-nowrap group-hover/menu-item:s-pr-8 group-data-[selected=true]/menu-item:s-pr-8">
169
+ <span className="s-grow s-overflow-hidden s-text-ellipsis s-whitespace-nowrap group-hover/menu-item:s-pr-7 group-data-[selected=true]/menu-item:s-pr-7">
167
170
  {label}
168
171
  </span>
169
172
  )}
@@ -189,13 +192,13 @@ const NavigationListItemAction = React.forwardRef<
189
192
  ref={ref}
190
193
  data-sidebar="menu-action"
191
194
  className={cn(
192
- "s-absolute s-right-1.5 s-top-1 s-opacity-0 s-transition-opacity",
195
+ "s-absolute s-right-2 s-top-1.5 s-opacity-0 s-transition-opacity",
193
196
  "s-opacity-0 group-focus-within/menu-item:s-opacity-100 group-hover/menu-item:s-opacity-100 group-data-[selected=true]/menu-item:s-opacity-100",
194
197
  className
195
198
  )}
196
199
  {...props}
197
200
  >
198
- <Button size="mini" icon={MoreIcon} variant="ghost" />
201
+ <Button size="xmini" icon={MoreIcon} variant="ghost" />
199
202
  </div>
200
203
  );
201
204
  });
@@ -224,92 +227,34 @@ const labelStyles = cva(
224
227
  "s-flex s-items-center s-justify-between s-gap-2 s-pt-4 s-pb-2 s-pr-2 s-heading-xs s-whitespace-nowrap s-overflow-hidden s-text-ellipsis"
225
228
  );
226
229
 
227
- interface NavigationListLabelButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
228
- icon?: React.ComponentType;
229
- children?: React.ReactNode;
230
- }
231
-
232
- const NavigationListLabelButton = React.forwardRef<
233
- HTMLButtonElement,
234
- NavigationListLabelButtonProps
235
- >(({ className, icon, children, disabled, ...props }, ref) => {
236
- return (
237
- <button
238
- ref={ref}
239
- type="button"
240
- disabled={disabled}
241
- className={cn(
242
- "s-inline-flex s-flex-shrink-0 s-items-center s-justify-center",
243
- "s-rounded-md s-transition-colors s-duration-200",
244
- "s-text-muted-foreground dark:s-text-muted-foreground-night",
245
- "hover:s-text-foreground dark:hover:s-text-foreground-night",
246
- "hover:s-bg-primary-150 dark:hover:s-bg-primary-150-night",
247
- "active:s-bg-primary-200 dark:active:s-bg-primary-200-night",
248
- "focus-visible:s-outline-none focus-visible:s-ring-2 focus-visible:s-ring-ring focus-visible:s-ring-offset-1",
249
- "disabled:s-cursor-not-allowed disabled:s-opacity-50",
250
- "disabled:hover:s-text-muted-foreground dark:disabled:hover:s-text-muted-foreground-night",
251
- "disabled:hover:s-bg-transparent dark:disabled:hover:s-bg-transparent",
252
- className
253
- )}
254
- {...props}
255
- >
256
- {icon ? <Icon visual={icon} size="xs" /> : children}
257
- </button>
258
- );
259
- });
260
-
261
- NavigationListLabelButton.displayName = "NavigationListLabelButton";
262
-
263
230
  interface NavigationListLabelProps
264
231
  extends
265
232
  React.HTMLAttributes<HTMLDivElement>,
266
233
  VariantProps<typeof variantStyles> {
267
234
  label: string;
268
- isCollapsible?: boolean;
269
- isOpen?: boolean;
270
235
  action?: React.ReactNode;
271
236
  }
272
237
 
273
238
  const NavigationListLabel = React.forwardRef<
274
239
  HTMLDivElement,
275
240
  NavigationListLabelProps
276
- >(
277
- (
278
- {
279
- className,
280
- variant,
281
- label,
282
- isSticky,
283
- isCollapsible,
284
- isOpen,
285
- action,
286
- ...props
287
- },
288
- ref
289
- ) => (
290
- <div
291
- ref={ref}
292
- className={cn(
293
- labelStyles(),
294
- variantStyles({ variant, isSticky }),
295
- isCollapsible ? "s-pl-1" : "s-pl-3",
296
- className
297
- )}
298
- {...props}
299
- >
300
- <div className="s-flex s-items-center s-gap-1 s-overflow-hidden s-text-ellipsis">
301
- {isCollapsible && (
302
- <NavigationListLabelButton
303
- icon={isOpen ? ArrowDownSIcon : ArrowRightSIcon}
304
- aria-label={isOpen ? "Collapse section" : "Expand section"}
305
- />
306
- )}
307
- <span className="s-overflow-hidden s-text-ellipsis">{label}</span>
308
- </div>
309
- {action}
241
+ >(({ className, variant, label, isSticky, action, ...props }, ref) => (
242
+ <div
243
+ ref={ref}
244
+ className={cn(
245
+ labelStyles(),
246
+ variantStyles({ variant, isSticky }),
247
+ "s-pl-3",
248
+ className
249
+ )}
250
+ {...props}
251
+ >
252
+ <div className="s-flex s-items-center s-gap-1 s-overflow-hidden s-text-ellipsis">
253
+ <span className="s-overflow-hidden s-text-ellipsis">{label}</span>
310
254
  </div>
311
- )
312
- );
255
+ {action}
256
+ </div>
257
+ ));
313
258
 
314
259
  NavigationListLabel.displayName = "NavigationListLabel";
315
260
 
@@ -322,58 +267,69 @@ interface NavigationListCollapsibleSectionProps extends React.HTMLAttributes<HTM
322
267
  children: React.ReactNode;
323
268
  }
324
269
 
325
- const NavigationListCollapsibleSection = React.forwardRef<
326
- React.ElementRef<typeof Collapsible>,
327
- NavigationListCollapsibleSectionProps
328
- >(
329
- (
330
- {
331
- label,
332
- action,
333
- defaultOpen,
334
- open,
335
- onOpenChange,
336
- children,
337
- className,
338
- ...props
270
+ const collapseableStyles = cva(
271
+ cn(
272
+ "s-py-2 s-mt-2 s-px-2.5",
273
+ "s-heading-xs s-whitespace-nowrap s-overflow-hidden s-text-ellipsis ",
274
+ "s-box-border s-flex s-items-center s-w-full s-gap-1.5",
275
+ "s-cursor-pointer s-select-none",
276
+ "s-outline-none s-rounded-xl s-transition-colors s-duration-300",
277
+ "data-[disabled]:s-pointer-events-none",
278
+ "data-[disabled]:s-text-muted-foreground dark:data-[disabled]:s-text-muted-foreground-night",
279
+ "hover:s-text-foreground dark:hover:s-text-foreground-night",
280
+ "hover:s-bg-primary-100 dark:hover:s-bg-primary-200-night"
281
+ ),
282
+ {
283
+ variants: {
284
+ state: {
285
+ active: "active:s-bg-primary-150 dark:active:s-bg-primary-200-night",
286
+ selected: cn(
287
+ "s-text-foreground dark:s-text-foreground-night",
288
+ "s-bg-primary-100 dark:s-bg-primary-200-night"
289
+ ),
290
+ unselected:
291
+ "s-text-muted-foreground dark:s-text-muted-foreground-night",
292
+ },
293
+ },
294
+ defaultVariants: {
295
+ state: "unselected",
339
296
  },
340
- ref
341
- ) => {
342
- const [internalOpen, setInternalOpen] = React.useState(
343
- defaultOpen ?? false
344
- );
345
- const isControlled = open !== undefined;
346
- const isOpen = isControlled ? open : internalOpen;
347
-
348
- const handleOpenChange = (newOpen: boolean) => {
349
- if (!isControlled) {
350
- setInternalOpen(newOpen);
351
- }
352
- onOpenChange?.(newOpen);
353
- };
354
-
355
- return (
356
- <Collapsible
357
- ref={ref}
358
- open={isOpen}
359
- onOpenChange={handleOpenChange}
360
- className={className}
361
- {...props}
362
- >
363
- <CollapsiblePrimitive.Trigger asChild>
364
- <NavigationListLabel
365
- label={label}
366
- isCollapsible={true}
367
- isOpen={isOpen}
368
- action={action}
369
- />
370
- </CollapsiblePrimitive.Trigger>
371
- <CollapsibleContent>{children}</CollapsibleContent>
372
- </Collapsible>
373
- );
374
297
  }
375
298
  );
376
299
 
300
+ const NavigationListCollapsibleSection = React.forwardRef<
301
+ React.ElementRef<typeof Collapsible>,
302
+ NavigationListCollapsibleSectionProps
303
+ >(({ label, action, children, className, ...props }) => {
304
+ return (
305
+ <Collapsible className={className} {...props}>
306
+ <div className="s-group/menu-item s-relative">
307
+ <CollapsibleTrigger>
308
+ <div className={collapseableStyles({ state: "unselected" })}>
309
+ {label}
310
+ </div>
311
+ </CollapsibleTrigger>
312
+ {action && (
313
+ <div
314
+ className={cn(
315
+ "s-absolute s-bottom-1 s-right-1.5 s-flex s-gap-1 s-opacity-0 s-transition-opacity",
316
+ "hover:s-opacity-100 group-focus-within/menu-item:s-opacity-100 group-hover/menu-item:s-opacity-100"
317
+ )}
318
+ onClick={(e) => {
319
+ e.stopPropagation();
320
+ }}
321
+ >
322
+ {action}
323
+ </div>
324
+ )}
325
+ </div>
326
+ <CollapsibleContent>
327
+ <div className="s-flex s-flex-col s-gap-0.5">{children}</div>
328
+ </CollapsibleContent>
329
+ </Collapsible>
330
+ );
331
+ });
332
+
377
333
  NavigationListCollapsibleSection.displayName =
378
334
  "NavigationListCollapsibleSection";
379
335
 
@@ -383,5 +339,4 @@ export {
383
339
  NavigationListItem,
384
340
  NavigationListItemAction,
385
341
  NavigationListLabel,
386
- NavigationListLabelButton,
387
342
  };
@@ -0,0 +1,17 @@
1
+ import type { SVGProps } from "react";
2
+ import * as React from "react";
3
+ const SvgInbox = (props: SVGProps<SVGSVGElement>) => (
4
+ <svg
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ width="1em"
7
+ height="1em"
8
+ fill="none"
9
+ viewBox="0 0 24 24"
10
+ {...props}
11
+ >
12
+ <path fill="currentColor" d="M22 17.5 12 23 2 17.5V15l10 5.5L22 15v2.5Z" />
13
+ <path fill="currentColor" d="m22 13-10 5.5L2 13v-2.5L12 16l10-5.5V13Z" />
14
+ <path fill="currentColor" d="M22 6.5v2L12 14 2 8.5v-2L12 1l10 5.5Z" />
15
+ </svg>
16
+ );
17
+ export default SvgInbox;
@@ -0,0 +1,18 @@
1
+ import type { SVGProps } from "react";
2
+ import * as React from "react";
3
+ const SvgSpaceClosed = (props: SVGProps<SVGSVGElement>) => (
4
+ <svg
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ width="1em"
7
+ height="1em"
8
+ fill="none"
9
+ viewBox="0 0 24 24"
10
+ {...props}
11
+ >
12
+ <path
13
+ fill="currentColor"
14
+ d="M22 17.5 12 23 2 17.5v-9L12 14l10-5.5v9Zm0-11L12 12 2 6.5 12 1l10 5.5Z"
15
+ />
16
+ </svg>
17
+ );
18
+ export default SvgSpaceClosed;
@@ -0,0 +1,20 @@
1
+ import type { SVGProps } from "react";
2
+ import * as React from "react";
3
+ const SvgSpaceOpen = (props: SVGProps<SVGSVGElement>) => (
4
+ <svg
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ width="1em"
7
+ height="1em"
8
+ fill="none"
9
+ viewBox="0 0 24 24"
10
+ {...props}
11
+ >
12
+ <path
13
+ fill="currentColor"
14
+ fillRule="evenodd"
15
+ d="M22 6.5v11L12 23 2 17.5v-11L12 1l10 5.5ZM4.073 7.64 12 12l7.926-4.36L12 3.282l-7.927 4.36Z"
16
+ clipRule="evenodd"
17
+ />
18
+ </svg>
19
+ );
20
+ export default SvgSpaceOpen;