@flikk/ui 1.0.0-beta.22 → 1.0.0-beta.23

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 (27) hide show
  1. package/dist/components/ai/PromptInput/PromptInput.js +139 -7
  2. package/dist/components/ai/PromptInput/VoiceRecorder.js +84 -0
  3. package/dist/components/core/NavItem/NavItem.js +16 -6
  4. package/dist/components/core/NavItem/NavItem.theme.js +2 -2
  5. package/dist/components/core/Sidebar/Sidebar.d.ts +1 -0
  6. package/dist/components/core/Sidebar/Sidebar.js +5 -3
  7. package/dist/components/core/Sidebar/Sidebar.types.d.ts +7 -1
  8. package/dist/components/core/Sidebar/SidebarContent.js +1 -1
  9. package/dist/components/core/Sidebar/SidebarFooter.js +1 -1
  10. package/dist/components/core/Sidebar/SidebarHeader.js +5 -2
  11. package/dist/components/core/Sidebar/SidebarLogo.d.ts +3 -0
  12. package/dist/components/core/Sidebar/SidebarLogo.js +17 -0
  13. package/dist/components/core/Sidebar/SidebarNavGroup.js +2 -1
  14. package/dist/components/core/Sidebar/SidebarToggle.js +2 -4
  15. package/dist/components/core/Sidebar/SidebarUserProfile.js +3 -6
  16. package/dist/components/core/Sidebar/index.d.ts +2 -1
  17. package/dist/components/core/Tooltip/Tooltip.d.ts +1 -1
  18. package/dist/components/core/Tooltip/Tooltip.js +2 -2
  19. package/dist/components/core/Tooltip/Tooltip.types.d.ts +5 -1
  20. package/dist/components/core/index.js +1 -0
  21. package/dist/components/forms/FileUpload/FileUpload.js +85 -0
  22. package/dist/components/forms/TimePicker/TimePickerContent.js +86 -1
  23. package/dist/components/forms/index.js +85 -0
  24. package/dist/components/layout/FormLayout/FormLayout.js +87 -1
  25. package/dist/index.js +228 -221
  26. package/dist/styles.css +1 -1
  27. package/package.json +2 -1
@@ -1,14 +1,48 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import React__default, { useState, useRef, useId, useEffect, useCallback } from 'react';
3
3
  import { AnimatePresence, motion } from 'motion/react';
