sonance-brand-mcp 1.2.4 → 1.3.1

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 (90) hide show
  1. package/dist/assets/components/alert-dialog.stories.tsx +142 -0
  2. package/dist/assets/components/alert-dialog.tsx +142 -0
  3. package/dist/assets/components/aspect-ratio.stories.tsx +67 -0
  4. package/dist/assets/components/aspect-ratio.tsx +8 -0
  5. package/dist/assets/components/avatar.tsx +64 -20
  6. package/dist/assets/components/carousel.stories.tsx +158 -0
  7. package/dist/assets/components/carousel.tsx +262 -0
  8. package/dist/assets/components/chart.stories.tsx +376 -0
  9. package/dist/assets/components/chart.tsx +384 -0
  10. package/dist/assets/components/checkbox.tsx +12 -2
  11. package/dist/assets/components/code.tsx +22 -20
  12. package/dist/assets/components/collapsible.stories.tsx +128 -0
  13. package/dist/assets/components/collapsible.tsx +10 -0
  14. package/dist/assets/components/command.stories.tsx +183 -0
  15. package/dist/assets/components/command.tsx +170 -0
  16. package/dist/assets/components/context-menu.stories.tsx +159 -0
  17. package/dist/assets/components/context-menu.tsx +218 -0
  18. package/dist/assets/components/divider.tsx +38 -35
  19. package/dist/assets/components/dropdown-menu.tsx +217 -0
  20. package/dist/assets/components/hover-card.stories.tsx +113 -0
  21. package/dist/assets/components/hover-card.tsx +35 -0
  22. package/dist/assets/components/kbd.tsx +6 -6
  23. package/dist/assets/components/menubar.stories.tsx +208 -0
  24. package/dist/assets/components/menubar.tsx +251 -0
  25. package/dist/assets/components/navigation-menu.stories.tsx +237 -0
  26. package/dist/assets/components/navigation-menu.tsx +135 -0
  27. package/dist/assets/components/resizable.stories.tsx +197 -0
  28. package/dist/assets/components/resizable.tsx +47 -0
  29. package/dist/assets/components/scroll-area.stories.tsx +123 -0
  30. package/dist/assets/components/scroll-area.tsx +48 -0
  31. package/dist/assets/components/scroll-shadow.tsx +29 -7
  32. package/dist/assets/components/separator.tsx +32 -0
  33. package/dist/assets/components/sheet.tsx +141 -0
  34. package/dist/assets/components/sidebar.stories.tsx +351 -0
  35. package/dist/assets/components/sidebar.tsx +760 -0
  36. package/dist/assets/components/toggle-group.stories.tsx +153 -0
  37. package/dist/assets/components/toggle-group.tsx +61 -0
  38. package/dist/assets/components/toggle.stories.tsx +77 -0
  39. package/dist/assets/components/toggle.tsx +46 -0
  40. package/dist/assets/components/tooltip.tsx +23 -90
  41. package/dist/assets/globals.css +30 -0
  42. package/dist/assets/logos/40th-anniversary/Sonance_40_Logo_CMYK_BEAM_BLUE_40_AND_BEAM_DARK.png +0 -0
  43. package/dist/assets/logos/Sonance logo dark mode.png +0 -0
  44. package/dist/assets/logos/Sonance logo light mode.png +0 -0
  45. package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_2C_Light_RGB_05162025.png +0 -0
  46. package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_3C_Dark_RGB_05162025.png +0 -0
  47. package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_White_RGB_05162025.png +0 -0
  48. package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Dark_RGB.png +0 -0
  49. package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Light_RGB.png +0 -0
  50. package/dist/assets/logos/james/James_Logo_Black_CMYK.png +0 -0
  51. package/dist/assets/logos/james/James_Logo_Black_RGB.png +0 -0
  52. package/dist/assets/logos/james/James_Logo_LtGray_CMYK.png +0 -0
  53. package/dist/assets/logos/james/James_Logo_LtGray_RGB.png +0 -0
  54. package/dist/assets/logos/james/James_Logo_Polished_RGB.png +0 -0
  55. package/dist/assets/logos/james/James_Logo_Reverse_CMYK.png +0 -0
  56. package/dist/assets/logos/james/James_Logo_Reverse_RGB.png +0 -0
  57. package/dist/assets/logos/james/James_Logo_White_CMYK.png +0 -0
  58. package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Dark_RGB.png +0 -0
  59. package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Light_RGB.png +0 -0
  60. package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Dark_RGB.png +0 -0
  61. package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Light_RGB.png +0 -0
  62. package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Reverse_RGB.png +0 -0
  63. package/dist/assets/logos/my-sonance/My.Sonance_Logo_Black_RGB.png +0 -0
  64. package/dist/assets/logos/my-sonance/My.Sonance_Logo_Reverse_RGB.png +0 -0
  65. package/dist/assets/logos/sonance/Sonance_Logo_2C_Dark_RGB.png +0 -0
  66. package/dist/assets/logos/sonance/Sonance_Logo_2C_Light_RGB.png +0 -0
  67. package/dist/assets/logos/sonance/Sonance_Logo_2C_Reverse_RGB.png +0 -0
  68. package/dist/assets/logos/sonance/Sonance_Logo_Black_RGB.png +0 -0
  69. package/dist/assets/logos/sonance/Sonance_Logo_Grayscale_RGB.png +0 -0
  70. package/dist/assets/logos/sonance/Sonance_Logo_Reverse_RGB.png +0 -0
  71. package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Dark_CMYK.png +0 -0
  72. package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Light_CMYK.png +0 -0
  73. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Dark_RGB.png +0 -0
  74. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Light_RGB.png +0 -0
  75. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Reverse_RGB.png +0 -0
  76. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Black_RGB.png +0 -0
  77. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Grayscale_RGB.png +0 -0
  78. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Reverse_RGB.png +0 -0
  79. package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Dark.png +0 -0
  80. package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Light.png +0 -0
  81. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Dark.png +0 -0
  82. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Light.png +0 -0
  83. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Dark.png +0 -0
  84. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Light.png +0 -0
  85. package/dist/assets/logos/trufig/TrufigLogo_Black.png +0 -0
  86. package/dist/assets/logos/trufig/TrufigLogo_Light.png +0 -0
  87. package/dist/assets/logos/trufig/TrufigWatermark_Black.png +0 -0
  88. package/dist/assets/logos/trufig/TrufigWatermark_Light.png +0 -0
  89. package/dist/index.js +416 -17
  90. package/package.json +1 -1
