xertica-ui 2.2.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +564 -525
- package/README.md +417 -382
- package/bin/cli.ts +1244 -748
- package/bin/generate-tokens.ts +262 -262
- package/bin/language-config.ts +5 -8
- package/components/assets/xertica-orbe-animation.ts +1162 -1162
- package/components/assistant/code-block/CodeBlock.tsx +268 -268
- package/components/assistant/code-block/code-block.stories.tsx +57 -57
- package/components/assistant/code-block/code-block.test.tsx +44 -44
- package/components/assistant/code-block/index.ts +1 -1
- package/components/assistant/formatted-document/FormattedDocument.tsx +147 -147
- package/components/assistant/formatted-document/formatted-document.stories.tsx +51 -51
- package/components/assistant/formatted-document/formatted-document.test.tsx +42 -42
- package/components/assistant/formatted-document/index.ts +1 -1
- package/components/assistant/index.ts +6 -6
- package/components/assistant/markdown-message/MarkdownMessage.tsx +152 -152
- package/components/assistant/markdown-message/index.ts +1 -1
- package/components/assistant/markdown-message/markdown-message.stories.tsx +50 -50
- package/components/assistant/markdown-message/markdown-message.test.tsx +33 -33
- package/components/assistant/modern-chat-input/ModernChatInput.tsx +17 -7
- package/components/assistant/modern-chat-input/index.ts +1 -1
- package/components/assistant/modern-chat-input/modern-chat-input.stories.tsx +131 -131
- package/components/assistant/modern-chat-input/modern-chat-input.test.tsx +79 -79
- package/components/assistant/xertica-assistant/index.ts +3 -3
- package/components/assistant/xertica-assistant/parts/AssistantCollapsedView.tsx +99 -99
- package/components/assistant/xertica-assistant/parts/AssistantConversationList.tsx +104 -106
- package/components/assistant/xertica-assistant/parts/AssistantDocumentEditor.tsx +81 -81
- package/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.tsx +88 -78
- package/components/assistant/xertica-assistant/parts/AssistantHeader.tsx +75 -75
- package/components/assistant/xertica-assistant/parts/AssistantMessageBubble.tsx +564 -560
- package/components/assistant/xertica-assistant/parts/AssistantTabBar.tsx +67 -67
- package/components/assistant/xertica-assistant/parts/AssistantTypingIndicator.tsx +41 -41
- package/components/assistant/xertica-assistant/parts/AssistantWelcomeScreen.tsx +103 -103
- package/components/assistant/xertica-assistant/parts/index.ts +16 -16
- package/components/assistant/xertica-assistant/types.ts +134 -134
- package/components/assistant/xertica-assistant/use-assistant.ts +615 -615
- package/components/assistant/xertica-assistant/xertica-assistant.stories.tsx +407 -407
- package/components/assistant/xertica-assistant/xertica-assistant.test.tsx +65 -65
- package/components/assistant/xertica-assistant/xertica-assistant.tsx +611 -613
- package/components/blocks/card-patterns/ActivityCard.tsx +100 -100
- package/components/blocks/card-patterns/FeatureCard.tsx +109 -109
- package/components/blocks/card-patterns/FeatureCardSkeleton.tsx +1 -6
- package/components/blocks/card-patterns/NotificationCard.tsx +140 -140
- package/components/blocks/card-patterns/ProfileCard.tsx +112 -114
- package/components/blocks/card-patterns/ProjectCard.tsx +123 -123
- package/components/blocks/card-patterns/ProjectCardSkeleton.tsx +1 -6
- package/components/blocks/card-patterns/QuickActionCard.tsx +68 -68
- package/components/blocks/card-patterns/card-patterns.mdx +123 -123
- package/components/blocks/card-patterns/card-patterns.stories.tsx +594 -594
- package/components/blocks/card-patterns/index.ts +29 -29
- package/components/blocks/index.ts +1 -1
- package/components/brand/branding/branding.stories.tsx +57 -57
- package/components/brand/index.ts +6 -6
- package/components/brand/language-selector/index.ts +1 -1
- package/components/brand/language-selector/language-selector.mdx +126 -126
- package/components/brand/language-selector/language-selector.stories.tsx +1 -4
- package/components/brand/theme-toggle/ThemeToggle.tsx +74 -70
- package/components/brand/theme-toggle/index.ts +1 -1
- package/components/brand/theme-toggle/theme-toggle.stories.tsx +34 -34
- package/components/brand/theme-toggle/theme-toggle.test.tsx +34 -34
- package/components/brand/xertica-logo/XerticaLogo.stories.tsx +82 -82
- package/components/brand/xertica-logo/XerticaLogo.tsx +104 -104
- package/components/brand/xertica-logo/index.ts +1 -1
- package/components/brand/xertica-logo/xertica-logo.test.tsx +26 -26
- package/components/brand/xertica-orbe/XerticaOrbe.tsx +1927 -1927
- package/components/brand/xertica-orbe/index.ts +1 -1
- package/components/brand/xertica-orbe/xertica-orbe.stories.tsx +40 -40
- package/components/brand/xertica-orbe/xertica-orbe.test.tsx +19 -19
- package/components/brand/xertica-provider/XerticaProvider.tsx +1 -4
- package/components/brand/xertica-provider/index.ts +1 -1
- package/components/brand/xertica-provider/xertica-provider.test.tsx +74 -74
- package/components/brand/xertica-xlogo/XerticaXLogo.stories.tsx +79 -79
- package/components/brand/xertica-xlogo/XerticaXLogo.tsx +65 -65
- package/components/brand/xertica-xlogo/index.ts +1 -1
- package/components/brand/xertica-xlogo/xertica-xlogo.test.tsx +16 -16
- package/components/examples/ApiKeyMapExample.tsx +71 -71
- package/components/examples/DrawingMapExample.tsx +565 -565
- package/components/examples/FilterableMapExample.tsx +393 -393
- package/components/examples/LocationPickerExample.tsx +348 -348
- package/components/examples/MapExamples.tsx +268 -268
- package/components/examples/MapGmpExample.tsx +169 -169
- package/components/examples/MapShowcase.tsx +471 -471
- package/components/examples/RouteMapExamples.tsx +329 -329
- package/components/examples/SidebarLogoExample.tsx +65 -65
- package/components/examples/SimpleFilterableMap.tsx +219 -219
- package/components/examples/index.ts +45 -45
- package/components/figma/ImageWithFallback.tsx +27 -27
- package/components/hooks/index.ts +13 -13
- package/components/hooks/use-layout-shortcuts.ts +43 -43
- package/components/index.ts +86 -90
- package/components/layout/header/header.stories.tsx +204 -204
- package/components/layout/header/header.test.tsx +75 -75
- package/components/layout/header/header.tsx +349 -349
- package/components/layout/header/index.ts +1 -1
- package/components/layout/index.ts +2 -2
- package/components/layout/sidebar/index.ts +3 -3
- package/components/layout/sidebar/sidebar.stories.tsx +586 -586
- package/components/layout/sidebar/sidebar.test.tsx +76 -76
- package/components/layout/sidebar/sidebar.tsx +1079 -1073
- package/components/layout/sidebar/use-sidebar.ts +104 -104
- package/components/media/FloatingMediaWrapper.tsx +371 -371
- package/components/media/audio-player/AudioPlayer.stories.tsx +124 -124
- package/components/media/audio-player/AudioPlayer.test.tsx +106 -106
- package/components/media/audio-player/AudioPlayer.tsx +767 -765
- package/components/media/audio-player/index.ts +1 -1
- package/components/media/audio-player/use-audio-player.ts +312 -312
- package/components/media/index.ts +3 -3
- package/components/media/video-player/VideoPlayer.stories.tsx +98 -98
- package/components/media/video-player/VideoPlayer.test.tsx +73 -73
- package/components/media/video-player/VideoPlayer.tsx +310 -310
- package/components/media/video-player/index.ts +1 -1
- package/components/pages/forgot-password-page/ForgotPasswordPage.stories.tsx +24 -24
- package/components/pages/forgot-password-page/ForgotPasswordPage.tsx +188 -188
- package/components/pages/forgot-password-page/forgot-password-page.test.tsx +45 -45
- package/components/pages/forgot-password-page/index.ts +1 -1
- package/components/pages/home-content/HomeContent.stories.tsx +43 -43
- package/components/pages/home-content/HomeContent.tsx +120 -120
- package/components/pages/home-content/index.ts +1 -1
- package/components/pages/home-page/HomePage.stories.tsx +39 -39
- package/components/pages/home-page/HomePage.tsx +78 -74
- package/components/pages/home-page/home-page.test.tsx +53 -53
- package/components/pages/home-page/index.ts +1 -1
- package/components/pages/index.ts +8 -8
- package/components/pages/login-page/LoginPage.stories.tsx +39 -39
- package/components/pages/login-page/LoginPage.tsx +218 -216
- package/components/pages/login-page/index.ts +1 -1
- package/components/pages/login-page/login-page.test.tsx +63 -63
- package/components/pages/reset-password-page/ResetPasswordPage.stories.tsx +24 -24
- package/components/pages/reset-password-page/ResetPasswordPage.tsx +243 -239
- package/components/pages/reset-password-page/index.ts +1 -1
- package/components/pages/template-content/TemplateContent.stories.tsx +43 -43
- package/components/pages/template-content/TemplateContent.tsx +1354 -1235
- package/components/pages/template-content/index.ts +1 -1
- package/components/pages/template-page/TemplatePage.stories.tsx +39 -39
- package/components/pages/template-page/TemplatePage.tsx +62 -62
- package/components/pages/template-page/index.ts +1 -1
- package/components/pages/template-page/template-page.test.tsx +52 -52
- package/components/pages/verify-email-page/VerifyEmailPage.stories.tsx +41 -41
- package/components/pages/verify-email-page/VerifyEmailPage.tsx +206 -206
- package/components/pages/verify-email-page/index.ts +1 -1
- package/components/public-api-smoke.test.tsx +52 -52
- package/components/shared/CustomTooltipContent.tsx +48 -48
- package/components/shared/assistant-utils.test.ts +16 -16
- package/components/shared/assistant-utils.ts +225 -225
- package/components/shared/error-boundary.stories.tsx +114 -132
- package/components/shared/error-boundary.tsx +150 -154
- package/components/shared/error-fallbacks.tsx +222 -226
- package/components/shared/layout-constants.ts +8 -8
- package/components/shared/navigation.ts +35 -35
- package/components/shared/use-mobile.test.ts +16 -16
- package/components/shared/use-mobile.ts +36 -36
- package/components/shared/utils.test.ts +14 -14
- package/components/shared/utils.ts +6 -6
- package/components/ui/accordion/accordion.stories.tsx +105 -105
- package/components/ui/accordion/accordion.test.tsx +59 -59
- package/components/ui/accordion/accordion.tsx +77 -77
- package/components/ui/accordion/index.ts +1 -1
- package/components/ui/alert/alert.stories.tsx +86 -86
- package/components/ui/alert/alert.test.tsx +53 -53
- package/components/ui/alert/alert.tsx +93 -93
- package/components/ui/alert/index.ts +1 -1
- package/components/ui/alert-dialog/alert-dialog.stories.tsx +84 -84
- package/components/ui/alert-dialog/alert-dialog.test.tsx +70 -70
- package/components/ui/alert-dialog/alert-dialog.tsx +149 -149
- package/components/ui/alert-dialog/index.ts +1 -1
- package/components/ui/aspect-ratio/aspect-ratio.stories.tsx +46 -46
- package/components/ui/aspect-ratio/aspect-ratio.test.tsx +28 -28
- package/components/ui/aspect-ratio/aspect-ratio.tsx +20 -20
- package/components/ui/aspect-ratio/index.ts +1 -1
- package/components/ui/assistant-chart/AssistantChart.tsx +64 -64
- package/components/ui/assistant-chart/assistant-chart.stories.tsx +44 -44
- package/components/ui/assistant-chart/assistant-chart.test.tsx +46 -46
- package/components/ui/assistant-chart/index.ts +1 -1
- package/components/ui/avatar/avatar.stories.tsx +86 -86
- package/components/ui/avatar/avatar.test.tsx +55 -55
- package/components/ui/avatar/avatar.tsx +71 -71
- package/components/ui/avatar/index.ts +1 -1
- package/components/ui/badge/badge.stories.tsx +72 -72
- package/components/ui/badge/badge.test.tsx +40 -40
- package/components/ui/badge/badge.tsx +58 -58
- package/components/ui/badge/index.ts +1 -1
- package/components/ui/breadcrumb/breadcrumb.stories.tsx +123 -123
- package/components/ui/breadcrumb/breadcrumb.test.tsx +70 -70
- package/components/ui/breadcrumb/breadcrumb.tsx +114 -114
- package/components/ui/breadcrumb/index.ts +1 -1
- package/components/ui/button/button.stories.tsx +183 -183
- package/components/ui/button/button.test.tsx +64 -64
- package/components/ui/button/button.tsx +98 -98
- package/components/ui/button/index.ts +1 -1
- package/components/ui/calendar/calendar.stories.tsx +108 -108
- package/components/ui/calendar/calendar.test.tsx +53 -53
- package/components/ui/calendar/calendar.tsx +230 -230
- package/components/ui/calendar/index.ts +1 -1
- package/components/ui/card/card.stories.tsx +301 -301
- package/components/ui/card/card.test.tsx +55 -55
- package/components/ui/card/card.tsx +83 -83
- package/components/ui/card/index.ts +1 -1
- package/components/ui/carousel/carousel.stories.tsx +80 -80
- package/components/ui/carousel/carousel.test.tsx +75 -75
- package/components/ui/carousel/carousel.tsx +242 -242
- package/components/ui/carousel/index.ts +1 -1
- package/components/ui/chart/chart.stories.tsx +1328 -1328
- package/components/ui/chart/chart.test.tsx +178 -178
- package/components/ui/chart/chart.tsx +2232 -2232
- package/components/ui/chart/index.ts +1 -1
- package/components/ui/checkbox/checkbox.stories.tsx +109 -109
- package/components/ui/checkbox/checkbox.test.tsx +49 -49
- package/components/ui/checkbox/checkbox.tsx +68 -68
- package/components/ui/checkbox/index.ts +1 -1
- package/components/ui/collapsible/collapsible.stories.tsx +45 -45
- package/components/ui/collapsible/collapsible.test.tsx +51 -51
- package/components/ui/collapsible/collapsible.tsx +32 -32
- package/components/ui/collapsible/index.ts +1 -1
- package/components/ui/command/command.stories.tsx +134 -134
- package/components/ui/command/command.test.tsx +48 -48
- package/components/ui/command/command.tsx +163 -163
- package/components/ui/command/index.ts +1 -1
- package/components/ui/context-menu/context-menu.stories.tsx +76 -76
- package/components/ui/context-menu/context-menu.test.tsx +61 -61
- package/components/ui/context-menu/context-menu.tsx +236 -236
- package/components/ui/context-menu/index.ts +1 -1
- package/components/ui/dialog/dialog.stories.tsx +174 -174
- package/components/ui/dialog/dialog.test.tsx +78 -78
- package/components/ui/dialog/dialog.tsx +189 -189
- package/components/ui/dialog/index.ts +1 -1
- package/components/ui/drawer/drawer.stories.tsx +71 -71
- package/components/ui/drawer/drawer.test.tsx +67 -67
- package/components/ui/drawer/drawer.tsx +146 -146
- package/components/ui/drawer/index.ts +1 -1
- package/components/ui/dropdown-menu/dropdown-menu.stories.tsx +156 -156
- package/components/ui/dropdown-menu/dropdown-menu.test.tsx +62 -62
- package/components/ui/dropdown-menu/dropdown-menu.tsx +240 -240
- package/components/ui/dropdown-menu/index.ts +1 -1
- package/components/ui/empty/empty.stories.tsx +85 -85
- package/components/ui/empty/empty.test.tsx +31 -31
- package/components/ui/empty/empty.tsx +88 -88
- package/components/ui/empty/index.ts +1 -1
- package/components/ui/file-upload/file-upload.stories.tsx +144 -144
- package/components/ui/file-upload/file-upload.test.tsx +65 -65
- package/components/ui/file-upload/file-upload.tsx +142 -142
- package/components/ui/file-upload/index.ts +2 -2
- package/components/ui/file-upload/use-file-upload.ts +177 -177
- package/components/ui/form/form.stories.tsx +85 -85
- package/components/ui/form/form.test.tsx +75 -75
- package/components/ui/form/form.tsx +163 -163
- package/components/ui/form/index.ts +1 -1
- package/components/ui/google-maps-loader/google-maps-loader.test.tsx +35 -35
- package/components/ui/google-maps-loader/google-maps-loader.tsx +465 -465
- package/components/ui/google-maps-loader/index.ts +1 -1
- package/components/ui/hover-card/hover-card.stories.tsx +61 -61
- package/components/ui/hover-card/hover-card.test.tsx +48 -48
- package/components/ui/hover-card/hover-card.tsx +50 -50
- package/components/ui/hover-card/index.ts +1 -1
- package/components/ui/index.ts +400 -400
- package/components/ui/input/index.ts +1 -1
- package/components/ui/input/input.stories.tsx +153 -153
- package/components/ui/input/input.test.tsx +47 -47
- package/components/ui/input/input.tsx +57 -57
- package/components/ui/input-otp/index.ts +1 -1
- package/components/ui/input-otp/input-otp.stories.tsx +120 -120
- package/components/ui/input-otp/input-otp.test.tsx +74 -74
- package/components/ui/input-otp/input-otp.tsx +101 -101
- package/components/ui/label/index.ts +1 -1
- package/components/ui/label/label.stories.tsx +74 -74
- package/components/ui/label/label.test.tsx +45 -45
- package/components/ui/label/label.tsx +53 -53
- package/components/ui/map/index.ts +1 -1
- package/components/ui/map/map.stories.tsx +86 -86
- package/components/ui/map/map.test.tsx +82 -82
- package/components/ui/map/map.tsx +506 -506
- package/components/ui/map/mock.test.tsx +13 -13
- package/components/ui/map-config/index.ts +1 -1
- package/components/ui/map-config/map-config.ts +18 -18
- package/components/ui/map-layers/index.ts +1 -1
- package/components/ui/map-layers/map-layers.test.tsx +48 -48
- package/components/ui/map-layers/map-layers.tsx +126 -126
- package/components/ui/map.exports/index.ts +1 -1
- package/components/ui/map.exports/map.exports.ts +31 -31
- package/components/ui/menubar/index.ts +1 -1
- package/components/ui/menubar/menubar.stories.tsx +130 -130
- package/components/ui/menubar/menubar.test.tsx +53 -53
- package/components/ui/menubar/menubar.tsx +265 -265
- package/components/ui/navigation-menu/index.ts +1 -1
- package/components/ui/navigation-menu/navigation-menu.stories.tsx +126 -126
- package/components/ui/navigation-menu/navigation-menu.test.tsx +47 -47
- package/components/ui/navigation-menu/navigation-menu.tsx +165 -165
- package/components/ui/notification-badge/index.ts +1 -1
- package/components/ui/notification-badge/notification-badge.stories.tsx +66 -66
- package/components/ui/notification-badge/notification-badge.test.tsx +61 -61
- package/components/ui/notification-badge/notification-badge.tsx +91 -91
- package/components/ui/page-header/index.ts +1 -1
- package/components/ui/page-header/page-header.stories.tsx +69 -69
- package/components/ui/page-header/page-header.test.tsx +37 -37
- package/components/ui/page-header/page-header.tsx +124 -124
- package/components/ui/pagination/index.ts +3 -3
- package/components/ui/pagination/pagination.stories.tsx +210 -210
- package/components/ui/pagination/pagination.test.tsx +63 -63
- package/components/ui/pagination/pagination.tsx +140 -140
- package/components/ui/pagination/use-pagination.ts +173 -173
- package/components/ui/popover/index.ts +1 -1
- package/components/ui/popover/popover.stories.tsx +73 -73
- package/components/ui/popover/popover.test.tsx +48 -48
- package/components/ui/popover/popover.tsx +54 -54
- package/components/ui/progress/index.ts +1 -1
- package/components/ui/progress/progress.stories.tsx +55 -55
- package/components/ui/progress/progress.test.tsx +23 -23
- package/components/ui/progress/progress.tsx +68 -68
- package/components/ui/radio-group/index.ts +1 -1
- package/components/ui/radio-group/radio-group.stories.tsx +114 -114
- package/components/ui/radio-group/radio-group.test.tsx +78 -78
- package/components/ui/radio-group/radio-group.tsx +93 -93
- package/components/ui/rating/index.ts +1 -1
- package/components/ui/rating/rating.stories.tsx +50 -50
- package/components/ui/rating/rating.test.tsx +48 -48
- package/components/ui/rating/rating.tsx +145 -145
- package/components/ui/resizable/index.ts +1 -1
- package/components/ui/resizable/resizable.stories.tsx +88 -88
- package/components/ui/resizable/resizable.test.tsx +61 -61
- package/components/ui/resizable/resizable.tsx +452 -452
- package/components/ui/rich-text-editor/index.ts +7 -7
- package/components/ui/rich-text-editor/rich-text-editor.stories.tsx +290 -290
- package/components/ui/rich-text-editor/rich-text-editor.test.tsx +86 -86
- package/components/ui/rich-text-editor/rich-text-editor.tsx +634 -634
- package/components/ui/rich-text-editor/use-rich-text-editor.ts +453 -453
- package/components/ui/route-map/index.ts +1 -1
- package/components/ui/route-map/route-map.stories.tsx +48 -48
- package/components/ui/route-map/route-map.test.tsx +108 -108
- package/components/ui/route-map/route-map.tsx +349 -349
- package/components/ui/scroll-area/index.ts +1 -1
- package/components/ui/scroll-area/scroll-area.stories.tsx +31 -31
- package/components/ui/scroll-area/scroll-area.test.tsx +27 -27
- package/components/ui/scroll-area/scroll-area.tsx +70 -70
- package/components/ui/search/index.ts +1 -1
- package/components/ui/search/search.stories.tsx +107 -107
- package/components/ui/search/search.test.tsx +67 -67
- package/components/ui/search/search.tsx +141 -141
- package/components/ui/select/index.ts +1 -1
- package/components/ui/select/select.stories.tsx +163 -163
- package/components/ui/select/select.test.tsx +99 -99
- package/components/ui/select/select.tsx +195 -195
- package/components/ui/separator/index.ts +1 -1
- package/components/ui/separator/separator.stories.tsx +55 -55
- package/components/ui/separator/separator.test.tsx +23 -23
- package/components/ui/separator/separator.tsx +39 -39
- package/components/ui/sheet/index.ts +1 -1
- package/components/ui/sheet/sheet.stories.tsx +93 -93
- package/components/ui/sheet/sheet.test.tsx +62 -62
- package/components/ui/sheet/sheet.tsx +149 -149
- package/components/ui/simple-map/index.ts +1 -1
- package/components/ui/simple-map/simple-map.stories.tsx +44 -44
- package/components/ui/simple-map/simple-map.test.tsx +36 -36
- package/components/ui/simple-map/simple-map.tsx +92 -92
- package/components/ui/skeleton/index.ts +1 -1
- package/components/ui/skeleton/skeleton.stories.tsx +36 -36
- package/components/ui/skeleton/skeleton.test.tsx +19 -19
- package/components/ui/skeleton/skeleton.tsx +25 -25
- package/components/ui/slider/index.ts +1 -1
- package/components/ui/slider/slider.stories.tsx +44 -44
- package/components/ui/slider/slider.test.tsx +25 -25
- package/components/ui/slider/slider.tsx +66 -66
- package/components/ui/sonner/index.ts +1 -1
- package/components/ui/sonner/sonner.stories.tsx +41 -41
- package/components/ui/sonner/sonner.test.tsx +24 -24
- package/components/ui/sonner/sonner.tsx +74 -74
- package/components/ui/stats-card/index.ts +2 -2
- package/components/ui/stats-card/stats-card-skeleton.tsx +1 -3
- package/components/ui/stats-card/stats-card.stories.tsx +99 -99
- package/components/ui/stats-card/stats-card.test.tsx +34 -34
- package/components/ui/stats-card/stats-card.tsx +93 -93
- package/components/ui/stepper/index.ts +3 -3
- package/components/ui/stepper/stepper.stories.tsx +171 -171
- package/components/ui/stepper/stepper.test.tsx +47 -47
- package/components/ui/stepper/stepper.tsx +190 -190
- package/components/ui/stepper/use-stepper.ts +139 -139
- package/components/ui/switch/index.ts +1 -1
- package/components/ui/switch/switch.stories.tsx +93 -93
- package/components/ui/switch/switch.test.tsx +44 -44
- package/components/ui/switch/switch.tsx +70 -70
- package/components/ui/table/index.ts +1 -1
- package/components/ui/table/table.stories.tsx +114 -114
- package/components/ui/table/table.test.tsx +43 -43
- package/components/ui/table/table.tsx +104 -104
- package/components/ui/tabs/index.ts +1 -1
- package/components/ui/tabs/tabs.stories.tsx +140 -140
- package/components/ui/tabs/tabs.test.tsx +50 -50
- package/components/ui/tabs/tabs.tsx +66 -66
- package/components/ui/textarea/index.ts +1 -1
- package/components/ui/textarea/textarea.stories.tsx +69 -69
- package/components/ui/textarea/textarea.test.tsx +41 -41
- package/components/ui/textarea/textarea.tsx +61 -61
- package/components/ui/timeline/index.ts +1 -1
- package/components/ui/timeline/timeline.stories.tsx +97 -97
- package/components/ui/timeline/timeline.test.tsx +53 -53
- package/components/ui/timeline/timeline.tsx +124 -124
- package/components/ui/toggle/index.ts +1 -1
- package/components/ui/toggle/toggle.stories.tsx +56 -56
- package/components/ui/toggle/toggle.test.tsx +32 -32
- package/components/ui/toggle/toggle.tsx +55 -55
- package/components/ui/toggle-group/index.ts +1 -1
- package/components/ui/toggle-group/toggle-group.stories.tsx +66 -66
- package/components/ui/toggle-group/toggle-group.test.tsx +47 -47
- package/components/ui/toggle-group/toggle-group.tsx +79 -79
- package/components/ui/tooltip/index.ts +1 -1
- package/components/ui/tooltip/tooltip.stories.tsx +83 -83
- package/components/ui/tooltip/tooltip.test.tsx +39 -39
- package/components/ui/tooltip/tooltip.tsx +69 -69
- package/components/ui/tree-view/index.ts +4 -4
- package/components/ui/tree-view/tree-view.stories.tsx +154 -154
- package/components/ui/tree-view/tree-view.test.tsx +58 -58
- package/components/ui/tree-view/tree-view.tsx +171 -171
- package/components/ui/tree-view/use-tree-view.ts +237 -237
- package/components.json +892 -892
- package/contexts/ApiKeyContext.test.tsx +26 -26
- package/contexts/ApiKeyContext.tsx +196 -196
- package/contexts/AssistenteContext.test.tsx +17 -17
- package/contexts/AssistenteContext.tsx +113 -113
- package/contexts/AuthContext.tsx +121 -118
- package/contexts/BrandColorsContext.test.tsx +21 -21
- package/contexts/BrandColorsContext.tsx +251 -251
- package/contexts/LanguageContext.tsx +1 -2
- package/contexts/LayoutContext.test.tsx +29 -29
- package/contexts/LayoutContext.tsx +140 -140
- package/contexts/ThemeContext.test.tsx +38 -38
- package/contexts/ThemeContext.tsx +111 -111
- package/contexts/index.ts +8 -8
- package/contexts/theme-data.ts +340 -340
- package/dist/AssistantChart-COGiOV-g.cjs +3541 -0
- package/dist/AssistantChart-CWX1OWNM.js +3373 -0
- package/dist/AudioPlayer-9psiEucT.cjs +1282 -0
- package/dist/AudioPlayer-Dp2bD1Gk.js +1278 -0
- package/dist/BrandColorsContext-DZT7JjeD.js +659 -0
- package/dist/BrandColorsContext-awnBCmC4.cjs +666 -0
- package/dist/CodeBlock-DYkTfR0f.js +221 -0
- package/dist/CodeBlock-EOvp9cVu.cjs +223 -0
- package/dist/CustomTooltipContent-BhdIeBEg.cjs +54 -0
- package/dist/CustomTooltipContent-CNbVB2NS.js +33 -0
- package/dist/FeatureCard-BZ4CYxFf.cjs +497 -0
- package/dist/FeatureCard-DNycVGwT.js +485 -0
- package/dist/FeatureCardSkeleton-DZqc96mt.js +27 -0
- package/dist/FeatureCardSkeleton-pTa0YNKP.cjs +29 -0
- package/dist/LayoutContext-BEq_-n98.cjs +96 -0
- package/dist/LayoutContext-DNl1xSoX.js +92 -0
- package/dist/ThemeContext-CMD3z2Dz.cjs +1930 -0
- package/dist/ThemeContext-x_F2zsnv.js +1923 -0
- package/dist/VerifyEmailPage-BJjAMUTW.js +3223 -0
- package/dist/VerifyEmailPage-Bv8Ah_TK.cjs +3235 -0
- package/dist/VerifyEmailPage-CkBYfsNy.cjs +3232 -0
- package/dist/VerifyEmailPage-Cyl55sJb.js +3226 -0
- package/dist/VerifyEmailPage-X14vhdyl.js +3296 -0
- package/dist/VerifyEmailPage-u_Dn7t1U.cjs +3305 -0
- package/dist/XerticaOrbe-Uk2JML1-.cjs +1927 -0
- package/dist/XerticaOrbe-jA5T2iOk.js +1925 -0
- package/dist/XerticaProvider-BErr83Bg.js +42 -0
- package/dist/XerticaProvider-CwOkHxiT.cjs +44 -0
- package/dist/XerticaProvider-DUOJg9iX.js +49 -0
- package/dist/XerticaProvider-Dl_b72_l.cjs +51 -0
- package/dist/XerticaXLogo-BX3ueACh.js +255 -0
- package/dist/XerticaXLogo-mqjoBiLI.js +252 -0
- package/dist/XerticaXLogo-qBPhwK3g.cjs +260 -0
- package/dist/XerticaXLogo-uQgwns_E.cjs +257 -0
- package/dist/alert-dialog-DhwPioBa.cjs +885 -0
- package/dist/alert-dialog-DqlRW_An.js +831 -0
- package/dist/assistant.cjs.js +8 -4
- package/dist/assistant.es.js +5 -11
- package/dist/avatar-3kO2Anrp.js +54 -0
- package/dist/avatar-BCM7YQRC.cjs +77 -0
- package/dist/blocks.cjs.js +9 -4
- package/dist/blocks.es.js +2 -16
- package/dist/brand.cjs.js +10 -5
- package/dist/brand.es.js +3 -11
- package/dist/breadcrumb-BKtHF4gk.cjs +98 -0
- package/dist/breadcrumb-ifNsA7Zl.js +90 -0
- package/dist/button-0BlA47It.cjs +85 -0
- package/dist/button-DZHzN1Gd.js +62 -0
- package/dist/cli.js +471 -93
- package/dist/components/brand/theme-toggle/ThemeToggle.d.ts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/dropdown-menu-BMcykFDf.cjs +225 -0
- package/dist/dropdown-menu-Dn_eV2Xb.js +190 -0
- package/dist/google-maps-loader-BCe58h9D.js +308 -0
- package/dist/google-maps-loader-casMyxlo.cjs +316 -0
- package/dist/hooks.cjs.js +12 -8
- package/dist/hooks.es.js +10 -27
- package/dist/index-9GWd0qxq.cjs +12 -0
- package/dist/index-BabBx2pa.js +6 -0
- package/dist/index.cjs.js +37 -32
- package/dist/index.es.js +30 -363
- package/dist/input-C_UiS2Py.cjs +152 -0
- package/dist/input-cc-PTD4R.js +123 -0
- package/dist/layout.cjs.js +10 -6
- package/dist/layout.es.js +7 -9
- package/dist/media.cjs.js +8 -3
- package/dist/media.es.js +1 -6
- package/dist/pages.cjs.js +8 -3
- package/dist/pages.es.js +1 -11
- package/dist/progress-C7Lti5wo.js +80 -0
- package/dist/progress-Cqwxbqs1.cjs +103 -0
- package/dist/rich-text-editor-DqLICivI.js +2832 -0
- package/dist/rich-text-editor-DxO1Hz3a.cjs +2903 -0
- package/dist/select-CH6v_KcQ.cjs +161 -0
- package/dist/select-D-xvCZK2.js +130 -0
- package/dist/sidebar-3XyzjVBw.js +792 -0
- package/dist/sidebar-B4ZWaMrE.js +792 -0
- package/dist/sidebar-BS1p2V7t.cjs +795 -0
- package/dist/sidebar-DyYvgyBj.cjs +795 -0
- package/dist/skeleton-DjiHerJn.cjs +87 -0
- package/dist/skeleton-DtR5tkYe.js +78 -0
- package/dist/slider-B00b9SVK.cjs +78 -0
- package/dist/slider-DQCNUUMj.js +56 -0
- package/dist/sonner-B-jWlik1.cjs +68 -0
- package/dist/sonner-C9tiqj4f.js +47 -0
- package/dist/tooltip-D8n9UYoU.cjs +72 -0
- package/dist/tooltip-RtbSmPYJ.js +48 -0
- package/dist/ui.cjs.js +23 -18
- package/dist/ui.es.js +16 -303
- package/dist/use-audio-player-B78fd2ct.js +188 -0
- package/dist/use-audio-player-DGvhPrgR.cjs +190 -0
- package/dist/use-mobile-BdXTRb0Z.cjs +51 -0
- package/dist/use-mobile-Ce2cBAQe.js +29 -0
- package/dist/xertica-assistant-B1NaSFFj.js +2173 -0
- package/dist/xertica-assistant-B687qEPU.js +2165 -0
- package/dist/xertica-assistant-CIaUlbIt.cjs +2180 -0
- package/dist/xertica-assistant-sOHwTgIP.cjs +2172 -0
- package/dist/xertica-ui.css +1 -1
- package/docs/ai-usage.md +195 -195
- package/docs/architecture-improvements.md +456 -456
- package/docs/architecture.md +312 -306
- package/docs/components/accordion.md +109 -109
- package/docs/components/alert-dialog.md +127 -127
- package/docs/components/alert.md +106 -106
- package/docs/components/aspect-ratio.md +58 -58
- package/docs/components/assistant-chart.md +47 -47
- package/docs/components/assistant.md +428 -426
- package/docs/components/audio-player.md +167 -167
- package/docs/components/avatar.md +101 -101
- package/docs/components/badge.md +84 -84
- package/docs/components/branding.md +252 -252
- package/docs/components/breadcrumb.md +104 -104
- package/docs/components/button.md +156 -156
- package/docs/components/calendar.md +141 -141
- package/docs/components/card-patterns.md +447 -445
- package/docs/components/card.md +245 -245
- package/docs/components/carousel.md +100 -100
- package/docs/components/chart.md +638 -638
- package/docs/components/checkbox.md +88 -88
- package/docs/components/code-block.md +105 -105
- package/docs/components/collapsible.md +86 -86
- package/docs/components/command.md +113 -113
- package/docs/components/context-menu.md +81 -81
- package/docs/components/dialog.md +198 -198
- package/docs/components/drawer.md +105 -105
- package/docs/components/dropdown-menu.md +127 -127
- package/docs/components/empty.md +127 -127
- package/docs/components/error-boundary.md +201 -191
- package/docs/components/file-upload.md +189 -189
- package/docs/components/floating-media-wrapper.md +63 -63
- package/docs/components/form.md +177 -177
- package/docs/components/formatted-document.md +105 -105
- package/docs/components/google-maps-loader.md +44 -44
- package/docs/components/header.md +177 -177
- package/docs/components/hooks.md +432 -430
- package/docs/components/hover-card.md +86 -86
- package/docs/components/image-with-fallback.md +107 -107
- package/docs/components/input-otp.md +95 -95
- package/docs/components/input.md +130 -130
- package/docs/components/label.md +69 -69
- package/docs/components/language-selector.md +20 -16
- package/docs/components/map-layers.md +138 -138
- package/docs/components/map.md +84 -84
- package/docs/components/markdown-message.md +47 -47
- package/docs/components/menubar.md +89 -89
- package/docs/components/modern-chat-input.md +164 -164
- package/docs/components/navigation-menu.md +83 -83
- package/docs/components/notification-badge.md +78 -78
- package/docs/components/page-header.md +93 -93
- package/docs/components/pages.md +323 -309
- package/docs/components/pagination.md +334 -334
- package/docs/components/popover.md +116 -116
- package/docs/components/progress.md +103 -103
- package/docs/components/radio-group.md +133 -133
- package/docs/components/rating.md +77 -77
- package/docs/components/resizable.md +84 -84
- package/docs/components/rich-text-editor.md +255 -255
- package/docs/components/route-map.md +124 -124
- package/docs/components/scroll-area.md +58 -58
- package/docs/components/search.md +87 -87
- package/docs/components/select.md +144 -144
- package/docs/components/separator.md +58 -58
- package/docs/components/sheet.md +122 -122
- package/docs/components/sidebar.md +314 -314
- package/docs/components/simple-map.md +51 -51
- package/docs/components/skeleton.md +99 -99
- package/docs/components/slider.md +84 -84
- package/docs/components/sonner.md +115 -115
- package/docs/components/stats-card.md +120 -120
- package/docs/components/stepper.md +268 -268
- package/docs/components/switch.md +106 -106
- package/docs/components/table.md +138 -138
- package/docs/components/tabs.md +117 -117
- package/docs/components/textarea.md +86 -86
- package/docs/components/theme-toggle.md +73 -73
- package/docs/components/timeline.md +121 -121
- package/docs/components/toggle-group.md +68 -68
- package/docs/components/toggle.md +62 -62
- package/docs/components/tooltip.md +116 -116
- package/docs/components/tree-view.md +238 -238
- package/docs/components/use-mobile.md +96 -96
- package/docs/components/video-player.md +68 -68
- package/docs/components/xertica-logo.md +36 -36
- package/docs/components/xertica-orbe.md +35 -35
- package/docs/components/xertica-provider.md +65 -65
- package/docs/components/xertica-xlogo.md +35 -35
- package/docs/decision-tree.md +293 -293
- package/docs/doc-audit.md +244 -243
- package/docs/form-sizing.md +162 -162
- package/docs/getting-started.md +616 -591
- package/docs/guidelines.md +330 -328
- package/docs/i18n.md +61 -57
- package/docs/installation.md +268 -267
- package/docs/layout.md +143 -143
- package/docs/llms.md +295 -295
- package/docs/patterns/analytics.md +194 -194
- package/docs/patterns/crud.md +149 -149
- package/docs/patterns/dashboard.md +138 -138
- package/docs/patterns/detail-page.md +296 -296
- package/docs/patterns/form.md +241 -241
- package/docs/patterns/login.md +156 -156
- package/docs/patterns/settings.md +368 -368
- package/docs/patterns/wizard.md +213 -213
- package/docs/state-management.md +289 -289
- package/guidelines/Guidelines.md +409 -406
- package/hooks/useTheme.test.tsx +16 -16
- package/hooks/useTheme.ts +4 -4
- package/imports/Podcast.tsx +540 -540
- package/imports/XerticaAi.tsx +46 -46
- package/imports/XerticaX.tsx +15 -15
- package/imports/svg-aueiaqngck.ts +20 -20
- package/imports/svg-v9krss1ozd.ts +23 -23
- package/imports/svg-vhrdofe3qe.ts +6 -6
- package/llms-compact.txt +2 -1
- package/llms.txt +2 -1
- package/mcp/resources.json +22 -22
- package/mcp/tools.json +35 -35
- package/package.json +219 -213
- package/scripts/ai-validator.ts +91 -91
- package/scripts/cleanup-case-dupes.ts +62 -62
- package/scripts/generate-ai-manifests.ts +107 -107
- package/styles/globals.css +13 -13
- package/styles/xertica/app-overrides/chat.css +61 -61
- package/styles/xertica/app-overrides/scrollbar.css +33 -33
- package/styles/xertica/base.css +90 -71
- package/styles/xertica/integrations/google-maps.css +76 -76
- package/styles/xertica/integrations/sonner.css +73 -73
- package/styles/xertica/theme-map.css +102 -99
- package/styles/xertica/tokens.css +240 -236
- package/templates/CLAUDE.md +16 -1
- package/templates/eslint.config.js +26 -26
- package/templates/guidelines/Guidelines.md +577 -553
- package/templates/package.json +69 -69
- package/templates/postcss.config.js +6 -6
- package/templates/src/app/App.tsx +46 -46
- package/templates/src/app/components/AppLayout.tsx +55 -55
- package/templates/src/app/components/AuthGuard.tsx +131 -82
- package/templates/src/app/context/AuthContext.tsx +108 -108
- package/templates/src/features/assistant/index.ts +5 -5
- package/templates/src/features/auth/index.ts +4 -4
- package/templates/src/features/auth/ui/AuthPageShell.tsx +32 -32
- package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +70 -72
- package/templates/src/features/auth/ui/LoginContent.tsx +92 -92
- package/templates/src/features/auth/ui/ResetPasswordContent.tsx +6 -2
- package/templates/src/features/auth/ui/SocialLoginButtons.tsx +78 -78
- package/templates/src/features/auth/ui/VerifyEmailContent.tsx +2 -6
- package/templates/src/features/home/data/mock.ts +41 -35
- package/templates/src/features/home/index.ts +11 -11
- package/templates/src/features/home/store/dashboardStore.ts +25 -25
- package/templates/src/features/home/ui/HomeContent.tsx +117 -119
- package/templates/src/features/template/index.ts +5 -5
- package/templates/src/features/template/ui/CrudTemplate.tsx +1 -4
- package/templates/src/features/template/ui/LoginTemplate.tsx +1 -1
- package/templates/src/features/template/ui/TemplateContent.tsx +29 -21
- package/templates/src/locales/en/pages/templates.json +17 -17
- package/templates/src/locales/es/pages/templates.json +17 -17
- package/templates/src/locales/pt-BR/pages/templates.json +17 -17
- package/templates/src/main.tsx +11 -11
- package/templates/src/pages/AssistantPage.tsx +26 -20
- package/templates/src/pages/ForgotPasswordPage.tsx +6 -6
- package/templates/src/pages/HomePage.tsx +53 -49
- package/templates/src/pages/LoginPage.tsx +10 -10
- package/templates/src/pages/ResetPasswordPage.tsx +6 -6
- package/templates/src/pages/TemplatePage.tsx +28 -28
- package/templates/src/pages/VerifyEmailPage.tsx +6 -6
- package/templates/src/shared/config/navigation.ts +19 -19
- package/templates/src/shared/error-boundary.tsx +150 -154
- package/templates/src/shared/error-fallbacks.tsx +222 -226
- package/templates/src/shared/lib/auth.ts +20 -20
- package/templates/src/shared/types/auth.ts +3 -3
- package/templates/src/styles/index.css +95 -95
- package/templates/src/styles/xertica/tokens.css +240 -236
- package/templates/tsconfig.json +25 -25
- package/templates/tsconfig.node.json +12 -12
- package/templates/vite-env.d.ts +1 -1
- package/templates/vite.config.js +20 -20
- package/templates/vite.config.ts +54 -51
- package/utils/color-utils.ts +72 -72
- package/utils/demo-responses.test.ts +10 -10
- package/utils/demo-responses.ts +151 -151
- package/utils/gemini.test.ts +25 -25
- package/utils/gemini.ts +155 -155
|
@@ -1,586 +1,586 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { Sidebar, useSidebar } from './sidebar';
|
|
3
|
-
import { useLayout } from '../../../contexts/LayoutContext';
|
|
4
|
-
import { BrowserRouter } from 'react-router-dom';
|
|
5
|
-
import {
|
|
6
|
-
Home,
|
|
7
|
-
Users,
|
|
8
|
-
Settings,
|
|
9
|
-
BarChart,
|
|
10
|
-
Plus,
|
|
11
|
-
Clock,
|
|
12
|
-
FileEdit,
|
|
13
|
-
ArrowRightLeft,
|
|
14
|
-
PanelLeft,
|
|
15
|
-
Menu,
|
|
16
|
-
Trash2,
|
|
17
|
-
Map,
|
|
18
|
-
Archive,
|
|
19
|
-
} from 'lucide-react';
|
|
20
|
-
import React, { useState } from 'react';
|
|
21
|
-
import { Badge } from '../../ui/badge';
|
|
22
|
-
import { Button } from '../../ui/button';
|
|
23
|
-
import { Progress } from '../../ui/progress';
|
|
24
|
-
|
|
25
|
-
const meta: Meta<typeof Sidebar> = {
|
|
26
|
-
title: 'Layout/Sidebar',
|
|
27
|
-
component: Sidebar,
|
|
28
|
-
decorators: [
|
|
29
|
-
Story => (
|
|
30
|
-
<BrowserRouter>
|
|
31
|
-
<div className="flex h-screen w-full overflow-hidden bg-background">
|
|
32
|
-
<Story />
|
|
33
|
-
</div>
|
|
34
|
-
</BrowserRouter>
|
|
35
|
-
),
|
|
36
|
-
],
|
|
37
|
-
parameters: {
|
|
38
|
-
layout: 'fullscreen',
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export default meta;
|
|
43
|
-
type Story = StoryObj<typeof Sidebar>;
|
|
44
|
-
|
|
45
|
-
export const Default: Story = {
|
|
46
|
-
args: {
|
|
47
|
-
variant: 'default',
|
|
48
|
-
expanded: false,
|
|
49
|
-
user: { email: 'admin@example.com' },
|
|
50
|
-
onLogout: () => console.log('Logged out'),
|
|
51
|
-
location: { pathname: '/home' },
|
|
52
|
-
routes: [
|
|
53
|
-
{ path: '/home', label: 'Home', icon: Home },
|
|
54
|
-
{ path: '/dashboard', label: 'Dashboard', icon: Users },
|
|
55
|
-
{ path: '/settings', label: 'Settings', icon: Settings },
|
|
56
|
-
],
|
|
57
|
-
footer: {
|
|
58
|
-
showUser: true,
|
|
59
|
-
showSettings: true,
|
|
60
|
-
showLogout: true,
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
render: args => {
|
|
64
|
-
const { sidebarWidth: contextWidth } = useLayout();
|
|
65
|
-
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
66
|
-
|
|
67
|
-
// In Storybook, we match the sidebar widths (280 expanded, 80 collapsed)
|
|
68
|
-
const currentWidth = isExpanded ? 280 : 80;
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<div
|
|
72
|
-
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
73
|
-
style={{ transform: 'translateZ(0)' }}
|
|
74
|
-
>
|
|
75
|
-
<Sidebar
|
|
76
|
-
{...args}
|
|
77
|
-
expanded={isExpanded}
|
|
78
|
-
onToggle={() => setIsExpanded(!isExpanded)}
|
|
79
|
-
width={currentWidth}
|
|
80
|
-
navigate={() => {}}
|
|
81
|
-
/>
|
|
82
|
-
<div
|
|
83
|
-
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
84
|
-
style={{ left: `${currentWidth}px` }}
|
|
85
|
-
>
|
|
86
|
-
<div className="text-center">
|
|
87
|
-
<p className="text-muted-foreground">Traditional System Navigation</p>
|
|
88
|
-
<p className="text-xs text-muted-foreground mt-2">Click on the menu icon to expand</p>
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
);
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
export const DefaultWithGroups: Story = {
|
|
97
|
-
args: {
|
|
98
|
-
variant: 'default',
|
|
99
|
-
expanded: false,
|
|
100
|
-
user: { name: 'Admin', email: 'admin@example.com' },
|
|
101
|
-
onLogout: () => console.log('Logged out'),
|
|
102
|
-
location: { pathname: '/home' },
|
|
103
|
-
navigationGroups: [
|
|
104
|
-
{
|
|
105
|
-
id: 'main',
|
|
106
|
-
label: 'Principal',
|
|
107
|
-
items: [
|
|
108
|
-
{ path: '/home', label: 'Início', icon: Home },
|
|
109
|
-
{
|
|
110
|
-
path: '/dashboard',
|
|
111
|
-
label: 'Dashboard',
|
|
112
|
-
icon: BarChart,
|
|
113
|
-
children: [
|
|
114
|
-
{ path: '/dashboard/overview', label: 'Visão Geral', icon: BarChart },
|
|
115
|
-
{ path: '/dashboard/reports', label: 'Relatórios', icon: FileEdit },
|
|
116
|
-
{ path: '/dashboard/analytics', label: 'Analytics', icon: Map },
|
|
117
|
-
],
|
|
118
|
-
},
|
|
119
|
-
],
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
id: 'admin',
|
|
123
|
-
label: 'Administração',
|
|
124
|
-
items: [
|
|
125
|
-
{
|
|
126
|
-
path: '/users',
|
|
127
|
-
label: 'Usuários',
|
|
128
|
-
icon: Users,
|
|
129
|
-
children: [
|
|
130
|
-
{ path: '/users/list', label: 'Lista de Usuários', icon: Users },
|
|
131
|
-
{ path: '/users/roles', label: 'Perfis de Acesso', icon: Settings },
|
|
132
|
-
],
|
|
133
|
-
},
|
|
134
|
-
{ path: '/settings', label: 'Configurações', icon: Settings },
|
|
135
|
-
],
|
|
136
|
-
},
|
|
137
|
-
],
|
|
138
|
-
footer: {
|
|
139
|
-
showUser: true,
|
|
140
|
-
showSettings: false,
|
|
141
|
-
showLogout: true,
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
render: args => {
|
|
145
|
-
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
146
|
-
const currentWidth = isExpanded ? 280 : 80;
|
|
147
|
-
|
|
148
|
-
return (
|
|
149
|
-
<div
|
|
150
|
-
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
151
|
-
style={{ transform: 'translateZ(0)' }}
|
|
152
|
-
>
|
|
153
|
-
<Sidebar
|
|
154
|
-
{...args}
|
|
155
|
-
expanded={isExpanded}
|
|
156
|
-
onToggle={() => setIsExpanded(!isExpanded)}
|
|
157
|
-
width={currentWidth}
|
|
158
|
-
navigate={() => {}}
|
|
159
|
-
/>
|
|
160
|
-
<div
|
|
161
|
-
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
162
|
-
style={{ left: `${currentWidth}px` }}
|
|
163
|
-
>
|
|
164
|
-
<div className="text-center">
|
|
165
|
-
<p className="text-muted-foreground">Navigation with Groups and Children</p>
|
|
166
|
-
<p className="text-xs text-muted-foreground mt-2">
|
|
167
|
-
Expand and click the arrow button on items to see sub-menus
|
|
168
|
-
</p>
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
</div>
|
|
172
|
-
);
|
|
173
|
-
},
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
export const Assistant: Story = {
|
|
177
|
-
args: {
|
|
178
|
-
variant: 'assistant',
|
|
179
|
-
expanded: false,
|
|
180
|
-
user: { email: 'admin@example.com' },
|
|
181
|
-
onLogout: () => console.log('Logged out'),
|
|
182
|
-
location: { pathname: '/assistant/refatoracao' },
|
|
183
|
-
search: {
|
|
184
|
-
show: true,
|
|
185
|
-
placeholder: 'Buscar tópicos...',
|
|
186
|
-
filter: {
|
|
187
|
-
show: true,
|
|
188
|
-
content: (
|
|
189
|
-
<div className="p-2 space-y-2">
|
|
190
|
-
<div className="text-xs font-semibold uppercase text-muted-foreground px-2 text-left">
|
|
191
|
-
Filter by Status
|
|
192
|
-
</div>
|
|
193
|
-
<div className="flex flex-wrap gap-2 p-1">
|
|
194
|
-
<Badge className="bg-sidebar-foreground/20 text-sidebar-foreground border-none cursor-pointer hover:bg-sidebar-foreground/30">
|
|
195
|
-
Active
|
|
196
|
-
</Badge>
|
|
197
|
-
<Badge
|
|
198
|
-
variant="outline"
|
|
199
|
-
className="text-sidebar-foreground/70 border-sidebar-foreground/20 cursor-pointer hover:bg-sidebar-foreground/10"
|
|
200
|
-
>
|
|
201
|
-
Archived
|
|
202
|
-
</Badge>
|
|
203
|
-
<Badge
|
|
204
|
-
variant="outline"
|
|
205
|
-
className="text-sidebar-foreground/70 border-sidebar-foreground/20 cursor-pointer hover:bg-sidebar-foreground/10"
|
|
206
|
-
>
|
|
207
|
-
Pending
|
|
208
|
-
</Badge>
|
|
209
|
-
</div>
|
|
210
|
-
</div>
|
|
211
|
-
),
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
fixedArea: {
|
|
215
|
-
show: true,
|
|
216
|
-
icon: Plus,
|
|
217
|
-
onClick: () => console.log('New Conversation clicked'),
|
|
218
|
-
content: (
|
|
219
|
-
<Button className="w-full bg-sidebar-primary hover:bg-sidebar-primary/90 text-sidebar-primary-foreground shadow-lg font-bold border-none transition-all duration-300 transform hover:scale-[1.02] active:scale-[0.98]">
|
|
220
|
-
<Plus className="w-4 h-4 mr-2" />
|
|
221
|
-
New Conversation
|
|
222
|
-
</Button>
|
|
223
|
-
),
|
|
224
|
-
},
|
|
225
|
-
navigationGroups: [
|
|
226
|
-
{
|
|
227
|
-
id: 'recent',
|
|
228
|
-
label: 'Recent',
|
|
229
|
-
icon: Clock,
|
|
230
|
-
items: [
|
|
231
|
-
{
|
|
232
|
-
path: '/assistant/refatoracao',
|
|
233
|
-
label: 'Edit Sidebar',
|
|
234
|
-
description: 'Active now',
|
|
235
|
-
actions: [
|
|
236
|
-
{ label: 'Rename', icon: FileEdit, onClick: () => console.log('Open rename...') },
|
|
237
|
-
{
|
|
238
|
-
label: 'Move',
|
|
239
|
-
icon: ArrowRightLeft,
|
|
240
|
-
children: [
|
|
241
|
-
{
|
|
242
|
-
label: 'Active Projects',
|
|
243
|
-
onClick: () => console.log('Moved to Active Projects'),
|
|
244
|
-
},
|
|
245
|
-
{ label: 'Monitoring', onClick: () => console.log('Moved to Monitoring') },
|
|
246
|
-
{ label: 'Archive', onClick: () => console.log('Moved to Archive') },
|
|
247
|
-
],
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
label: 'Clear',
|
|
251
|
-
icon: Trash2,
|
|
252
|
-
onClick: () => console.log('History Cleared!'),
|
|
253
|
-
variant: 'destructive',
|
|
254
|
-
},
|
|
255
|
-
],
|
|
256
|
-
},
|
|
257
|
-
],
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
id: 'projects',
|
|
261
|
-
label: 'Project Monitoring',
|
|
262
|
-
icon: Map,
|
|
263
|
-
actions: [
|
|
264
|
-
{
|
|
265
|
-
label: 'New Category',
|
|
266
|
-
icon: Plus,
|
|
267
|
-
onClick: () => console.log('Create new category...'),
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
label: 'Archive Group',
|
|
271
|
-
icon: Archive,
|
|
272
|
-
onClick: () => console.log('Archiving group...'),
|
|
273
|
-
},
|
|
274
|
-
],
|
|
275
|
-
items: [
|
|
276
|
-
{
|
|
277
|
-
path: '/assistant/br163',
|
|
278
|
-
label: 'Panel Status',
|
|
279
|
-
icon: () => <div className="w-2 h-2 rounded-full bg-yellow-500" />,
|
|
280
|
-
description: (
|
|
281
|
-
<div className="space-y-1.5 min-w-[160px]">
|
|
282
|
-
<Progress value={67} className="h-1.5 bg-sidebar-foreground/10" />
|
|
283
|
-
<div className="flex justify-between items-center text-[10px] text-sidebar-foreground/60">
|
|
284
|
-
<span>Label</span>
|
|
285
|
-
<span>67%</span>
|
|
286
|
-
</div>
|
|
287
|
-
</div>
|
|
288
|
-
),
|
|
289
|
-
},
|
|
290
|
-
],
|
|
291
|
-
},
|
|
292
|
-
],
|
|
293
|
-
},
|
|
294
|
-
render: args => {
|
|
295
|
-
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
296
|
-
const currentWidth = isExpanded ? 280 : 80;
|
|
297
|
-
|
|
298
|
-
return (
|
|
299
|
-
<div
|
|
300
|
-
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
301
|
-
style={{ transform: 'translateZ(0)' }}
|
|
302
|
-
>
|
|
303
|
-
<Sidebar
|
|
304
|
-
{...args}
|
|
305
|
-
expanded={isExpanded}
|
|
306
|
-
onToggle={() => setIsExpanded(!isExpanded)}
|
|
307
|
-
width={currentWidth}
|
|
308
|
-
navigate={() => {}}
|
|
309
|
-
/>
|
|
310
|
-
<div
|
|
311
|
-
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
312
|
-
style={{ left: `${currentWidth}px` }}
|
|
313
|
-
>
|
|
314
|
-
<div className="text-center">
|
|
315
|
-
<p className="text-muted-foreground">Assistant Mode Content</p>
|
|
316
|
-
<p className="text-xs text-muted-foreground mt-2">Click on the menu icon to expand</p>
|
|
317
|
-
</div>
|
|
318
|
-
</div>
|
|
319
|
-
</div>
|
|
320
|
-
);
|
|
321
|
-
},
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
export const Collapsed: Story = {
|
|
325
|
-
args: {
|
|
326
|
-
...Default.args,
|
|
327
|
-
expanded: false,
|
|
328
|
-
},
|
|
329
|
-
render: args => {
|
|
330
|
-
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
331
|
-
const currentWidth = isExpanded ? 280 : 80;
|
|
332
|
-
|
|
333
|
-
return (
|
|
334
|
-
<div
|
|
335
|
-
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
336
|
-
style={{ transform: 'translateZ(0)' }}
|
|
337
|
-
>
|
|
338
|
-
<Sidebar
|
|
339
|
-
{...args}
|
|
340
|
-
expanded={isExpanded}
|
|
341
|
-
onToggle={() => setIsExpanded(!isExpanded)}
|
|
342
|
-
width={currentWidth}
|
|
343
|
-
navigate={() => {}}
|
|
344
|
-
/>
|
|
345
|
-
<div
|
|
346
|
-
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
347
|
-
style={{ left: `${currentWidth}px` }}
|
|
348
|
-
>
|
|
349
|
-
<div className="text-center">
|
|
350
|
-
<p className="text-muted-foreground">Compact Navigation</p>
|
|
351
|
-
<p className="text-xs text-muted-foreground mt-2">Click on the menu icon to expand</p>
|
|
352
|
-
</div>
|
|
353
|
-
</div>
|
|
354
|
-
</div>
|
|
355
|
-
);
|
|
356
|
-
},
|
|
357
|
-
};
|
|
358
|
-
export const NoFooter: Story = {
|
|
359
|
-
args: {
|
|
360
|
-
...Default.args,
|
|
361
|
-
showFooter: false,
|
|
362
|
-
},
|
|
363
|
-
render: args => {
|
|
364
|
-
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
365
|
-
const currentWidth = isExpanded ? 280 : 80;
|
|
366
|
-
|
|
367
|
-
return (
|
|
368
|
-
<div
|
|
369
|
-
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
370
|
-
style={{ transform: 'translateZ(0)' }}
|
|
371
|
-
>
|
|
372
|
-
<Sidebar
|
|
373
|
-
{...args}
|
|
374
|
-
expanded={isExpanded}
|
|
375
|
-
onToggle={() => setIsExpanded(!isExpanded)}
|
|
376
|
-
width={currentWidth}
|
|
377
|
-
navigate={() => {}}
|
|
378
|
-
/>
|
|
379
|
-
<div
|
|
380
|
-
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
381
|
-
style={{ left: `${currentWidth}px` }}
|
|
382
|
-
>
|
|
383
|
-
<div className="text-center">
|
|
384
|
-
<p className="text-muted-foreground">Sidebar without Footer</p>
|
|
385
|
-
<p className="text-xs text-muted-foreground mt-2">Click on the menu icon to expand</p>
|
|
386
|
-
</div>
|
|
387
|
-
</div>
|
|
388
|
-
</div>
|
|
389
|
-
);
|
|
390
|
-
},
|
|
391
|
-
};
|
|
392
|
-
|
|
393
|
-
export const Autonomous: Story = {
|
|
394
|
-
args: {
|
|
395
|
-
...Default.args,
|
|
396
|
-
expanded: undefined,
|
|
397
|
-
onToggle: undefined,
|
|
398
|
-
},
|
|
399
|
-
render: args => {
|
|
400
|
-
return (
|
|
401
|
-
<div
|
|
402
|
-
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
403
|
-
style={{ transform: 'translateZ(0)' }}
|
|
404
|
-
>
|
|
405
|
-
<Sidebar {...args} />
|
|
406
|
-
<div
|
|
407
|
-
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
408
|
-
style={{ left: `80px` }}
|
|
409
|
-
>
|
|
410
|
-
<div className="text-center max-w-md">
|
|
411
|
-
<p className="text-muted-foreground font-bold">Autonomous Sidebar</p>
|
|
412
|
-
<p className="text-sm text-muted-foreground/80 mt-2">
|
|
413
|
-
This instance is managing its own state internally. No `expanded` or `onToggle` props
|
|
414
|
-
are passed.
|
|
415
|
-
</p>
|
|
416
|
-
<p className="text-xs text-muted-foreground mt-4">
|
|
417
|
-
Note: Layout coordination (content padding) must be handled manually when using
|
|
418
|
-
autonomous mode without LayoutProvider.
|
|
419
|
-
</p>
|
|
420
|
-
</div>
|
|
421
|
-
</div>
|
|
422
|
-
</div>
|
|
423
|
-
);
|
|
424
|
-
},
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
/**
|
|
428
|
-
* Compound Component API — demonstrates using Sidebar.Root + sub-components
|
|
429
|
-
* for full layout control. This is the recommended pattern for advanced
|
|
430
|
-
* customization without forking the component.
|
|
431
|
-
*/
|
|
432
|
-
export const CompoundComponentAPI: Story = {
|
|
433
|
-
name: 'Compound Component API',
|
|
434
|
-
render: () => {
|
|
435
|
-
const [isExpanded, setIsExpanded] = React.useState(true);
|
|
436
|
-
const currentWidth = isExpanded ? 280 : 80;
|
|
437
|
-
const groups = [
|
|
438
|
-
{
|
|
439
|
-
id: 'main',
|
|
440
|
-
label: 'Principal',
|
|
441
|
-
items: [
|
|
442
|
-
{ path: '/home', label: 'Início', icon: Home },
|
|
443
|
-
{ path: '/dashboard', label: 'Dashboard', icon: BarChart },
|
|
444
|
-
],
|
|
445
|
-
},
|
|
446
|
-
{
|
|
447
|
-
id: 'admin',
|
|
448
|
-
label: 'Administração',
|
|
449
|
-
items: [
|
|
450
|
-
{ path: '/users', label: 'Usuários', icon: Users },
|
|
451
|
-
{ path: '/settings', label: 'Configurações', icon: Settings },
|
|
452
|
-
],
|
|
453
|
-
},
|
|
454
|
-
];
|
|
455
|
-
|
|
456
|
-
return (
|
|
457
|
-
<div
|
|
458
|
-
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
459
|
-
style={{ transform: 'translateZ(0)' }}
|
|
460
|
-
>
|
|
461
|
-
{/* Compound Component usage */}
|
|
462
|
-
<Sidebar.Root
|
|
463
|
-
expanded={isExpanded}
|
|
464
|
-
onToggle={() => setIsExpanded(prev => !prev)}
|
|
465
|
-
width={currentWidth}
|
|
466
|
-
location={{ pathname: '/home' }}
|
|
467
|
-
navigate={() => {}}
|
|
468
|
-
>
|
|
469
|
-
<Sidebar.Header />
|
|
470
|
-
<Sidebar.Nav navigationGroups={groups} />
|
|
471
|
-
<Sidebar.Footer
|
|
472
|
-
user={{ name: 'Admin', email: 'admin@example.com' }}
|
|
473
|
-
onLogout={() => console.log('logout')}
|
|
474
|
-
showUser
|
|
475
|
-
showSettings
|
|
476
|
-
showLogout
|
|
477
|
-
/>
|
|
478
|
-
</Sidebar.Root>
|
|
479
|
-
|
|
480
|
-
<div
|
|
481
|
-
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
482
|
-
style={{ left: `${currentWidth}px` }}
|
|
483
|
-
>
|
|
484
|
-
<div className="text-center max-w-md space-y-3">
|
|
485
|
-
<p className="text-muted-foreground font-bold">Compound Component API</p>
|
|
486
|
-
<p className="text-sm text-muted-foreground/80">
|
|
487
|
-
Built with <code className="bg-muted px-1 rounded text-xs"><Sidebar.Root></code>
|
|
488
|
-
, <code className="bg-muted px-1 rounded text-xs"><Sidebar.Header></code>,{' '}
|
|
489
|
-
<code className="bg-muted px-1 rounded text-xs"><Sidebar.Nav></code>, and{' '}
|
|
490
|
-
<code className="bg-muted px-1 rounded text-xs"><Sidebar.Footer></code>.
|
|
491
|
-
</p>
|
|
492
|
-
<p className="text-xs text-muted-foreground">
|
|
493
|
-
Each sub-component reads shared state from{' '}
|
|
494
|
-
<code className="bg-muted px-1 rounded text-xs">SidebarContext</code> via{' '}
|
|
495
|
-
<code className="bg-muted px-1 rounded text-xs">Sidebar.Root</code>.
|
|
496
|
-
</p>
|
|
497
|
-
</div>
|
|
498
|
-
</div>
|
|
499
|
-
</div>
|
|
500
|
-
);
|
|
501
|
-
},
|
|
502
|
-
};
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Headless Hook — demonstrates using `useSidebar` directly for fully custom rendering.
|
|
506
|
-
* The hook manages all state; the UI is entirely up to the consumer.
|
|
507
|
-
*/
|
|
508
|
-
export const HeadlessHook: Story = {
|
|
509
|
-
name: 'Headless Hook (useSidebar)',
|
|
510
|
-
render: () => {
|
|
511
|
-
const groups = [
|
|
512
|
-
{
|
|
513
|
-
id: 'main',
|
|
514
|
-
label: 'Principal',
|
|
515
|
-
items: [
|
|
516
|
-
{ path: '/home', label: 'Início', icon: Home },
|
|
517
|
-
{ path: '/dashboard', label: 'Dashboard', icon: BarChart },
|
|
518
|
-
{ path: '/users', label: 'Usuários', icon: Users },
|
|
519
|
-
],
|
|
520
|
-
},
|
|
521
|
-
];
|
|
522
|
-
|
|
523
|
-
const {
|
|
524
|
-
expanded,
|
|
525
|
-
toggleExpanded,
|
|
526
|
-
navigationGroups: resolvedGroups,
|
|
527
|
-
} = useSidebar({ defaultExpanded: true, navigationGroups: groups });
|
|
528
|
-
|
|
529
|
-
const width = expanded ? 280 : 80;
|
|
530
|
-
|
|
531
|
-
return (
|
|
532
|
-
<div
|
|
533
|
-
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
534
|
-
style={{ transform: 'translateZ(0)' }}
|
|
535
|
-
>
|
|
536
|
-
{/* Fully custom sidebar built with useSidebar hook */}
|
|
537
|
-
<div
|
|
538
|
-
className="absolute inset-y-0 left-0 bg-sidebar text-sidebar-foreground flex flex-col transition-all duration-300 z-50"
|
|
539
|
-
style={{ width: `${width}px` }}
|
|
540
|
-
>
|
|
541
|
-
<div className="p-4">
|
|
542
|
-
<button
|
|
543
|
-
onClick={toggleExpanded}
|
|
544
|
-
className="w-full h-10 flex items-center justify-center rounded-md bg-sidebar-foreground/10 hover:bg-sidebar-foreground/20 text-sidebar-foreground transition-colors"
|
|
545
|
-
aria-label={expanded ? 'Collapse' : 'Expand'}
|
|
546
|
-
>
|
|
547
|
-
{expanded ? <PanelLeft className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
|
|
548
|
-
</button>
|
|
549
|
-
</div>
|
|
550
|
-
<nav className="flex-1 px-3 space-y-1">
|
|
551
|
-
{resolvedGroups
|
|
552
|
-
.flatMap(g => g.items)
|
|
553
|
-
.map(item => {
|
|
554
|
-
const Icon = item.icon;
|
|
555
|
-
return (
|
|
556
|
-
<button
|
|
557
|
-
key={item.path}
|
|
558
|
-
className="w-full h-10 flex items-center gap-3 px-3 rounded-md text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground transition-colors"
|
|
559
|
-
>
|
|
560
|
-
{Icon && <Icon className="w-5 h-5 flex-shrink-0" />}
|
|
561
|
-
{expanded && <span className="truncate text-sm">{item.label}</span>}
|
|
562
|
-
</button>
|
|
563
|
-
);
|
|
564
|
-
})}
|
|
565
|
-
</nav>
|
|
566
|
-
</div>
|
|
567
|
-
|
|
568
|
-
<div
|
|
569
|
-
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
570
|
-
style={{ left: `${width}px` }}
|
|
571
|
-
>
|
|
572
|
-
<div className="text-center max-w-md space-y-3">
|
|
573
|
-
<p className="text-muted-foreground font-bold">Headless Hook</p>
|
|
574
|
-
<p className="text-sm text-muted-foreground/80">
|
|
575
|
-
State managed by <code className="bg-muted px-1 rounded text-xs">useSidebar()</code>.
|
|
576
|
-
The entire UI is custom — no Sidebar component used.
|
|
577
|
-
</p>
|
|
578
|
-
<p className="text-xs text-muted-foreground">
|
|
579
|
-
Sidebar is currently: <strong>{expanded ? 'Expanded' : 'Collapsed'}</strong>
|
|
580
|
-
</p>
|
|
581
|
-
</div>
|
|
582
|
-
</div>
|
|
583
|
-
</div>
|
|
584
|
-
);
|
|
585
|
-
},
|
|
586
|
-
};
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Sidebar, useSidebar } from './sidebar';
|
|
3
|
+
import { useLayout } from '../../../contexts/LayoutContext';
|
|
4
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
5
|
+
import {
|
|
6
|
+
Home,
|
|
7
|
+
Users,
|
|
8
|
+
Settings,
|
|
9
|
+
BarChart,
|
|
10
|
+
Plus,
|
|
11
|
+
Clock,
|
|
12
|
+
FileEdit,
|
|
13
|
+
ArrowRightLeft,
|
|
14
|
+
PanelLeft,
|
|
15
|
+
Menu,
|
|
16
|
+
Trash2,
|
|
17
|
+
Map,
|
|
18
|
+
Archive,
|
|
19
|
+
} from 'lucide-react';
|
|
20
|
+
import React, { useState } from 'react';
|
|
21
|
+
import { Badge } from '../../ui/badge';
|
|
22
|
+
import { Button } from '../../ui/button';
|
|
23
|
+
import { Progress } from '../../ui/progress';
|
|
24
|
+
|
|
25
|
+
const meta: Meta<typeof Sidebar> = {
|
|
26
|
+
title: 'Layout/Sidebar',
|
|
27
|
+
component: Sidebar,
|
|
28
|
+
decorators: [
|
|
29
|
+
Story => (
|
|
30
|
+
<BrowserRouter>
|
|
31
|
+
<div className="flex h-screen w-full overflow-hidden bg-background">
|
|
32
|
+
<Story />
|
|
33
|
+
</div>
|
|
34
|
+
</BrowserRouter>
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
parameters: {
|
|
38
|
+
layout: 'fullscreen',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default meta;
|
|
43
|
+
type Story = StoryObj<typeof Sidebar>;
|
|
44
|
+
|
|
45
|
+
export const Default: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
variant: 'default',
|
|
48
|
+
expanded: false,
|
|
49
|
+
user: { email: 'admin@example.com' },
|
|
50
|
+
onLogout: () => console.log('Logged out'),
|
|
51
|
+
location: { pathname: '/home' },
|
|
52
|
+
routes: [
|
|
53
|
+
{ path: '/home', label: 'Home', icon: Home },
|
|
54
|
+
{ path: '/dashboard', label: 'Dashboard', icon: Users },
|
|
55
|
+
{ path: '/settings', label: 'Settings', icon: Settings },
|
|
56
|
+
],
|
|
57
|
+
footer: {
|
|
58
|
+
showUser: true,
|
|
59
|
+
showSettings: true,
|
|
60
|
+
showLogout: true,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
render: args => {
|
|
64
|
+
const { sidebarWidth: contextWidth } = useLayout();
|
|
65
|
+
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
66
|
+
|
|
67
|
+
// In Storybook, we match the sidebar widths (280 expanded, 80 collapsed)
|
|
68
|
+
const currentWidth = isExpanded ? 280 : 80;
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div
|
|
72
|
+
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
73
|
+
style={{ transform: 'translateZ(0)' }}
|
|
74
|
+
>
|
|
75
|
+
<Sidebar
|
|
76
|
+
{...args}
|
|
77
|
+
expanded={isExpanded}
|
|
78
|
+
onToggle={() => setIsExpanded(!isExpanded)}
|
|
79
|
+
width={currentWidth}
|
|
80
|
+
navigate={() => {}}
|
|
81
|
+
/>
|
|
82
|
+
<div
|
|
83
|
+
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
84
|
+
style={{ left: `${currentWidth}px` }}
|
|
85
|
+
>
|
|
86
|
+
<div className="text-center">
|
|
87
|
+
<p className="text-muted-foreground">Traditional System Navigation</p>
|
|
88
|
+
<p className="text-xs text-muted-foreground mt-2">Click on the menu icon to expand</p>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const DefaultWithGroups: Story = {
|
|
97
|
+
args: {
|
|
98
|
+
variant: 'default',
|
|
99
|
+
expanded: false,
|
|
100
|
+
user: { name: 'Admin', email: 'admin@example.com' },
|
|
101
|
+
onLogout: () => console.log('Logged out'),
|
|
102
|
+
location: { pathname: '/home' },
|
|
103
|
+
navigationGroups: [
|
|
104
|
+
{
|
|
105
|
+
id: 'main',
|
|
106
|
+
label: 'Principal',
|
|
107
|
+
items: [
|
|
108
|
+
{ path: '/home', label: 'Início', icon: Home },
|
|
109
|
+
{
|
|
110
|
+
path: '/dashboard',
|
|
111
|
+
label: 'Dashboard',
|
|
112
|
+
icon: BarChart,
|
|
113
|
+
children: [
|
|
114
|
+
{ path: '/dashboard/overview', label: 'Visão Geral', icon: BarChart },
|
|
115
|
+
{ path: '/dashboard/reports', label: 'Relatórios', icon: FileEdit },
|
|
116
|
+
{ path: '/dashboard/analytics', label: 'Analytics', icon: Map },
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'admin',
|
|
123
|
+
label: 'Administração',
|
|
124
|
+
items: [
|
|
125
|
+
{
|
|
126
|
+
path: '/users',
|
|
127
|
+
label: 'Usuários',
|
|
128
|
+
icon: Users,
|
|
129
|
+
children: [
|
|
130
|
+
{ path: '/users/list', label: 'Lista de Usuários', icon: Users },
|
|
131
|
+
{ path: '/users/roles', label: 'Perfis de Acesso', icon: Settings },
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
{ path: '/settings', label: 'Configurações', icon: Settings },
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
footer: {
|
|
139
|
+
showUser: true,
|
|
140
|
+
showSettings: false,
|
|
141
|
+
showLogout: true,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
render: args => {
|
|
145
|
+
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
146
|
+
const currentWidth = isExpanded ? 280 : 80;
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<div
|
|
150
|
+
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
151
|
+
style={{ transform: 'translateZ(0)' }}
|
|
152
|
+
>
|
|
153
|
+
<Sidebar
|
|
154
|
+
{...args}
|
|
155
|
+
expanded={isExpanded}
|
|
156
|
+
onToggle={() => setIsExpanded(!isExpanded)}
|
|
157
|
+
width={currentWidth}
|
|
158
|
+
navigate={() => {}}
|
|
159
|
+
/>
|
|
160
|
+
<div
|
|
161
|
+
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
162
|
+
style={{ left: `${currentWidth}px` }}
|
|
163
|
+
>
|
|
164
|
+
<div className="text-center">
|
|
165
|
+
<p className="text-muted-foreground">Navigation with Groups and Children</p>
|
|
166
|
+
<p className="text-xs text-muted-foreground mt-2">
|
|
167
|
+
Expand and click the arrow button on items to see sub-menus
|
|
168
|
+
</p>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
);
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export const Assistant: Story = {
|
|
177
|
+
args: {
|
|
178
|
+
variant: 'assistant',
|
|
179
|
+
expanded: false,
|
|
180
|
+
user: { email: 'admin@example.com' },
|
|
181
|
+
onLogout: () => console.log('Logged out'),
|
|
182
|
+
location: { pathname: '/assistant/refatoracao' },
|
|
183
|
+
search: {
|
|
184
|
+
show: true,
|
|
185
|
+
placeholder: 'Buscar tópicos...',
|
|
186
|
+
filter: {
|
|
187
|
+
show: true,
|
|
188
|
+
content: (
|
|
189
|
+
<div className="p-2 space-y-2">
|
|
190
|
+
<div className="text-xs font-semibold uppercase text-muted-foreground px-2 text-left">
|
|
191
|
+
Filter by Status
|
|
192
|
+
</div>
|
|
193
|
+
<div className="flex flex-wrap gap-2 p-1">
|
|
194
|
+
<Badge className="bg-sidebar-foreground/20 text-sidebar-foreground border-none cursor-pointer hover:bg-sidebar-foreground/30">
|
|
195
|
+
Active
|
|
196
|
+
</Badge>
|
|
197
|
+
<Badge
|
|
198
|
+
variant="outline"
|
|
199
|
+
className="text-sidebar-foreground/70 border-sidebar-foreground/20 cursor-pointer hover:bg-sidebar-foreground/10"
|
|
200
|
+
>
|
|
201
|
+
Archived
|
|
202
|
+
</Badge>
|
|
203
|
+
<Badge
|
|
204
|
+
variant="outline"
|
|
205
|
+
className="text-sidebar-foreground/70 border-sidebar-foreground/20 cursor-pointer hover:bg-sidebar-foreground/10"
|
|
206
|
+
>
|
|
207
|
+
Pending
|
|
208
|
+
</Badge>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
),
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
fixedArea: {
|
|
215
|
+
show: true,
|
|
216
|
+
icon: Plus,
|
|
217
|
+
onClick: () => console.log('New Conversation clicked'),
|
|
218
|
+
content: (
|
|
219
|
+
<Button className="w-full bg-sidebar-primary hover:bg-sidebar-primary/90 text-sidebar-primary-foreground shadow-lg font-bold border-none transition-all duration-300 transform hover:scale-[1.02] active:scale-[0.98]">
|
|
220
|
+
<Plus className="w-4 h-4 mr-2" />
|
|
221
|
+
New Conversation
|
|
222
|
+
</Button>
|
|
223
|
+
),
|
|
224
|
+
},
|
|
225
|
+
navigationGroups: [
|
|
226
|
+
{
|
|
227
|
+
id: 'recent',
|
|
228
|
+
label: 'Recent',
|
|
229
|
+
icon: Clock,
|
|
230
|
+
items: [
|
|
231
|
+
{
|
|
232
|
+
path: '/assistant/refatoracao',
|
|
233
|
+
label: 'Edit Sidebar',
|
|
234
|
+
description: 'Active now',
|
|
235
|
+
actions: [
|
|
236
|
+
{ label: 'Rename', icon: FileEdit, onClick: () => console.log('Open rename...') },
|
|
237
|
+
{
|
|
238
|
+
label: 'Move',
|
|
239
|
+
icon: ArrowRightLeft,
|
|
240
|
+
children: [
|
|
241
|
+
{
|
|
242
|
+
label: 'Active Projects',
|
|
243
|
+
onClick: () => console.log('Moved to Active Projects'),
|
|
244
|
+
},
|
|
245
|
+
{ label: 'Monitoring', onClick: () => console.log('Moved to Monitoring') },
|
|
246
|
+
{ label: 'Archive', onClick: () => console.log('Moved to Archive') },
|
|
247
|
+
],
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
label: 'Clear',
|
|
251
|
+
icon: Trash2,
|
|
252
|
+
onClick: () => console.log('History Cleared!'),
|
|
253
|
+
variant: 'destructive',
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
id: 'projects',
|
|
261
|
+
label: 'Project Monitoring',
|
|
262
|
+
icon: Map,
|
|
263
|
+
actions: [
|
|
264
|
+
{
|
|
265
|
+
label: 'New Category',
|
|
266
|
+
icon: Plus,
|
|
267
|
+
onClick: () => console.log('Create new category...'),
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
label: 'Archive Group',
|
|
271
|
+
icon: Archive,
|
|
272
|
+
onClick: () => console.log('Archiving group...'),
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
items: [
|
|
276
|
+
{
|
|
277
|
+
path: '/assistant/br163',
|
|
278
|
+
label: 'Panel Status',
|
|
279
|
+
icon: () => <div className="w-2 h-2 rounded-full bg-yellow-500" />,
|
|
280
|
+
description: (
|
|
281
|
+
<div className="space-y-1.5 min-w-[160px]">
|
|
282
|
+
<Progress value={67} className="h-1.5 bg-sidebar-foreground/10" />
|
|
283
|
+
<div className="flex justify-between items-center text-[10px] text-sidebar-foreground/60">
|
|
284
|
+
<span>Label</span>
|
|
285
|
+
<span>67%</span>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
),
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
render: args => {
|
|
295
|
+
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
296
|
+
const currentWidth = isExpanded ? 280 : 80;
|
|
297
|
+
|
|
298
|
+
return (
|
|
299
|
+
<div
|
|
300
|
+
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
301
|
+
style={{ transform: 'translateZ(0)' }}
|
|
302
|
+
>
|
|
303
|
+
<Sidebar
|
|
304
|
+
{...args}
|
|
305
|
+
expanded={isExpanded}
|
|
306
|
+
onToggle={() => setIsExpanded(!isExpanded)}
|
|
307
|
+
width={currentWidth}
|
|
308
|
+
navigate={() => {}}
|
|
309
|
+
/>
|
|
310
|
+
<div
|
|
311
|
+
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
312
|
+
style={{ left: `${currentWidth}px` }}
|
|
313
|
+
>
|
|
314
|
+
<div className="text-center">
|
|
315
|
+
<p className="text-muted-foreground">Assistant Mode Content</p>
|
|
316
|
+
<p className="text-xs text-muted-foreground mt-2">Click on the menu icon to expand</p>
|
|
317
|
+
</div>
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
);
|
|
321
|
+
},
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
export const Collapsed: Story = {
|
|
325
|
+
args: {
|
|
326
|
+
...Default.args,
|
|
327
|
+
expanded: false,
|
|
328
|
+
},
|
|
329
|
+
render: args => {
|
|
330
|
+
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
331
|
+
const currentWidth = isExpanded ? 280 : 80;
|
|
332
|
+
|
|
333
|
+
return (
|
|
334
|
+
<div
|
|
335
|
+
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
336
|
+
style={{ transform: 'translateZ(0)' }}
|
|
337
|
+
>
|
|
338
|
+
<Sidebar
|
|
339
|
+
{...args}
|
|
340
|
+
expanded={isExpanded}
|
|
341
|
+
onToggle={() => setIsExpanded(!isExpanded)}
|
|
342
|
+
width={currentWidth}
|
|
343
|
+
navigate={() => {}}
|
|
344
|
+
/>
|
|
345
|
+
<div
|
|
346
|
+
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
347
|
+
style={{ left: `${currentWidth}px` }}
|
|
348
|
+
>
|
|
349
|
+
<div className="text-center">
|
|
350
|
+
<p className="text-muted-foreground">Compact Navigation</p>
|
|
351
|
+
<p className="text-xs text-muted-foreground mt-2">Click on the menu icon to expand</p>
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
);
|
|
356
|
+
},
|
|
357
|
+
};
|
|
358
|
+
export const NoFooter: Story = {
|
|
359
|
+
args: {
|
|
360
|
+
...Default.args,
|
|
361
|
+
showFooter: false,
|
|
362
|
+
},
|
|
363
|
+
render: args => {
|
|
364
|
+
const [isExpanded, setIsExpanded] = useState(args.expanded);
|
|
365
|
+
const currentWidth = isExpanded ? 280 : 80;
|
|
366
|
+
|
|
367
|
+
return (
|
|
368
|
+
<div
|
|
369
|
+
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
370
|
+
style={{ transform: 'translateZ(0)' }}
|
|
371
|
+
>
|
|
372
|
+
<Sidebar
|
|
373
|
+
{...args}
|
|
374
|
+
expanded={isExpanded}
|
|
375
|
+
onToggle={() => setIsExpanded(!isExpanded)}
|
|
376
|
+
width={currentWidth}
|
|
377
|
+
navigate={() => {}}
|
|
378
|
+
/>
|
|
379
|
+
<div
|
|
380
|
+
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
381
|
+
style={{ left: `${currentWidth}px` }}
|
|
382
|
+
>
|
|
383
|
+
<div className="text-center">
|
|
384
|
+
<p className="text-muted-foreground">Sidebar without Footer</p>
|
|
385
|
+
<p className="text-xs text-muted-foreground mt-2">Click on the menu icon to expand</p>
|
|
386
|
+
</div>
|
|
387
|
+
</div>
|
|
388
|
+
</div>
|
|
389
|
+
);
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
export const Autonomous: Story = {
|
|
394
|
+
args: {
|
|
395
|
+
...Default.args,
|
|
396
|
+
expanded: undefined,
|
|
397
|
+
onToggle: undefined,
|
|
398
|
+
},
|
|
399
|
+
render: args => {
|
|
400
|
+
return (
|
|
401
|
+
<div
|
|
402
|
+
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
403
|
+
style={{ transform: 'translateZ(0)' }}
|
|
404
|
+
>
|
|
405
|
+
<Sidebar {...args} />
|
|
406
|
+
<div
|
|
407
|
+
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
408
|
+
style={{ left: `80px` }}
|
|
409
|
+
>
|
|
410
|
+
<div className="text-center max-w-md">
|
|
411
|
+
<p className="text-muted-foreground font-bold">Autonomous Sidebar</p>
|
|
412
|
+
<p className="text-sm text-muted-foreground/80 mt-2">
|
|
413
|
+
This instance is managing its own state internally. No `expanded` or `onToggle` props
|
|
414
|
+
are passed.
|
|
415
|
+
</p>
|
|
416
|
+
<p className="text-xs text-muted-foreground mt-4">
|
|
417
|
+
Note: Layout coordination (content padding) must be handled manually when using
|
|
418
|
+
autonomous mode without LayoutProvider.
|
|
419
|
+
</p>
|
|
420
|
+
</div>
|
|
421
|
+
</div>
|
|
422
|
+
</div>
|
|
423
|
+
);
|
|
424
|
+
},
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Compound Component API — demonstrates using Sidebar.Root + sub-components
|
|
429
|
+
* for full layout control. This is the recommended pattern for advanced
|
|
430
|
+
* customization without forking the component.
|
|
431
|
+
*/
|
|
432
|
+
export const CompoundComponentAPI: Story = {
|
|
433
|
+
name: 'Compound Component API',
|
|
434
|
+
render: () => {
|
|
435
|
+
const [isExpanded, setIsExpanded] = React.useState(true);
|
|
436
|
+
const currentWidth = isExpanded ? 280 : 80;
|
|
437
|
+
const groups = [
|
|
438
|
+
{
|
|
439
|
+
id: 'main',
|
|
440
|
+
label: 'Principal',
|
|
441
|
+
items: [
|
|
442
|
+
{ path: '/home', label: 'Início', icon: Home },
|
|
443
|
+
{ path: '/dashboard', label: 'Dashboard', icon: BarChart },
|
|
444
|
+
],
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
id: 'admin',
|
|
448
|
+
label: 'Administração',
|
|
449
|
+
items: [
|
|
450
|
+
{ path: '/users', label: 'Usuários', icon: Users },
|
|
451
|
+
{ path: '/settings', label: 'Configurações', icon: Settings },
|
|
452
|
+
],
|
|
453
|
+
},
|
|
454
|
+
];
|
|
455
|
+
|
|
456
|
+
return (
|
|
457
|
+
<div
|
|
458
|
+
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
459
|
+
style={{ transform: 'translateZ(0)' }}
|
|
460
|
+
>
|
|
461
|
+
{/* Compound Component usage */}
|
|
462
|
+
<Sidebar.Root
|
|
463
|
+
expanded={isExpanded}
|
|
464
|
+
onToggle={() => setIsExpanded(prev => !prev)}
|
|
465
|
+
width={currentWidth}
|
|
466
|
+
location={{ pathname: '/home' }}
|
|
467
|
+
navigate={() => {}}
|
|
468
|
+
>
|
|
469
|
+
<Sidebar.Header />
|
|
470
|
+
<Sidebar.Nav navigationGroups={groups} />
|
|
471
|
+
<Sidebar.Footer
|
|
472
|
+
user={{ name: 'Admin', email: 'admin@example.com' }}
|
|
473
|
+
onLogout={() => console.log('logout')}
|
|
474
|
+
showUser
|
|
475
|
+
showSettings
|
|
476
|
+
showLogout
|
|
477
|
+
/>
|
|
478
|
+
</Sidebar.Root>
|
|
479
|
+
|
|
480
|
+
<div
|
|
481
|
+
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
482
|
+
style={{ left: `${currentWidth}px` }}
|
|
483
|
+
>
|
|
484
|
+
<div className="text-center max-w-md space-y-3">
|
|
485
|
+
<p className="text-muted-foreground font-bold">Compound Component API</p>
|
|
486
|
+
<p className="text-sm text-muted-foreground/80">
|
|
487
|
+
Built with <code className="bg-muted px-1 rounded text-xs"><Sidebar.Root></code>
|
|
488
|
+
, <code className="bg-muted px-1 rounded text-xs"><Sidebar.Header></code>,{' '}
|
|
489
|
+
<code className="bg-muted px-1 rounded text-xs"><Sidebar.Nav></code>, and{' '}
|
|
490
|
+
<code className="bg-muted px-1 rounded text-xs"><Sidebar.Footer></code>.
|
|
491
|
+
</p>
|
|
492
|
+
<p className="text-xs text-muted-foreground">
|
|
493
|
+
Each sub-component reads shared state from{' '}
|
|
494
|
+
<code className="bg-muted px-1 rounded text-xs">SidebarContext</code> via{' '}
|
|
495
|
+
<code className="bg-muted px-1 rounded text-xs">Sidebar.Root</code>.
|
|
496
|
+
</p>
|
|
497
|
+
</div>
|
|
498
|
+
</div>
|
|
499
|
+
</div>
|
|
500
|
+
);
|
|
501
|
+
},
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Headless Hook — demonstrates using `useSidebar` directly for fully custom rendering.
|
|
506
|
+
* The hook manages all state; the UI is entirely up to the consumer.
|
|
507
|
+
*/
|
|
508
|
+
export const HeadlessHook: Story = {
|
|
509
|
+
name: 'Headless Hook (useSidebar)',
|
|
510
|
+
render: () => {
|
|
511
|
+
const groups = [
|
|
512
|
+
{
|
|
513
|
+
id: 'main',
|
|
514
|
+
label: 'Principal',
|
|
515
|
+
items: [
|
|
516
|
+
{ path: '/home', label: 'Início', icon: Home },
|
|
517
|
+
{ path: '/dashboard', label: 'Dashboard', icon: BarChart },
|
|
518
|
+
{ path: '/users', label: 'Usuários', icon: Users },
|
|
519
|
+
],
|
|
520
|
+
},
|
|
521
|
+
];
|
|
522
|
+
|
|
523
|
+
const {
|
|
524
|
+
expanded,
|
|
525
|
+
toggleExpanded,
|
|
526
|
+
navigationGroups: resolvedGroups,
|
|
527
|
+
} = useSidebar({ defaultExpanded: true, navigationGroups: groups });
|
|
528
|
+
|
|
529
|
+
const width = expanded ? 280 : 80;
|
|
530
|
+
|
|
531
|
+
return (
|
|
532
|
+
<div
|
|
533
|
+
className="relative h-screen w-full border rounded-[var(--radius-lg)] bg-muted/20 overflow-hidden"
|
|
534
|
+
style={{ transform: 'translateZ(0)' }}
|
|
535
|
+
>
|
|
536
|
+
{/* Fully custom sidebar built with useSidebar hook */}
|
|
537
|
+
<div
|
|
538
|
+
className="absolute inset-y-0 left-0 bg-sidebar text-sidebar-foreground flex flex-col transition-all duration-300 z-50"
|
|
539
|
+
style={{ width: `${width}px` }}
|
|
540
|
+
>
|
|
541
|
+
<div className="p-4">
|
|
542
|
+
<button
|
|
543
|
+
onClick={toggleExpanded}
|
|
544
|
+
className="w-full h-10 flex items-center justify-center rounded-md bg-sidebar-foreground/10 hover:bg-sidebar-foreground/20 text-sidebar-foreground transition-colors"
|
|
545
|
+
aria-label={expanded ? 'Collapse' : 'Expand'}
|
|
546
|
+
>
|
|
547
|
+
{expanded ? <PanelLeft className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
|
|
548
|
+
</button>
|
|
549
|
+
</div>
|
|
550
|
+
<nav className="flex-1 px-3 space-y-1">
|
|
551
|
+
{resolvedGroups
|
|
552
|
+
.flatMap(g => g.items)
|
|
553
|
+
.map(item => {
|
|
554
|
+
const Icon = item.icon;
|
|
555
|
+
return (
|
|
556
|
+
<button
|
|
557
|
+
key={item.path}
|
|
558
|
+
className="w-full h-10 flex items-center gap-3 px-3 rounded-md text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground transition-colors"
|
|
559
|
+
>
|
|
560
|
+
{Icon && <Icon className="w-5 h-5 flex-shrink-0" />}
|
|
561
|
+
{expanded && <span className="truncate text-sm">{item.label}</span>}
|
|
562
|
+
</button>
|
|
563
|
+
);
|
|
564
|
+
})}
|
|
565
|
+
</nav>
|
|
566
|
+
</div>
|
|
567
|
+
|
|
568
|
+
<div
|
|
569
|
+
className="absolute inset-y-0 right-0 p-8 flex items-center justify-center transition-all duration-300"
|
|
570
|
+
style={{ left: `${width}px` }}
|
|
571
|
+
>
|
|
572
|
+
<div className="text-center max-w-md space-y-3">
|
|
573
|
+
<p className="text-muted-foreground font-bold">Headless Hook</p>
|
|
574
|
+
<p className="text-sm text-muted-foreground/80">
|
|
575
|
+
State managed by <code className="bg-muted px-1 rounded text-xs">useSidebar()</code>.
|
|
576
|
+
The entire UI is custom — no Sidebar component used.
|
|
577
|
+
</p>
|
|
578
|
+
<p className="text-xs text-muted-foreground">
|
|
579
|
+
Sidebar is currently: <strong>{expanded ? 'Expanded' : 'Collapsed'}</strong>
|
|
580
|
+
</p>
|
|
581
|
+
</div>
|
|
582
|
+
</div>
|
|
583
|
+
</div>
|
|
584
|
+
);
|
|
585
|
+
},
|
|
586
|
+
};
|