4
- import { cn } from '../../../utils/cn.js';
5
- import { CloudArrowUpIcon, MicrophoneIcon, PaperClipIcon, LinkIcon, DocumentIcon, XMarkIcon, PlusIcon, AdjustmentsHorizontalIcon, ChevronDownIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
6
- import { StopIcon } from '@heroicons/react/24/solid';
7
- import { promptInputTheme } from './PromptInput.theme.js';
8
- import { VoiceRecorder } from './VoiceRecorder.js';
9
- import { dropzoneContainerVariants, dropzoneChildVariants, dropzoneActionIconVariants, textareaSwapVariants, iconSwapVariants } from './PromptInput.animations.js';
4
+ import '../../forms/Input/Input.js';
5
+ import '../../forms/Input/Input.theme.js';
6
+ import '../../forms/Select/Select.js';
7
+ import '../../forms/Select/Select.theme.js';
10
8
  import { Textarea } from '../../forms/Textarea/Textarea.js';
11
9
  import '../../forms/Textarea/Textarea.theme.js';
10
+ import '../../forms/FormLabel/FormLabel.js';
11
+ import '../../forms/Radio/Radio.js';
12
+ import '../../forms/Checkbox/Checkbox.js';
13
+ import '../../forms/Switch/Switch.js';
14
+ import '../../forms/DatePicker/DatePicker.js';
15
+ import '../../forms/DatePicker/DatePicker.theme.js';
16
+ import '../../forms/DateRangePicker/DateRangePicker.js';
17
+ import '../../forms/DateRangePicker/DateRangePicker.theme.js';
18
+ import '../../forms/FileUpload/FileUpload.js';
19
+ import '../../forms/FileUpload/FileUploadProgress.js';
20
+ import '../../forms/TimePicker/TimePicker.js';
21
+ import { CloudArrowUpIcon, MicrophoneIcon, PaperClipIcon, LinkIcon, DocumentIcon, XMarkIcon, PlusIcon, AdjustmentsHorizontalIcon, ChevronDownIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
22
+ import { cn } from '../../../utils/cn.js';
23
+ import 'react-dom';
24
+ import '../../core/Accordion/Accordion.js';
25
+ import '../../core/AlertDialog/AlertDialog.js';
26
+ import '../../core/AspectRatio/AspectRatio.js';
27
+ import '../../core/Avatar/Avatar.js';
28
+ import '../../core/AvatarGroup/AvatarGroup.js';
29
+ import '../../core/Badge/Badge.js';
30
+ import '../../core/Breadcrumbs/Breadcrumbs.js';
31
+ import '../../core/Breadcrumbs/Breadcrumbs.theme.js';
32
+ import { Button } from '../../core/Button/Button.js';
33
+ import '../../core/ButtonGroup/ButtonGroup.js';
34
+ import '../../core/ButtonGroup/ButtonGroupSeparator.js';
35
+ import '../../core/ButtonGroup/ButtonGroupText.js';
36
+ import '../../core/Calendar/Calendar.js';
37
+ import '../../core/Calendar/CalendarMini/CalendarMini.js';
38
+ import '../../core/Card/Card.js';
39
+ import '../../core/CardStack/CardStack.js';
40
+ import '../../core/Carousel/Carousel.js';
41
+ import '../../core/Carousel/CarouselBody.js';
42
+ import '../../core/CommandPalette/CommandPalette.js';
43
+ import '../../core/Separator/Separator.js';
44
+ import '../../core/Drawer/Drawer.js';
45
+ import '../../core/Drawer/DrawerBody.js';
12
46
  import { Dropdown } from '../../core/Dropdown/Dropdown.js';
13
47
  import '../../core/Dropdown/DropdownTrigger.js';
14
48
  import '../../core/Dropdown/DropdownMenu.js';
@@ -16,7 +50,105 @@ import '../../core/Dropdown/DropdownItem.js';
16
50
  import '../../core/Dropdown/DropdownSection.js';
17
51
  import '../../core/Dropdown/DropdownSeparator.js';
18
52
  import '../../core/Dropdown/Dropdown.theme.js';
19
- import { Button } from '../../core/Button/Button.js';
53
+ import '../../core/Kbd/Kbd.js';
54
+ import '../../core/MenuItem/MenuItem.js';
55
+ import '../../core/Link/Link.js';
56
+ import '../../core/Modal/Modal.js';
57
+ import '../../core/ModalStack/ModalStack.js';
58
+ import '../../core/PageHeading/PageHeading.js';
59
+ import '../../core/Pagination/Pagination.js';
60
+ import '../../core/Popover/Popover.js';
61
+ import '../../core/Popover/PopoverContext.js';
62
+ import '../../core/Popover/PopoverBody.js';
63
+ import '../../core/Progress/Progress.js';
64
+ import '../../core/Rating/Rating.js';
65
+ import '../../core/ScrollArea/ScrollArea.js';
66
+ import '../../core/ScrollArea/smooth/SmoothScrollEngine.js';
67
+ import '../../core/Segmented/Segmented.js';
68
+ import '../../core/Skeleton/Skeleton.js';
69
+ import '../../core/SlidingNumber/SlidingNumber.js';
70
+ import '../../core/Tabs/Tabs.js';
71
+ import '../../core/Tabs/TabsList.js';
72
+ import '../../core/Tabs/TabsTrigger.js';
73
+ import '../../core/Tabs/TabsBody.js';
74
+ import '../../core/Tabs/TabsContext.js';
75
+ import '../../core/Tooltip/Tooltip.js';
76
+ import '../../core/Tooltip/Tooltip.animations.js';
77
+ import '../../core/Tree/Tree.js';
78
+ import '../../core/Tag/Tag.js';
79
+ import '../../core/Alert/Alert.js';
80
+ import '../../core/Toast/Toast.js';
81
+ import '../../core/Toast/ToastProvider.js';
82
+ import { StopIcon } from '@heroicons/react/24/solid';
83
+ import '../../core/Spinner/Spinner.js';
84
+ import '../../core/Message/Message.js';
85
+ import '../../core/Message/TypeWriter.js';
86
+ import '../../core/Message/MessageBody.js';
87
+ import '@heroicons/react/16/solid';
88
+ import '../../core/Empty/Empty.js';
89
+ import '../../core/Masonry/Masonry.js';
90
+ import '../../core/DragDrop/DragDrop.js';
91
+ import '../../core/Sortable/Sortable.js';
92
+ import '../../core/NavItem/NavItem.js';
93
+ import '../../core/Sidebar/Sidebar.js';
94
+ import '../../core/Sidebar/SidebarHeader.js';
95
+ import '../../core/Sidebar/SidebarContent.js';
96
+ import '../../core/Sidebar/SidebarFooter.js';
97
+ import '../../core/Sidebar/SidebarNav.js';
98
+ import '../../core/Sidebar/SidebarNavGroup.js';
99
+ import '../../core/Sidebar/SidebarToggle.js';
100
+ import '../../core/Sidebar/SidebarMobileTrigger.js';
101
+ import '../../core/Sidebar/SidebarUserProfile.js';
102
+ import '../../core/Sidebar/SidebarLogo.js';
103
+ import '../../core/Sidebar/SidebarContext.js';
104
+ import '../../core/OfflineIndicator/OfflineIndicator.js';
105
+ import '../../core/ContextMenu/ContextMenu.js';
106
+ import '../../core/ContextMenu/ContextMenu.theme.js';
107
+ import '../../core/Pill/Pill.js';
108
+ import '../../core/Icon/Icon.js';
109
+ import '../../forms/TimePicker/WheelColumn.js';
110
+ import '../../forms/TimePicker/TimePicker.theme.js';
111
+ import '../../forms/Slider/Slider.js';
112
+ import '../../forms/Slider/Slider.theme.js';
113
+ import '../../forms/Signature/Signature.js';
114
+ import '../../forms/Signature/Signature.theme.js';
115
+ import '../../forms/RichTextEditor/RichTextEditor.js';
116
+ import '../../forms/RichTextEditor/RichTextEditor.theme.js';
117
+ import '../../forms/InputOTP/InputOTP.js';
118
+ import '../../forms/InputOTP/InputOTP.theme.js';
119
+ import '../../forms/InputCreditCard/InputCreditCard.js';
120
+ import '../../forms/InputCreditCard/InputCreditCard.theme.js';
121
+ import '../../forms/InputAddress/InputAddress.js';
122
+ import '../../forms/InputAddress/InputAddress.theme.js';
123
+ import '../../forms/InputDate/InputDate.js';
124
+ import '../../forms/InputCounter/InputCounter.js';
125
+ import '../../forms/InputTag/InputTag.js';
126
+ import '../../forms/InputTag/InputTag.theme.js';
127
+ import '../../forms/Combobox/Combobox.js';
128
+ import '../../forms/Combobox/Combobox.theme.js';
129
+ import '../../forms/ColorPicker/ColorPicker.js';
130
+ import '../../forms/ColorPicker/ColorPickerContext.js';
131
+ import '../../forms/ColorPicker/ColorPickerTrigger.js';
132
+ import '../../forms/ColorPicker/ColorPickerBody.js';
133
+ import '../../forms/ColorPicker/ColorPicker2DCanvas.js';
134
+ import '../../forms/ColorPicker/ColorPickerSwatch.js';
135
+ import '../../forms/ColorPicker/ColorPickerSliders.js';
136
+ import '../../forms/ColorPicker/ColorPickerInput.js';
137
+ import '../../forms/ColorPicker/ColorPickerFormatSelector.js';
138
+ import '../../forms/ColorPicker/ColorPickerEyeDropper.js';
139
+ import '../../forms/ColorPicker/ColorPickerPresets.js';
140
+ import '../../forms/ColorPicker/ColorPickerSavedColors.js';
141
+ import '../../forms/ColorPicker/ColorPickerHeader.js';
142
+ import '../../forms/ColorPicker/ColorPickerGradient.js';
143
+ import '../../forms/ColorPicker/ColorPickerImage.js';
144
+ import '../../forms/SelectableCard/SelectableCard.js';
145
+ import '../../forms/Mention/Mention.js';
146
+ import '../../forms/Mention/Mention.theme.js';
147
+ import '../../forms/CronInput/CronInput.js';
148
+ import '../../forms/CronInput/CronInput.theme.js';
149
+ import { promptInputTheme } from './PromptInput.theme.js';
150
+ import { VoiceRecorder } from './VoiceRecorder.js';
151
+ import { dropzoneContainerVariants, dropzoneChildVariants, dropzoneActionIconVariants, textareaSwapVariants, iconSwapVariants } from './PromptInput.animations.js';
20
152
 
21
153
  /**
22
154
  * Default model options for the model selector
@@ -3,7 +3,91 @@ import { useState, useRef, useCallback, useEffect } from 'react';
3
3
  import { motion } from 'motion/react';
4
4
  import { PlayIcon, PauseIcon, CheckIcon } from '@heroicons/react/24/outline';
5
5
  import { cn } from '../../../utils/cn.js';
6
+ import '../../core/Accordion/Accordion.js';
7
+ import '../../core/AlertDialog/AlertDialog.js';
8
+ import '../../core/AspectRatio/AspectRatio.js';
9
+ import '../../core/Avatar/Avatar.js';
10
+ import '../../core/AvatarGroup/AvatarGroup.js';
11
+ import '../../core/Badge/Badge.js';
12
+ import '../../core/Breadcrumbs/Breadcrumbs.js';
13
+ import '../../core/Breadcrumbs/Breadcrumbs.theme.js';
6
14
  import { Button } from '../../core/Button/Button.js';
15
+ import '../../core/ButtonGroup/ButtonGroup.js';
16
+ import '../../core/ButtonGroup/ButtonGroupSeparator.js';
17
+ import '../../core/ButtonGroup/ButtonGroupText.js';
18
+ import '../../core/Calendar/Calendar.js';
19
+ import '../../core/Calendar/CalendarMini/CalendarMini.js';
20
+ import '../../core/Card/Card.js';
21
+ import '../../core/CardStack/CardStack.js';
22
+ import '../../core/Carousel/Carousel.js';
23
+ import '../../core/Carousel/CarouselBody.js';
24
+ import '../../core/CommandPalette/CommandPalette.js';
25
+ import '../../core/Separator/Separator.js';
26
+ import '../../core/Drawer/Drawer.js';
27
+ import '../../core/Drawer/DrawerBody.js';
28
+ import '../../core/Dropdown/Dropdown.js';
29
+ import '../../core/Dropdown/DropdownTrigger.js';
30
+ import '../../core/Dropdown/DropdownMenu.js';
31
+ import '../../core/Dropdown/DropdownItem.js';
32
+ import '../../core/Dropdown/DropdownSection.js';
33
+ import '../../core/Dropdown/DropdownSeparator.js';
34
+ import '../../core/Dropdown/Dropdown.theme.js';
35
+ import '../../core/Kbd/Kbd.js';
36
+ import '../../core/MenuItem/MenuItem.js';
37
+ import '../../core/Link/Link.js';
38
+ import '../../core/Modal/Modal.js';
39
+ import '../../core/ModalStack/ModalStack.js';
40
+ import '../../core/PageHeading/PageHeading.js';
41
+ import '../../core/Pagination/Pagination.js';
42
+ import '../../core/Popover/Popover.js';
43
+ import '../../core/Popover/PopoverContext.js';
44
+ import '../../core/Popover/PopoverBody.js';
45
+ import '../../core/Progress/Progress.js';
46
+ import '../../core/Rating/Rating.js';
47
+ import '../../core/ScrollArea/ScrollArea.js';
48
+ import '../../core/ScrollArea/smooth/SmoothScrollEngine.js';
49
+ import '../../core/Segmented/Segmented.js';
50
+ import '../../core/Skeleton/Skeleton.js';
51
+ import '../../core/SlidingNumber/SlidingNumber.js';
52
+ import '../../core/Tabs/Tabs.js';
53
+ import '../../core/Tabs/TabsList.js';
54
+ import '../../core/Tabs/TabsTrigger.js';
55
+ import '../../core/Tabs/TabsBody.js';
56
+ import '../../core/Tabs/TabsContext.js';
57
+ import '../../core/Tooltip/Tooltip.js';
58
+ import '../../core/Tooltip/Tooltip.animations.js';
59
+ import '../../core/Tree/Tree.js';
60
+ import '../../core/Tag/Tag.js';
61
+ import '../../core/Alert/Alert.js';
62
+ import '../../core/Toast/Toast.js';
63
+ import '../../core/Toast/ToastProvider.js';
64
+ import '@heroicons/react/24/solid';
65
+ import '../../core/Spinner/Spinner.js';
66
+ import '../../core/Message/Message.js';
67
+ import '../../core/Message/TypeWriter.js';
68
+ import '../../core/Message/MessageBody.js';
69
+ import '@heroicons/react/16/solid';
70
+ import '../../core/Empty/Empty.js';
71
+ import '../../core/Masonry/Masonry.js';
72
+ import '../../core/DragDrop/DragDrop.js';
73
+ import '../../core/Sortable/Sortable.js';
74
+ import '../../core/NavItem/NavItem.js';
75
+ import '../../core/Sidebar/Sidebar.js';
76
+ import '../../core/Sidebar/SidebarHeader.js';
77
+ import '../../core/Sidebar/SidebarContent.js';
78
+ import '../../core/Sidebar/SidebarFooter.js';
79
+ import '../../core/Sidebar/SidebarNav.js';
80
+ import '../../core/Sidebar/SidebarNavGroup.js';
81
+ import '../../core/Sidebar/SidebarToggle.js';
82
+ import '../../core/Sidebar/SidebarMobileTrigger.js';
83
+ import '../../core/Sidebar/SidebarUserProfile.js';
84
+ import '../../core/Sidebar/SidebarLogo.js';
85
+ import '../../core/Sidebar/SidebarContext.js';
86
+ import '../../core/OfflineIndicator/OfflineIndicator.js';
87
+ import '../../core/ContextMenu/ContextMenu.js';
88
+ import '../../core/ContextMenu/ContextMenu.theme.js';
89
+ import '../../core/Pill/Pill.js';
90
+ import '../../core/Icon/Icon.js';
7
91
 
8
92
  /**
9
93
  * Format seconds into MM:SS display
@@ -120,7 +120,6 @@ notification, description, shortcut, href, onClick, active = false, disabled = f
120
120
  const dangerClasses = isDanger ? theme.danger : "";
121
121
  // Active indicator
122
122
  const activeIndicatorClasses = isActive && level === 0 ? theme.activeIndicator : "";
123
- // Build container classes
124
123
  const containerClasses = cn(theme.baseStyle, getStateClasses(), theme.levels[level], isCollapsedView && ((_a = theme.collapsed) === null || _a === void 0 ? void 0 : _a.container), dangerClasses, activeIndicatorClasses, className);
125
124
  // Get icon state classes
126
125
  const getIconStateClasses = () => {
@@ -146,7 +145,16 @@ notification, description, shortcut, href, onClick, active = false, disabled = f
146
145
  ? React__default.cloneElement(startContent, {
147
146
  className: cn(iconClasses, startContent.props.className),
148
147
  })
149
- : startContent, isCollapsedView && notificationElement && (jsx("span", { className: "absolute -top-1 -right-1", children: notificationElement }))] })), !isCollapsedView && (jsxs("div", { className: "flex-1 min-w-0", children: [jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsx("span", { className: cn("truncate", textClasses), children: children }), shortcut && (jsx("kbd", { className: "hidden group-hover:inline-block text-sm text-[var(--color-text-muted)] font-sans border border-[var(--color-border)] rounded px-1.5 py-0.5", children: shortcut }))] }), description && (jsx("div", { className: "text-sm text-[var(--color-text-muted)] mt-0.5 truncate", children: description }))] })), !isCollapsedView && (jsxs("div", { className: "flex items-center gap-1.5 flex-shrink-0", children: [notificationElement, endContent, chevron] })), isCollapsedView && (jsx("span", { className: "sr-only", children: children }))] }));
148
+ : startContent, isCollapsedView && notificationElement && (jsx("span", { className: "absolute -top-1 -right-1", children: notificationElement }))] })), jsxs("div", { className: "min-w-0 overflow-hidden", "aria-hidden": isCollapsedView || undefined, style: {
149
+ flex: "1 1 auto",
150
+ maxWidth: isCollapsedView ? 0 : 9999,
151
+ opacity: isCollapsedView ? 0 : 1,
152
+ transition: "max-width 0.18s cubic-bezier(0.4,0,0.2,1), opacity 0.12s ease-out",
153
+ }, children: [jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsx("span", { className: cn("truncate", textClasses), children: children }), shortcut && (jsx("kbd", { className: "hidden group-hover:inline-block text-sm text-[var(--color-text-muted)] font-sans border border-[var(--color-border)] rounded px-1.5 py-0.5", children: shortcut }))] }), description && (jsx("div", { className: "text-sm text-[var(--color-text-muted)] mt-0.5 truncate", children: description }))] }), jsxs("div", { className: "flex items-center gap-1.5 flex-shrink-0 overflow-hidden", style: {
154
+ maxWidth: isCollapsedView ? 0 : 120,
155
+ opacity: isCollapsedView ? 0 : 1,
156
+ transition: "max-width 0.18s cubic-bezier(0.4,0,0.2,1), opacity 0.12s ease-out",
157
+ }, children: [notificationElement, endContent, chevron] }), isCollapsedView && (jsx("span", { className: "sr-only", children: children }))] }));
150
158
  // Self-contained submenu
151
159
  const submenu = hasSubmenu && items && items.length > 0 && !isCollapsedView ? (jsx(AnimatePresence, { initial: false, children: isExpanded && (jsx(motion.div, { initial: "collapsed", animate: "open", exit: "collapsed", variants: {
152
160
  open: { opacity: 1, height: "auto" },
@@ -159,12 +167,14 @@ notification, description, shortcut, href, onClick, active = false, disabled = f
159
167
  }
160
168
  return node;
161
169
  };
162
- // Show tooltip in collapsed sidebar mode
170
+ // Always render Tooltip when in a sidebar (keeps tree structure stable across
171
+ // collapse/expand so CSS transitions aren't interrupted by DOM remounts).
172
+ // The tooltip is disabled when not in collapsed view.
163
173
  const renderWithTooltip = (node) => {
164
- if (isCollapsedView && showTooltipWhenCollapsed) {
165
- return (jsx(Tooltip, { content: children, placement: "right", children: node }));
174
+ if (!isInSidebar || !showTooltipWhenCollapsed) {
175
+ return node;
166
176
  }
167
- return node;
177
+ return (jsx(Tooltip, { content: children, placement: "right", disabled: !isCollapsedView, triggerClassName: "block w-full", children: node }));
168
178
  };
169
179
  return (jsxs(Fragment, { children: [renderWithTooltip(renderWrapped(content)), submenu] }));
170
180
  });
@@ -1,5 +1,5 @@
1
1
  const navItemTheme = {
2
- baseStyle: "relative flex items-center gap-2 px-2 py-1.5 text-sm font-medium cursor-pointer select-none transition-all duration-150 w-full rounded-[var(--nav-item-radius)] outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] group",
2
+ baseStyle: "relative flex items-center gap-2 px-2 py-1.5 text-sm font-medium cursor-pointer select-none transition-colors duration-150 w-full rounded-[var(--nav-item-radius)] outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] group overflow-hidden",
3
3
  icon: "size-4 text-[var(--color-text-secondary)]",
4
4
  text: "flex-1 min-w-0 truncate",
5
5
  states: {
@@ -19,7 +19,7 @@ const navItemTheme = {
19
19
  2: "pl-10",
20
20
  },
21
21
  collapsed: {
22
- container: "!gap-0 justify-center p-2 aspect-square",
22
+ container: "!gap-0 justify-center !p-2",
23
23
  icon: "size-5",
24
24
  },
25
25
  activeIndicator: "before:absolute before:left-0 before:top-1/2 before:-translate-y-1/2 before:h-5 before:w-[3px] before:rounded-full before:bg-[var(--color-primary)]",
@@ -10,4 +10,5 @@ export declare const Sidebar: React.ForwardRefExoticComponent<SidebarProps & Rea
10
10
  Toggle: React.ForwardRefExoticComponent<import("./Sidebar.types").SidebarToggleProps & React.RefAttributes<HTMLButtonElement>>;
11
11
  MobileTrigger: React.ForwardRefExoticComponent<import("./Sidebar.types").SidebarMobileTriggerProps & React.RefAttributes<HTMLButtonElement>>;
12
12
  UserProfile: React.ForwardRefExoticComponent<import("./Sidebar.types").SidebarUserProfileProps & React.RefAttributes<HTMLDivElement>>;
13
+ Logo: React.ForwardRefExoticComponent<import("./Sidebar.types").SidebarLogoProps & React.RefAttributes<HTMLDivElement>>;
13
14
  };
@@ -13,11 +13,12 @@ import { SidebarSubmenu } from './SidebarSubmenu.js';
13
13
  import { SidebarToggle } from './SidebarToggle.js';
14
14
  import { SidebarMobileTrigger } from './SidebarMobileTrigger.js';
15
15
  import { SidebarUserProfile } from './SidebarUserProfile.js';
16
+ import { SidebarLogo } from './SidebarLogo.js';
16
17
 
17
18
  const SIDEBAR_TRANSITION = {
18
- type: "spring",
19
- stiffness: 300,
20
- damping: 30,
19
+ type: "tween",
20
+ duration: 0.22,
21
+ ease: [0.4, 0, 0.2, 1],
21
22
  };
22
23
  const SidebarDesktop = React__default.forwardRef(({ side = "left", variant = "sidebar", width, children, className, theme: customTheme = {}, ...props }, ref) => {
23
24
  var _a, _b, _c;
@@ -73,6 +74,7 @@ const Sidebar = Object.assign(SidebarRoot, {
73
74
  Toggle: SidebarToggle,
74
75
  MobileTrigger: SidebarMobileTrigger,
75
76
  UserProfile: SidebarUserProfile,
77
+ Logo: SidebarLogo,
76
78
  });
77
79
 
78
80
  export { Sidebar };
@@ -1,4 +1,4 @@
1
- import { ReactNode } from 'react';
1
+ import { ReactNode, HTMLAttributes } from 'react';
2
2
  export type SidebarSide = 'left' | 'right';
3
3
  export type SidebarVariant = 'sidebar' | 'floating' | 'inset';
4
4
  export type SidebarUserStatus = 'online' | 'offline' | 'away' | 'busy';
@@ -158,6 +158,12 @@ export interface SidebarUserProfileProps extends React.HTMLAttributes<HTMLDivEle
158
158
  */
159
159
  dropdownContent?: ReactNode;
160
160
  }
161
+ export interface SidebarLogoProps extends HTMLAttributes<HTMLDivElement> {
162
+ /** Always-visible icon/mark (shown in both expanded and collapsed states) */
163
+ icon: ReactNode;
164
+ /** Text shown only when expanded — animates in/out automatically */
165
+ text?: ReactNode;
166
+ }
161
167
  export interface SidebarTheme {
162
168
  baseStyle: string;
163
169
  variants: {
@@ -8,7 +8,7 @@ const SidebarContent = React__default.forwardRef(({ children, className, ...prop
8
8
  const collapsed = (sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.collapsed) || false;
9
9
  const isMobile = (sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.isMobile) || false;
10
10
  const isCollapsedView = collapsed && !isMobile;
11
- return (jsx("div", { ref: ref, className: cn("flex-1 overflow-y-auto overflow-x-hidden py-2 transition-all duration-200", isCollapsedView ? "px-2" : "px-3", className), ...props, children: children }));
11
+ return (jsx("div", { ref: ref, className: cn("flex-1 overflow-y-auto overflow-x-hidden py-3 transition-all duration-200", isCollapsedView ? "px-2" : "px-2.5", className), ...props, children: children }));
12
12
  });
13
13
  SidebarContent.displayName = "SidebarContent";
14
14
 
@@ -8,7 +8,7 @@ const SidebarFooter = React__default.forwardRef(({ children, className, ...props
8
8
  const collapsed = (sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.collapsed) || false;
9
9
  const isMobile = (sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.isMobile) || false;
10
10
  const isCollapsedView = collapsed && !isMobile;
11
- return (jsx("div", { ref: ref, className: cn("flex-shrink-0 border-t border-[var(--color-border)] transition-all duration-200", isCollapsedView ? "p-2 flex justify-center" : "p-4", className), ...props, children: children }));
11
+ return (jsx("div", { ref: ref, className: cn("flex-shrink-0 border-t border-[var(--color-border)] transition-all duration-200", isCollapsedView ? "p-2 flex justify-center" : "p-3", className), ...props, children: children }));
12
12
  });
13
13
  SidebarFooter.displayName = "SidebarFooter";
14
14
 
@@ -1,4 +1,4 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import React__default from 'react';
3
3
  import { XMarkIcon } from '@heroicons/react/24/outline';
4
4
  import { cn } from '../../../utils/cn.js';
@@ -15,7 +15,10 @@ const SidebarHeader = React__default.forwardRef(({ logo, showToggle = true, cust
15
15
  if (children) {
16
16
  return (jsx("div", { ref: ref, className: cn("flex-shrink-0 border-b border-[var(--color-border)]", className), ...props, children: children }));
17
17
  }
18
- return (jsxs("div", { ref: ref, className: cn("flex items-center justify-between flex-shrink-0 h-16 border-b border-[var(--color-border)] transition-all duration-200", collapsed && !isMobile ? "px-3" : "px-4", className), ...props, children: [jsx("div", { className: cn("flex items-center min-w-0 transition-all duration-200", collapsed && !isMobile ? "flex-shrink-0" : "flex-1"), children: logo }), isMobile && isMobileOpen && (jsx(Button, { variant: "soft", size: "sm", className: "size-8 p-0", onClick: () => sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.setMobileOpen(false), "aria-label": "Close navigation", children: jsx(XMarkIcon, { className: "size-5" }) })), !isMobile && showToggle && (jsx("div", { className: "flex-shrink-0", children: customToggle || jsx(SidebarToggle, {}) }))] }));
18
+ const isCollapsedDesktop = collapsed && !isMobile;
19
+ return (jsx("div", { ref: ref, className: cn("flex items-center flex-shrink-0 h-14 border-b border-[var(--color-border)] overflow-hidden", isCollapsedDesktop ? "justify-center px-2" : "justify-between px-3", className), ...props, children: isCollapsedDesktop ? (
20
+ /* Collapsed: only show the toggle (expand) button centered */
21
+ showToggle && (customToggle || jsx(SidebarToggle, {}))) : (jsxs(Fragment, { children: [jsx("div", { className: "flex items-center min-w-0 flex-1", children: logo }), isMobile && isMobileOpen && (jsx(Button, { variant: "ghost", size: "sm", className: "size-7 p-0 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]", onClick: () => sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.setMobileOpen(false), "aria-label": "Close navigation", children: jsx(XMarkIcon, { className: "size-4" }) })), !isMobile && showToggle && (jsx("div", { className: "flex-shrink-0", children: customToggle || jsx(SidebarToggle, {}) }))] })) }));
19
22
  });
20
23
  SidebarHeader.displayName = "SidebarHeader";
21
24
 
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import { SidebarLogoProps } from "./Sidebar.types";
3
+ export declare const SidebarLogo: React.ForwardRefExoticComponent<SidebarLogoProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,17 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+ import { cn } from '../../../utils/cn.js';
4
+ import { AnimatePresence, motion } from 'motion/react';
5
+ import { useSidebarContext } from './SidebarContext.js';
6
+
7
+ const SidebarLogo = React__default.forwardRef(({ icon, text, className, ...props }, ref) => {
8
+ var _a, _b;
9
+ const context = useSidebarContext();
10
+ const collapsed = (_a = context === null || context === void 0 ? void 0 : context.collapsed) !== null && _a !== void 0 ? _a : false;
11
+ const isMobile = (_b = context === null || context === void 0 ? void 0 : context.isMobile) !== null && _b !== void 0 ? _b : false;
12
+ const isCollapsedView = collapsed && !isMobile;
13
+ return (jsxs("div", { ref: ref, className: cn("flex items-center gap-2 overflow-hidden", className), ...props, children: [jsx("div", { className: "flex-shrink-0", children: icon }), jsx(AnimatePresence, { initial: false, children: !isCollapsedView && text && (jsx(motion.div, { className: "overflow-hidden whitespace-nowrap", initial: { opacity: 0, x: -8 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -8 }, transition: { duration: 0.15, ease: [0.4, 0, 0.2, 1] }, children: typeof text === "string" ? (jsx("span", { className: "text-lg font-bold text-[var(--color-text-primary)]", children: text })) : (text) }, "logo-text")) })] }));
14
+ });
15
+ SidebarLogo.displayName = "SidebarLogo";
16
+
17
+ export { SidebarLogo };
@@ -1,6 +1,7 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import React__default from 'react';
3
3
  import { cn } from '../../../utils/cn.js';
4
+ import { AnimatePresence, motion } from 'motion/react';
4
5
  import { useSidebarContext } from './SidebarContext.js';
5
6
 
6
7
  const SidebarNavGroup = React__default.forwardRef(({ title, showTitleWhenCollapsed = false, children, className, ...props }, ref) => {
@@ -9,7 +10,7 @@ const SidebarNavGroup = React__default.forwardRef(({ title, showTitleWhenCollaps
9
10
  const isMobile = (sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.isMobile) || false;
10
11
  const isCollapsedView = collapsed && !isMobile;
11
12
  const showTitle = title && (!isCollapsedView || showTitleWhenCollapsed);
12
- return (jsxs("div", { ref: ref, className: cn("space-y-1", className), ...props, children: [showTitle && (jsx("div", { className: "px-2 py-2", children: jsx("h3", { className: "text-sm font-semibold text-[var(--color-text-muted)] uppercase tracking-wider", children: title }) })), isCollapsedView && !showTitleWhenCollapsed && (jsx("div", { className: "h-px bg-[var(--color-border)] mx-2 my-2" })), jsx("div", { className: "space-y-1", children: children })] }));
13
+ return (jsxs("div", { ref: ref, className: cn("space-y-1", className), ...props, children: [jsx(AnimatePresence, { initial: false, children: showTitle && (jsx(motion.div, { initial: { opacity: 0, height: 0 }, animate: { opacity: 1, height: "auto" }, exit: { opacity: 0, height: 0 }, transition: { duration: 0.15, ease: "easeInOut" }, className: "overflow-hidden", children: jsx("div", { className: "px-2 py-1", children: jsx("h3", { className: "text-xs font-semibold text-[var(--color-text-muted)] uppercase tracking-wider", children: title }) }) }, "title")) }), jsx(AnimatePresence, { initial: false, children: isCollapsedView && !showTitleWhenCollapsed && (jsx(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, className: "h-px bg-[var(--color-border)] mx-2 my-1" }, "sep")) }), jsx("div", { className: "space-y-1", children: children })] }));
13
14
  });
14
15
  SidebarNavGroup.displayName = "SidebarNavGroup";
15
16
 
@@ -1,6 +1,6 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import React__default from 'react';
3
- import { ChevronRightIcon, ChevronLeftIcon } from '@heroicons/react/24/outline';
3
+ import { ChevronLeftIcon } from '@heroicons/react/24/outline';
4
4
  import { motion } from 'motion/react';
5
5
  import { cn } from '../../../utils/cn.js';
6
6
  import { useSidebarContext } from './SidebarContext.js';
@@ -20,9 +20,7 @@ const SidebarToggle = React__default.forwardRef(({ expandIcon, collapseIcon, cla
20
20
  onClick === null || onClick === void 0 ? void 0 : onClick(e);
21
21
  };
22
22
  const { onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, color: _color, ...buttonProps } = props;
23
- return (jsx(Button, { ref: ref, variant: "soft", size: "sm", className: cn("size-8 p-0", className), onClick: handleClick, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", title: collapsed ? "Expand sidebar" : "Collapse sidebar", ...buttonProps, children: jsx(motion.div, { initial: false, animate: { rotate: collapsed ? 180 : 0 }, transition: { duration: 0.2 }, children: collapsed
24
- ? expandIcon || jsx(ChevronRightIcon, { className: "size-4" })
25
- : collapseIcon || jsx(ChevronLeftIcon, { className: "size-4" }) }) }));
23
+ return (jsx(Button, { ref: ref, variant: "ghost", size: "sm", className: cn("size-7 p-0 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-background-secondary)]", className), onClick: handleClick, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", title: collapsed ? "Expand sidebar" : "Collapse sidebar", ...buttonProps, children: jsx(motion.div, { initial: false, animate: { rotate: collapsed ? 180 : 0 }, transition: { duration: 0.22, ease: [0.4, 0, 0.2, 1] }, children: jsx(ChevronLeftIcon, { className: "size-[15px]" }) }) }));
26
24
  });
27
25
  SidebarToggle.displayName = "SidebarToggle";
28
26
 
@@ -1,6 +1,7 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import React__default from 'react';
3
3
  import { cn } from '../../../utils/cn.js';
4
+ import { AnimatePresence, motion } from 'motion/react';
4
5
  import { useSidebarContext } from './SidebarContext.js';
5
6
  import { Avatar } from '../Avatar/Avatar.js';
6
7
  import { Tooltip } from '../Tooltip/Tooltip.js';
@@ -23,12 +24,8 @@ const SidebarUserProfile = React__default.forwardRef(({ name, email, avatar, sta
23
24
  e.preventDefault();
24
25
  e.currentTarget.click();
25
26
  }
26
- }, ...props, children: [avatarElement, !isCollapsedView && (jsxs("div", { className: "flex-1 min-w-0", children: [jsx("div", { className: "text-sm font-medium text-[var(--color-text-primary)] truncate", children: name }), email && (jsx("div", { className: "text-xs text-[var(--color-text-muted)] truncate", children: email }))] }))] }));
27
- // Tooltip when collapsed
28
- if (isCollapsedView) {
29
- return (jsx(Tooltip, { content: name, placement: "right", children: content }));
30
- }
31
- return content;
27
+ }, ...props, children: [avatarElement, jsx(AnimatePresence, { initial: false, children: !isCollapsedView && (jsxs(motion.div, { className: "flex-1 min-w-0", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.12, ease: "easeOut" }, children: [jsx("div", { className: "text-sm font-medium text-[var(--color-text-primary)] truncate", children: name }), email && (jsx("div", { className: "text-xs text-[var(--color-text-muted)] truncate", children: email }))] }, "profile-text")) })] }));
28
+ return (jsx(Tooltip, { content: name, placement: "right", disabled: !isCollapsedView, triggerClassName: "block", children: content }));
32
29
  });