@@ -0,0 +1,237 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import {
3
+ NavigationMenu,
4
+ NavigationMenuContent,
5
+ NavigationMenuItem,
6
+ NavigationMenuLink,
7
+ NavigationMenuList,
8
+ NavigationMenuTrigger,
9
+ navigationMenuTriggerStyle,
10
+ } from "./navigation-menu";
11
+ import { cn } from "@/lib/utils";
12
+ import React from "react";
13
+
14
+ const meta: Meta<typeof NavigationMenu> = {
15
+ title: "Components/Navigation/NavigationMenu",
16
+ component: NavigationMenu,
17
+ parameters: {
18
+ layout: "centered",
19
+ },
20
+ tags: ["autodocs"],
21
+ };
22
+
23
+ export default meta;
24
+ type Story = StoryObj<typeof NavigationMenu>;
25
+
26
+ const components: { title: string; href: string; description: string }[] = [
27
+ {
28
+ title: "Alert Dialog",
29
+ href: "#",
30
+ description:
31
+ "A modal dialog that interrupts the user with important content and expects a response.",
32
+ },
33
+ {
34
+ title: "Hover Card",
35
+ href: "#",
36
+ description:
37
+ "For sighted users to preview content available behind a link.",
38
+ },
39
+ {
40
+ title: "Progress",
41
+ href: "#",
42
+ description:
43
+ "Displays an indicator showing the completion progress of a task.",
44
+ },
45
+ {
46
+ title: "Scroll Area",
47
+ href: "#",
48
+ description: "Visually or semantically separates content.",
49
+ },
50
+ {
51
+ title: "Tabs",
52
+ href: "#",
53
+ description:
54
+ "A set of layered sections of content—known as tab panels.",
55
+ },
56
+ {
57
+ title: "Tooltip",
58
+ href: "#",
59
+ description:
60
+ "A popup that displays information related to an element.",
61
+ },
62
+ ];
63
+
64
+ const ListItem = React.forwardRef<
65
+ React.ElementRef<"a">,
66
+ React.ComponentPropsWithoutRef<"a">
67
+ >(({ className, title, children, ...props }, ref) => {
68
+ return (
69
+ <li>
70
+ <NavigationMenuLink asChild>
71
+ <a
72
+ ref={ref}
73
+ className={cn(
74
+ "block select-none space-y-1 rounded-sm p-3 leading-none no-underline outline-none transition-colors hover:bg-secondary-hover hover:text-foreground focus:bg-secondary-hover focus:text-foreground",
75
+ className
76
+ )}
77
+ {...props}
78
+ >
79
+ <div className="text-sm font-medium leading-none">{title}</div>
80
+ <p className="line-clamp-2 text-sm leading-snug text-foreground-muted">
81
+ {children}
82
+ </p>
83
+ </a>
84
+ </NavigationMenuLink>
85
+ </li>
86
+ );
87
+ });
88
+ ListItem.displayName = "ListItem";
89
+
90
+ export const Default: Story = {
91
+ render: () => (
92
+ <NavigationMenu>
93
+ <NavigationMenuList>
94
+ <NavigationMenuItem>
95
+ <NavigationMenuTrigger>Getting started</NavigationMenuTrigger>
96
+ <NavigationMenuContent>
97
+ <ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
98
+ <li className="row-span-3">
99
+ <NavigationMenuLink asChild>
100
+ <a
101
+ className="flex h-full w-full select-none flex-col justify-end rounded-sm bg-gradient-to-b from-secondary-hover/50 to-secondary-hover p-6 no-underline outline-none focus:shadow-md"
102
+ href="#"
103
+ >
104
+ <div className="mb-2 mt-4 text-lg font-medium">
105
+ Sonance
106
+ </div>
107
+ <p className="text-sm leading-tight text-foreground-muted">
108
+ Premium architectural speakers and outdoor audio solutions.
109
+ </p>
110
+ </a>
111
+ </NavigationMenuLink>
112
+ </li>
113
+ <ListItem href="#" title="Introduction">
114
+ Learn about the Sonance brand and our commitment to audio excellence.
115
+ </ListItem>
116
+ <ListItem href="#" title="Installation">
117
+ How to get started with your Sonance audio system.
118
+ </ListItem>
119
+ <ListItem href="#" title="Support">
120
+ Find answers and get help from our team.
121
+ </ListItem>
122
+ </ul>
123
+ </NavigationMenuContent>
124
+ </NavigationMenuItem>
125
+ <NavigationMenuItem>
126
+ <NavigationMenuTrigger>Components</NavigationMenuTrigger>
127
+ <NavigationMenuContent>
128
+ <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
129
+ {components.map((component) => (
130
+ <ListItem
131
+ key={component.title}
132
+ title={component.title}
133
+ href={component.href}
134
+ >
135
+ {component.description}
136
+ </ListItem>
137
+ ))}
138
+ </ul>
139
+ </NavigationMenuContent>
140
+ </NavigationMenuItem>
141
+ <NavigationMenuItem>
142
+ <a href="#">
143
+ <NavigationMenuLink className={navigationMenuTriggerStyle()}>
144
+ Documentation
145
+ </NavigationMenuLink>
146
+ </a>
147
+ </NavigationMenuItem>
148
+ </NavigationMenuList>
149
+ </NavigationMenu>
150
+ ),
151
+ };
152
+
153
+ export const Simple: Story = {
154
+ render: () => (
155
+ <NavigationMenu>
156
+ <NavigationMenuList>
157
+ <NavigationMenuItem>
158
+ <a href="#">
159
+ <NavigationMenuLink className={navigationMenuTriggerStyle()}>
160
+ Products
161
+ </NavigationMenuLink>
162
+ </a>
163
+ </NavigationMenuItem>
164
+ <NavigationMenuItem>
165
+ <a href="#">
166
+ <NavigationMenuLink className={navigationMenuTriggerStyle()}>
167
+ Solutions
168
+ </NavigationMenuLink>
169
+ </a>
170
+ </NavigationMenuItem>
171
+ <NavigationMenuItem>
172
+ <a href="#">
173
+ <NavigationMenuLink className={navigationMenuTriggerStyle()}>
174
+ Support
175
+ </NavigationMenuLink>
176
+ </a>
177
+ </NavigationMenuItem>
178
+ <NavigationMenuItem>
179
+ <a href="#">
180
+ <NavigationMenuLink className={navigationMenuTriggerStyle()}>
181
+ About
182
+ </NavigationMenuLink>
183
+ </a>
184
+ </NavigationMenuItem>
185
+ </NavigationMenuList>
186
+ </NavigationMenu>
187
+ ),
188
+ };
189
+
190
+ export const ProductsMenu: Story = {
191
+ render: () => (
192
+ <NavigationMenu>
193
+ <NavigationMenuList>
194
+ <NavigationMenuItem>
195
+ <NavigationMenuTrigger>Architectural</NavigationMenuTrigger>
196
+ <NavigationMenuContent>
197
+ <ul className="grid gap-3 p-4 w-[400px]">
198
+ <ListItem href="#" title="In-Ceiling Speakers">
199
+ Invisible audio solutions for residential and commercial spaces.
200
+ </ListItem>
201
+ <ListItem href="#" title="In-Wall Speakers">
202
+ Seamless integration into any wall surface.
203
+ </ListItem>
204
+ <ListItem href="#" title="Invisible Series">
205
+ Completely hidden speakers that disappear into your walls.
206
+ </ListItem>
207
+ </ul>
208
+ </NavigationMenuContent>
209
+ </NavigationMenuItem>
210
+ <NavigationMenuItem>
211
+ <NavigationMenuTrigger>Outdoor</NavigationMenuTrigger>
212
+ <NavigationMenuContent>
213
+ <ul className="grid gap-3 p-4 w-[400px]">
214
+ <ListItem href="#" title="Landscape Series">
215
+ Outdoor speakers designed to blend into your garden.
216
+ </ListItem>
217
+ <ListItem href="#" title="Patio Series">
218
+ Weather-resistant speakers for covered outdoor areas.
219
+ </ListItem>
220
+ <ListItem href="#" title="Subwoofers">
221
+ Powerful bass for your outdoor entertainment.
222
+ </ListItem>
223
+ </ul>
224
+ </NavigationMenuContent>
225
+ </NavigationMenuItem>
226
+ <NavigationMenuItem>
227
+ <a href="#">
228
+ <NavigationMenuLink className={navigationMenuTriggerStyle()}>
229
+ View All
230
+ </NavigationMenuLink>
231
+ </a>
232
+ </NavigationMenuItem>
233
+ </NavigationMenuList>
234
+ </NavigationMenu>
235
+ ),
236
+ };
237
+
@@ -0,0 +1,135 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
5
+ import { ChevronDown } from "lucide-react";
6
+ import { cva } from "class-variance-authority";
7
+ import { cn } from "@/lib/utils";
8
+
9
+ const NavigationMenu = React.forwardRef<
10
+ React.ElementRef<typeof NavigationMenuPrimitive.Root>,
11
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
12
+ >(({ className, children, ...props }, ref) => (
13
+ <NavigationMenuPrimitive.Root
14
+ ref={ref}
15
+ className={cn(
16
+ "relative z-10 flex max-w-max flex-1 items-center justify-center",
17
+ className
18
+ )}
19
+ {...props}
20
+ >
21
+ {children}
22
+ <NavigationMenuViewport />
23
+ </NavigationMenuPrimitive.Root>
24
+ ));
25
+ NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
26
+
27
+ const NavigationMenuList = React.forwardRef<
28
+ React.ElementRef<typeof NavigationMenuPrimitive.List>,
29
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
30
+ >(({ className, ...props }, ref) => (
31
+ <NavigationMenuPrimitive.List
32
+ ref={ref}
33
+ className={cn(
34
+ "group flex flex-1 list-none items-center justify-center space-x-1",
35
+ className
36
+ )}
37
+ {...props}
38
+ />
39
+ ));
40
+ NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
41
+
42
+ const NavigationMenuItem = NavigationMenuPrimitive.Item;
43
+
44
+ const navigationMenuTriggerStyle = cva(
45
+ "group inline-flex h-10 w-max items-center justify-center rounded-sm bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-secondary-hover hover:text-foreground focus:bg-secondary-hover focus:text-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-secondary-hover/50 data-[state=open]:bg-secondary-hover/50"
46
+ );
47
+
48
+ const NavigationMenuTrigger = React.forwardRef<
49
+ React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
50
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
51
+ >(({ className, children, ...props }, ref) => (
52
+ <NavigationMenuPrimitive.Trigger
53
+ ref={ref}
54
+ className={cn(navigationMenuTriggerStyle(), "group", className)}
55
+ {...props}
56
+ >
57
+ {children}{" "}
58
+ <ChevronDown
59
+ className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180"
60
+ aria-hidden="true"
61
+ />
62
+ </NavigationMenuPrimitive.Trigger>
63
+ ));
64
+ NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
65
+
66
+ const NavigationMenuContent = React.forwardRef<
67
+ React.ElementRef<typeof NavigationMenuPrimitive.Content>,
68
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
69
+ >(({ className, ...props }, ref) => (
70
+ <NavigationMenuPrimitive.Content
71
+ ref={ref}
72
+ className={cn(
73
+ "left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto",
74
+ className
75
+ )}
76
+ {...props}
77
+ />
78
+ ));
79
+ NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
80
+
81
+ const NavigationMenuLink = NavigationMenuPrimitive.Link;
82
+
83
+ const NavigationMenuViewport = React.forwardRef<
84
+ React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
85
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
86
+ >(({ className, ...props }, ref) => (
87
+ <div className={cn("absolute left-0 top-full flex justify-center")}>
88
+ <NavigationMenuPrimitive.Viewport
89
+ className={cn(
90
+ "origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-sm border border-border bg-card text-foreground shadow-lg",
91
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
92
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90",
93
+ "md:w-[var(--radix-navigation-menu-viewport-width)]",
94
+ className
95
+ )}
96
+ ref={ref}
97
+ {...props}
98
+ />
99
+ </div>
100
+ ));
101
+ NavigationMenuViewport.displayName =
102
+ NavigationMenuPrimitive.Viewport.displayName;
103
+
104
+ const NavigationMenuIndicator = React.forwardRef<
105
+ React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
106
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
107
+ >(({ className, ...props }, ref) => (
108
+ <NavigationMenuPrimitive.Indicator
109
+ ref={ref}
110
+ className={cn(
111
+ "top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden",
112
+ "data-[state=visible]:animate-in data-[state=hidden]:animate-out",
113
+ "data-[state=hidden]:fade-out data-[state=visible]:fade-in",
114
+ className
115
+ )}
116
+ {...props}
117
+ >
118
+ <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
119
+ </NavigationMenuPrimitive.Indicator>
120
+ ));
121
+ NavigationMenuIndicator.displayName =
122
+ NavigationMenuPrimitive.Indicator.displayName;
123
+
124
+ export {
125
+ navigationMenuTriggerStyle,
126
+ NavigationMenu,
127
+ NavigationMenuList,
128
+ NavigationMenuItem,
129
+ NavigationMenuContent,
130
+ NavigationMenuTrigger,
131
+ NavigationMenuLink,
132
+ NavigationMenuIndicator,
133
+ NavigationMenuViewport,
134
+ };
135
+
@@ -0,0 +1,197 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import {
3
+ ResizableHandle,
4
+ ResizablePanel,
5
+ ResizablePanelGroup,
6
+ } from "./resizable";
7
+
8
+ const meta: Meta<typeof ResizablePanelGroup> = {
9
+ title: "Components/Layout/Resizable",
10
+ component: ResizablePanelGroup,
11
+ parameters: {
12
+ layout: "centered",
13
+ },
14
+ tags: ["autodocs"],
15
+ };
16
+
17
+ export default meta;
18
+ type Story = StoryObj<typeof ResizablePanelGroup>;
19
+
20
+ export const Default: Story = {
21
+ render: () => (
22
+ <ResizablePanelGroup
23
+ direction="horizontal"
24
+ className="max-w-md rounded-sm border border-border"
25
+ >
26
+ <ResizablePanel defaultSize={50}>
27
+ <div className="flex h-[200px] items-center justify-center p-6">
28
+ <span className="font-medium text-foreground">One</span>
29
+ </div>
30
+ </ResizablePanel>
31
+ <ResizableHandle />
32
+ <ResizablePanel defaultSize={50}>
33
+ <div className="flex h-[200px] items-center justify-center p-6">
34
+ <span className="font-medium text-foreground">Two</span>
35
+ </div>
36
+ </ResizablePanel>
37
+ </ResizablePanelGroup>
38
+ ),
39
+ };
40
+
41
+ export const Vertical: Story = {
42
+ render: () => (
43
+ <ResizablePanelGroup
44
+ direction="vertical"
45
+ className="min-h-[200px] max-w-md rounded-sm border border-border"
46
+ >
47
+ <ResizablePanel defaultSize={25}>
48
+ <div className="flex h-full items-center justify-center p-6">
49
+ <span className="font-medium text-foreground">Header</span>
50
+ </div>
51
+ </ResizablePanel>
52
+ <ResizableHandle />
53
+ <ResizablePanel defaultSize={75}>
54
+ <div className="flex h-full items-center justify-center p-6">
55
+ <span className="font-medium text-foreground">Content</span>
56
+ </div>
57
+ </ResizablePanel>
58
+ </ResizablePanelGroup>
59
+ ),
60
+ };
61
+
62
+ export const WithHandle: Story = {
63
+ render: () => (
64
+ <ResizablePanelGroup
65
+ direction="horizontal"
66
+ className="min-h-[200px] max-w-md rounded-sm border border-border"
67
+ >
68
+ <ResizablePanel defaultSize={25}>
69
+ <div className="flex h-full items-center justify-center p-6">
70
+ <span className="font-medium text-foreground">Sidebar</span>
71
+ </div>
72
+ </ResizablePanel>
73
+ <ResizableHandle withHandle />
74
+ <ResizablePanel defaultSize={75}>
75
+ <div className="flex h-full items-center justify-center p-6">
76
+ <span className="font-medium text-foreground">Content</span>
77
+ </div>
78
+ </ResizablePanel>
79
+ </ResizablePanelGroup>
80
+ ),
81
+ };
82
+
83
+ export const ThreePanels: Story = {
84
+ render: () => (
85
+ <ResizablePanelGroup
86
+ direction="horizontal"
87
+ className="min-h-[200px] max-w-lg rounded-sm border border-border"
88
+ >
89
+ <ResizablePanel defaultSize={20} minSize={15}>
90
+ <div className="flex h-full items-center justify-center p-4">
91
+ <span className="text-sm font-medium text-foreground">Nav</span>
92
+ </div>
93
+ </ResizablePanel>
94
+ <ResizableHandle withHandle />
95
+ <ResizablePanel defaultSize={60}>
96
+ <div className="flex h-full items-center justify-center p-4">
97
+ <span className="font-medium text-foreground">Main Content</span>
98
+ </div>
99
+ </ResizablePanel>
100
+ <ResizableHandle withHandle />
101
+ <ResizablePanel defaultSize={20} minSize={15}>
102
+ <div className="flex h-full items-center justify-center p-4">
103
+ <span className="text-sm font-medium text-foreground">Panel</span>
104
+ </div>
105
+ </ResizablePanel>
106
+ </ResizablePanelGroup>
107
+ ),
108
+ };
109
+
110
+ export const NestedPanels: Story = {
111
+ render: () => (
112
+ <ResizablePanelGroup
113
+ direction="horizontal"
114
+ className="min-h-[300px] max-w-lg rounded-sm border border-border"
115
+ >
116
+ <ResizablePanel defaultSize={25}>
117
+ <div className="flex h-full items-center justify-center p-6">
118
+ <span className="font-medium text-foreground">Sidebar</span>
119
+ </div>
120
+ </ResizablePanel>
121
+ <ResizableHandle withHandle />
122
+ <ResizablePanel defaultSize={75}>
123
+ <ResizablePanelGroup direction="vertical">
124
+ <ResizablePanel defaultSize={50}>
125
+ <div className="flex h-full items-center justify-center p-6">
126
+ <span className="font-medium text-foreground">Top Panel</span>
127
+ </div>
128
+ </ResizablePanel>
129
+ <ResizableHandle />
130
+ <ResizablePanel defaultSize={50}>
131
+ <div className="flex h-full items-center justify-center p-6">
132
+ <span className="font-medium text-foreground">Bottom Panel</span>
133
+ </div>
134
+ </ResizablePanel>
135
+ </ResizablePanelGroup>
136
+ </ResizablePanel>
137
+ </ResizablePanelGroup>
138
+ ),
139
+ };
140
+
141
+ export const IDELayout: Story = {
142
+ render: () => (
143
+ <ResizablePanelGroup
144
+ direction="horizontal"
145
+ className="min-h-[400px] max-w-2xl rounded-sm border border-border"
146
+ >
147
+ <ResizablePanel defaultSize={20} minSize={10}>
148
+ <div className="flex h-full flex-col bg-background p-2">
149
+ <p className="text-xs font-medium uppercase tracking-widest text-foreground-muted mb-2">
150
+ Explorer
151
+ </p>
152
+ <div className="space-y-1 text-sm text-foreground-secondary">
153
+ <p>📁 src</p>
154
+ <p className="pl-4">📁 components</p>
155
+ <p className="pl-4">📁 lib</p>
156
+ <p>📄 package.json</p>
157
+ </div>
158
+ </div>
159
+ </ResizablePanel>
160
+ <ResizableHandle withHandle />
161
+ <ResizablePanel defaultSize={60}>
162
+ <ResizablePanelGroup direction="vertical">
163
+ <ResizablePanel defaultSize={70}>
164
+ <div className="flex h-full items-center justify-center bg-card p-6">
165
+ <span className="font-medium text-foreground">Editor</span>
166
+ </div>
167
+ </ResizablePanel>
168
+ <ResizableHandle />
169
+ <ResizablePanel defaultSize={30} minSize={15}>
170
+ <div className="flex h-full flex-col bg-background p-2">
171
+ <p className="text-xs font-medium uppercase tracking-widest text-foreground-muted mb-2">
172
+ Terminal
173
+ </p>
174
+ <code className="text-sm text-foreground-secondary">
175
+ $ npm run dev
176
+ </code>
177
+ </div>
178
+ </ResizablePanel>
179
+ </ResizablePanelGroup>
180
+ </ResizablePanel>
181
+ <ResizableHandle withHandle />
182
+ <ResizablePanel defaultSize={20} minSize={10}>
183
+ <div className="flex h-full flex-col bg-background p-2">
184
+ <p className="text-xs font-medium uppercase tracking-widest text-foreground-muted mb-2">
185
+ Outline
186
+ </p>
187
+ <div className="space-y-1 text-sm text-foreground-secondary">
188
+ <p>• function Button</p>
189
+ <p>• function Card</p>
190
+ <p>• function Dialog</p>
191
+ </div>
192
+ </div>
193
+ </ResizablePanel>
194
+ </ResizablePanelGroup>
195
+ ),
196
+ };
197
+
@@ -0,0 +1,47 @@
1
+ "use client";
2
+
3
+ import { GripVertical } from "lucide-react";
4
+ import * as ResizablePrimitive from "react-resizable-panels";
5
+ import { cn } from "@/lib/utils";
6
+
7
+ const ResizablePanelGroup = ({
8
+ className,
9
+ ...props
10
+ }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
11
+ <ResizablePrimitive.PanelGroup
12
+ className={cn(
13
+ "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
14
+ className
15
+ )}
16
+ {...props}
17
+ />
18
+ );
19
+
20
+ const ResizablePanel = ResizablePrimitive.Panel;
21
+
22
+ const ResizableHandle = ({
23
+ withHandle,
24
+ className,
25
+ ...props
26
+ }: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
27
+ withHandle?: boolean;
28
+ }) => (
29
+ <ResizablePrimitive.PanelResizeHandle
30
+ className={cn(
31
+ "relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary focus-visible:ring-offset-1",
32
+ "data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0",
33
+ "[&[data-panel-group-direction=vertical]>div]:rotate-90",
34
+ className
35
+ )}
36
+ {...props}
37
+ >
38
+ {withHandle && (
39
+ <div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border border-border bg-card">
40
+ <GripVertical className="h-2.5 w-2.5" />
41
+ </div>
42
+ )}
43
+ </ResizablePrimitive.PanelResizeHandle>
44
+ );
45
+
46
+ export { ResizablePanelGroup, ResizablePanel, ResizableHandle };
47
+