33
30
  SidebarUserProfile.displayName = "SidebarUserProfile";
34
31
 
@@ -8,5 +8,6 @@ export { SidebarSubmenu } from "./SidebarSubmenu";
8
8
  export { SidebarToggle } from "./SidebarToggle";
9
9
  export { SidebarMobileTrigger } from "./SidebarMobileTrigger";
10
10
  export { SidebarUserProfile } from "./SidebarUserProfile";
11
+ export { SidebarLogo } from "./SidebarLogo";
11
12
  export { useSidebarContext } from "./SidebarContext";
12
- export type { SidebarProps, SidebarHeaderProps, SidebarContentProps, SidebarFooterProps, SidebarNavProps, SidebarNavGroupProps, SidebarToggleProps, SidebarMobileTriggerProps, SidebarUserProfileProps, SidebarUserStatus, SidebarSide, SidebarVariant, SidebarContextValue, SidebarTheme, SidebarThemeOverrides, } from "./Sidebar.types";
13
+ export type { SidebarProps, SidebarHeaderProps, SidebarContentProps, SidebarFooterProps, SidebarNavProps, SidebarNavGroupProps, SidebarToggleProps, SidebarMobileTriggerProps, SidebarUserProfileProps, SidebarUserStatus, SidebarSide, SidebarVariant, SidebarContextValue, SidebarTheme, SidebarThemeOverrides, SidebarLogoProps, } from "./Sidebar.types";
@@ -1,6 +1,6 @@
1
1
  import { TooltipProps } from "./Tooltip.types";
2
2
  declare const Tooltip: {
3
- ({ content, children, placement, delay, disabled, className, maxWidth, minWidth, showOnFocus, wrapText, id, theme: themeOverrides, "aria-label": ariaLabel, role, offset, darkMode, }: TooltipProps): import("react/jsx-runtime").JSX.Element;
3
+ ({ content, children, placement, delay, disabled, className, triggerClassName, maxWidth, minWidth, showOnFocus, wrapText, id, theme: themeOverrides, "aria-label": ariaLabel, role, offset, darkMode, }: TooltipProps): import("react/jsx-runtime").JSX.Element;
4
4
  displayName: string;
5
5
  };
6
6
  export { Tooltip };
@@ -37,7 +37,7 @@ const useDarkMode = () => {
37
37
  }, []);
38
38
  return isDark;
39
39
  };
40
- const Tooltip = ({ content, children, placement = "top", delay = 300, disabled = false, className, maxWidth = "360px", minWidth = "fit-content", showOnFocus = true, wrapText = false, id, theme: themeOverrides, "aria-label": ariaLabel, role = "tooltip", offset = 8, darkMode = false, }) => {
40
+ const Tooltip = ({ content, children, placement = "top", delay = 300, disabled = false, className, triggerClassName, maxWidth = "360px", minWidth = "fit-content", showOnFocus = true, wrapText = false, id, theme: themeOverrides, "aria-label": ariaLabel, role = "tooltip", offset = 8, darkMode = false, }) => {
41
41
  const [isVisible, setIsVisible] = useState(false);
42
42
  const tooltipRef = useRef(null);
43
43
  const triggerRef = useRef(null);
@@ -123,7 +123,7 @@ const Tooltip = ({ content, children, placement = "top", delay = 300, disabled =
123
123
  top: `${position.top}px`,
124
124
  left: `${position.left}px`,
125
125
  }, className: cn(theme.baseStyle, widthClasses, className), "aria-hidden": !isVisible, "aria-label": ariaLabel, "aria-live": role === "tooltip" ? "polite" : undefined, variants: shouldReduceMotion ? {} : getTooltipVariants(placement), initial: shouldReduceMotion ? undefined : "initial", animate: shouldReduceMotion ? undefined : "animate", exit: shouldReduceMotion ? undefined : "exit", children: content })) }));
126
- return (jsxs("div", { className: "relative inline-block", ref: triggerRef, ...triggerHandlers, tabIndex: showOnFocus ? 0 : undefined, "aria-describedby": isVisible && id ? id : undefined, children: [children, isClient &&
126
+ return (jsxs("div", { className: cn("relative inline-block", triggerClassName), ref: triggerRef, ...triggerHandlers, tabIndex: showOnFocus ? 0 : undefined, "aria-describedby": isVisible && id ? id : undefined, children: [children, isClient &&
127
127
  createPortal(jsx("div", { className: darkMode || isDarkMode ? "dark" : undefined, children: tooltipContent }), document.body)] }));
128
128
  };
129
129
  // Set display name for dev tools and Storybook
@@ -38,9 +38,13 @@ export interface TooltipProps {
38
38
  */
39
39
  disabled?: boolean;
40
40
  /**
41
- * Additional classes for the tooltip container
41
+ * Additional classes for the tooltip container (the tooltip bubble)
42
42
  */
43
43
  className?: string;
44
+ /**
45
+ * Additional classes for the trigger wrapper element
46
+ */
47
+ triggerClassName?: string;
44
48
  /**
45
49
  * Max width for the tooltip content
46
50
  * @default "360px"
@@ -100,6 +100,7 @@ export { SidebarSubmenu } from './Sidebar/SidebarSubmenu.js';
100
100
  export { SidebarToggle } from './Sidebar/SidebarToggle.js';
101
101
  export { SidebarMobileTrigger } from './Sidebar/SidebarMobileTrigger.js';
102
102
  export { SidebarUserProfile } from './Sidebar/SidebarUserProfile.js';
103
+ export { SidebarLogo } from './Sidebar/SidebarLogo.js';
103
104
  export { useSidebarContext } from './Sidebar/SidebarContext.js';
104
105
  export { OfflineIndicator } from './OfflineIndicator/OfflineIndicator.js';
105
106
  export { offlineIndicatorTheme } from './OfflineIndicator/OfflineIndicator.theme.js';