sonance-brand-mcp 1.1.4 → 1.2.2

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 (73) hide show
  1. package/dist/assets/BRAND_GUIDELINES.md +0 -8
  2. package/dist/assets/components/accordion.stories.tsx +310 -0
  3. package/dist/assets/components/accordion.tsx +56 -30
  4. package/dist/assets/components/alert.stories.tsx +199 -0
  5. package/dist/assets/components/autocomplete.stories.tsx +307 -0
  6. package/dist/assets/components/autocomplete.tsx +28 -4
  7. package/dist/assets/components/avatar.stories.tsx +175 -0
  8. package/dist/assets/components/badge.stories.tsx +258 -0
  9. package/dist/assets/components/breadcrumbs.stories.tsx +175 -0
  10. package/dist/assets/components/button.stories.tsx +362 -0
  11. package/dist/assets/components/button.tsx +48 -3
  12. package/dist/assets/components/calendar.stories.tsx +247 -0
  13. package/dist/assets/components/card.stories.tsx +275 -0
  14. package/dist/assets/components/card.tsx +26 -1
  15. package/dist/assets/components/checkbox-group.stories.tsx +281 -0
  16. package/dist/assets/components/checkbox.stories.tsx +160 -0
  17. package/dist/assets/components/checkbox.tsx +32 -4
  18. package/dist/assets/components/code.stories.tsx +265 -0
  19. package/dist/assets/components/date-input.stories.tsx +278 -0
  20. package/dist/assets/components/date-input.tsx +24 -2
  21. package/dist/assets/components/date-picker.stories.tsx +337 -0
  22. package/dist/assets/components/date-picker.tsx +28 -4
  23. package/dist/assets/components/date-range-picker.stories.tsx +340 -0
  24. package/dist/assets/components/dialog.stories.tsx +285 -0
  25. package/dist/assets/components/divider.stories.tsx +176 -0
  26. package/dist/assets/components/drawer.stories.tsx +216 -0
  27. package/dist/assets/components/dropdown.stories.tsx +342 -0
  28. package/dist/assets/components/dropdown.tsx +55 -10
  29. package/dist/assets/components/form.stories.tsx +372 -0
  30. package/dist/assets/components/image.stories.tsx +348 -0
  31. package/dist/assets/components/input-otp.stories.tsx +336 -0
  32. package/dist/assets/components/input-otp.tsx +24 -2
  33. package/dist/assets/components/input.stories.tsx +223 -0
  34. package/dist/assets/components/input.tsx +27 -2
  35. package/dist/assets/components/kbd.stories.tsx +272 -0
  36. package/dist/assets/components/link.stories.tsx +199 -0
  37. package/dist/assets/components/link.tsx +50 -1
  38. package/dist/assets/components/listbox.stories.tsx +287 -0
  39. package/dist/assets/components/listbox.tsx +30 -7
  40. package/dist/assets/components/navbar.stories.tsx +218 -0
  41. package/dist/assets/components/number-input.stories.tsx +295 -0
  42. package/dist/assets/components/number-input.tsx +30 -8
  43. package/dist/assets/components/pagination.stories.tsx +280 -0
  44. package/dist/assets/components/pagination.tsx +45 -21
  45. package/dist/assets/components/popover.stories.tsx +219 -0
  46. package/dist/assets/components/progress.stories.tsx +153 -0
  47. package/dist/assets/components/radio-group.stories.tsx +187 -0
  48. package/dist/assets/components/radio-group.tsx +30 -6
  49. package/dist/assets/components/range-calendar.stories.tsx +334 -0
  50. package/dist/assets/components/scroll-shadow.stories.tsx +335 -0
  51. package/dist/assets/components/select.stories.tsx +192 -0
  52. package/dist/assets/components/select.tsx +54 -7
  53. package/dist/assets/components/skeleton.stories.tsx +166 -0
  54. package/dist/assets/components/slider.stories.tsx +145 -0
  55. package/dist/assets/components/slider.tsx +43 -8
  56. package/dist/assets/components/spacer.stories.tsx +216 -0
  57. package/dist/assets/components/spinner.stories.tsx +149 -0
  58. package/dist/assets/components/switch.stories.tsx +170 -0
  59. package/dist/assets/components/switch.tsx +29 -4
  60. package/dist/assets/components/table.stories.tsx +322 -0
  61. package/dist/assets/components/tabs.stories.tsx +306 -0
  62. package/dist/assets/components/tabs.tsx +25 -4
  63. package/dist/assets/components/textarea.stories.tsx +103 -0
  64. package/dist/assets/components/textarea.tsx +27 -3
  65. package/dist/assets/components/theme-toggle.stories.tsx +248 -0
  66. package/dist/assets/components/time-input.stories.tsx +365 -0
  67. package/dist/assets/components/time-input.tsx +25 -3
  68. package/dist/assets/components/toast.stories.tsx +195 -0
  69. package/dist/assets/components/tooltip.stories.tsx +226 -0
  70. package/dist/assets/components/user.stories.tsx +274 -0
  71. package/dist/assets/logo-manifest.json +0 -18
  72. package/dist/index.js +2142 -85
  73. package/package.json +1 -1
@@ -0,0 +1,280 @@
1
+ import type { Meta, StoryObj } from '@storybook/nextjs-vite';
2
+ import { ComponentProps } from 'react';
3
+ import { useState } from 'react';
4
+ import { Pagination, CompactPagination, type PaginationButtonState } from './pagination';
5
+
6
+ type PaginationStoryProps = ComponentProps<typeof Pagination> & {
7
+ state?: PaginationButtonState;
8
+ };
9
+
10
+ const meta: Meta<PaginationStoryProps> = {
11
+ title: 'Components/Navigation/Pagination',
12
+ component: Pagination,
13
+ tags: ['autodocs'],
14
+ parameters: {
15
+ docs: {
16
+ description: {
17
+ component: 'Navigation component for paginated content with multiple display options.',
18
+ },
19
+ },
20
+ },
21
+ argTypes: {
22
+ state: {
23
+ control: 'select',
24
+ options: ['default', 'hover', 'focus', 'active', 'disabled'],
25
+ description: 'Visual state for PaginationButton documentation',
26
+ table: {
27
+ defaultValue: { summary: 'default' },
28
+ },
29
+ },
30
+ },
31
+ };
32
+
33
+ export default meta;
34
+ type Story = StoryObj<PaginationStoryProps>;
35
+
36
+ export const Default: Story = {
37
+ render: () => {
38
+ const [page, setPage] = useState(1);
39
+ return (
40
+ <Pagination
41
+ currentPage={page}
42
+ totalPages={10}
43
+ onPageChange={setPage}
44
+ />
45
+ );
46
+ },
47
+ };
48
+
49
+ export const ManyPages: Story = {
50
+ render: () => {
51
+ const [page, setPage] = useState(15);
52
+ return (
53
+ <Pagination
54
+ currentPage={page}
55
+ totalPages={50}
56
+ onPageChange={setPage}
57
+ />
58
+ );
59
+ },
60
+ };
61
+
62
+ export const FewPages: Story = {
63
+ render: () => {
64
+ const [page, setPage] = useState(2);
65
+ return (
66
+ <Pagination
67
+ currentPage={page}
68
+ totalPages={5}
69
+ onPageChange={setPage}
70
+ />
71
+ );
72
+ },
73
+ };
74
+
75
+ export const FirstPage: Story = {
76
+ render: () => {
77
+ const [page, setPage] = useState(1);
78
+ return (
79
+ <Pagination
80
+ currentPage={page}
81
+ totalPages={10}
82
+ onPageChange={setPage}
83
+ />
84
+ );
85
+ },
86
+ };
87
+
88
+ export const LastPage: Story = {
89
+ render: () => {
90
+ const [page, setPage] = useState(10);
91
+ return (
92
+ <Pagination
93
+ currentPage={page}
94
+ totalPages={10}
95
+ onPageChange={setPage}
96
+ />
97
+ );
98
+ },
99
+ };
100
+
101
+ export const MoreSiblings: Story = {
102
+ render: () => {
103
+ const [page, setPage] = useState(10);
104
+ return (
105
+ <Pagination
106
+ currentPage={page}
107
+ totalPages={20}
108
+ onPageChange={setPage}
109
+ siblingCount={2}
110
+ />
111
+ );
112
+ },
113
+ };
114
+
115
+ export const Compact: Story = {
116
+ render: () => {
117
+ const [page, setPage] = useState(5);
118
+ return (
119
+ <CompactPagination
120
+ currentPage={page}
121
+ totalPages={20}
122
+ onPageChange={setPage}
123
+ />
124
+ );
125
+ },
126
+ };
127
+
128
+ export const BothStyles: Story = {
129
+ render: () => {
130
+ const [page, setPage] = useState(5);
131
+ return (
132
+ <div className="space-y-8">
133
+ <div>
134
+ <p className="text-xs text-foreground-muted mb-2">Full Pagination</p>
135
+ <Pagination
136
+ currentPage={page}
137
+ totalPages={20}
138
+ onPageChange={setPage}
139
+ />
140
+ </div>
141
+ <div>
142
+ <p className="text-xs text-foreground-muted mb-2">Compact Pagination</p>
143
+ <CompactPagination
144
+ currentPage={page}
145
+ totalPages={20}
146
+ onPageChange={setPage}
147
+ />
148
+ </div>
149
+ </div>
150
+ );
151
+ },
152
+ };
153
+
154
+ export const TableExample: Story = {
155
+ render: () => {
156
+ const [page, setPage] = useState(1);
157
+ const itemsPerPage = 5;
158
+ const items = Array.from({ length: 23 }, (_, i) => ({
159
+ id: i + 1,
160
+ name: `Product ${i + 1}`,
161
+ price: `$${((i + 1) * 99).toFixed(2)}`,
162
+ }));
163
+ const totalPages = Math.ceil(items.length / itemsPerPage);
164
+ const displayedItems = items.slice((page - 1) * itemsPerPage, page * itemsPerPage);
165
+
166
+ return (
167
+ <div className="space-y-4">
168
+ <div className="border border-border">
169
+ <table className="w-full text-sm">
170
+ <thead className="bg-background-secondary">
171
+ <tr>
172
+ <th className="px-4 py-2 text-left">ID</th>
173
+ <th className="px-4 py-2 text-left">Name</th>
174
+ <th className="px-4 py-2 text-right">Price</th>
175
+ </tr>
176
+ </thead>
177
+ <tbody>
178
+ {displayedItems.map((item) => (
179
+ <tr key={item.id} className="border-t border-border">
180
+ <td className="px-4 py-2">{item.id}</td>
181
+ <td className="px-4 py-2">{item.name}</td>
182
+ <td className="px-4 py-2 text-right">{item.price}</td>
183
+ </tr>
184
+ ))}
185
+ </tbody>
186
+ </table>
187
+ </div>
188
+ <div className="flex items-center justify-between">
189
+ <p className="text-sm text-foreground-muted">
190
+ Showing {(page - 1) * itemsPerPage + 1} to{' '}
191
+ {Math.min(page * itemsPerPage, items.length)} of {items.length} results
192
+ </p>
193
+ <Pagination
194
+ currentPage={page}
195
+ totalPages={totalPages}
196
+ onPageChange={setPage}
197
+ />
198
+ </div>
199
+ </div>
200
+ );
201
+ },
202
+ };
203
+
204
+ // State Matrix - Visual documentation of all PaginationButton states
205
+ export const StateMatrix: Story = {
206
+ render: () => {
207
+ const states: PaginationButtonState[] = ['default', 'hover', 'focus', 'active', 'disabled'];
208
+ return (
209
+ <div className="space-y-6">
210
+ <h3 className="text-sm font-medium text-foreground-muted">PaginationButton States</h3>
211
+ <p className="text-xs text-foreground-muted">States are demonstrated via the Pagination component&apos;s active and disabled props.</p>
212
+ <div className="space-y-4">
213
+ <div>
214
+ <span className="text-xs font-medium text-foreground-muted uppercase">Default + Active</span>
215
+ <Pagination currentPage={3} totalPages={5} onPageChange={() => {}} />
216
+ </div>
217
+ <div>
218
+ <span className="text-xs font-medium text-foreground-muted uppercase">First Page (prev disabled)</span>
219
+ <Pagination currentPage={1} totalPages={5} onPageChange={() => {}} />
220
+ </div>
221
+ <div>
222
+ <span className="text-xs font-medium text-foreground-muted uppercase">Last Page (next disabled)</span>
223
+ <Pagination currentPage={5} totalPages={5} onPageChange={() => {}} />
224
+ </div>
225
+ </div>
226
+ </div>
227
+ );
228
+ },
229
+ };
230
+
231
+ // Responsive Matrix - Mobile, Tablet, Desktop
232
+ export const ResponsiveMatrix: Story = {
233
+ render: () => {
234
+ const [mobilePage, setMobilePage] = useState(3);
235
+ const [tabletPage, setTabletPage] = useState(5);
236
+ const [desktopPage, setDesktopPage] = useState(10);
237
+
238
+ return (
239
+ <div className="space-y-8">
240
+ {/* Mobile */}
241
+ <div>
242
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
243
+ <div className="w-[375px] border border-dashed border-border p-4">
244
+ <CompactPagination
245
+ currentPage={mobilePage}
246
+ totalPages={20}
247
+ onPageChange={setMobilePage}
248
+ />
249
+ </div>
250
+ </div>
251
+ {/* Tablet */}
252
+ <div>
253
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
254
+ <div className="w-[768px] border border-dashed border-border p-4 flex justify-center">
255
+ <Pagination
256
+ currentPage={tabletPage}
257
+ totalPages={15}
258
+ onPageChange={setTabletPage}
259
+ />
260
+ </div>
261
+ </div>
262
+ {/* Desktop */}
263
+ <div>
264
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
265
+ <div className="w-[1280px] border border-dashed border-border p-4 flex items-center justify-between">
266
+ <p className="text-sm text-foreground-muted">
267
+ Showing 91-100 of 500 results
268
+ </p>
269
+ <Pagination
270
+ currentPage={desktopPage}
271
+ totalPages={50}
272
+ onPageChange={setDesktopPage}
273
+ siblingCount={2}
274
+ />
275
+ </div>
276
+ </div>
277
+ </div>
278
+ );
279
+ },
280
+ };
@@ -4,6 +4,22 @@ import { forwardRef } from "react";
4
4
  import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
5
5
  import { cn } from "@/lib/utils";
6
6
 
7
+ export type PaginationButtonState = "default" | "hover" | "focus" | "active" | "disabled";
8
+
9
+ // State styles for Storybook/Figma visualization
10
+ const getButtonStateStyles = (state?: PaginationButtonState) => {
11
+ if (!state || state === "default") return "";
12
+
13
+ const stateMap: Record<string, string> = {
14
+ hover: "bg-secondary-hover",
15
+ focus: "ring-2 ring-border-focus ring-offset-2",
16
+ active: "bg-primary text-primary-foreground border-primary",
17
+ disabled: "opacity-50 cursor-not-allowed",
18
+ };
19
+
20
+ return stateMap[state] || "";
21
+ };
22
+
7
23
  interface PaginationProps {
8
24
  currentPage: number;
9
25
  totalPages: number;
@@ -121,30 +137,38 @@ export function Pagination({
121
137
 
122
138
  interface PaginationButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
123
139
  active?: boolean;
140
+ /** Visual state for Storybook/Figma documentation */
141
+ state?: PaginationButtonState;
124
142
  }
125
143
 
126
144
  const PaginationButton = forwardRef<HTMLButtonElement, PaginationButtonProps>(
127
- ({ className, active, disabled, children, ...props }, ref) => (
128
- <button
129
- ref={ref}
130
- type="button"
131
- disabled={disabled}
132
- className={cn(
133
- "flex h-9 min-w-9 items-center justify-center px-3 text-sm font-medium",
134
- "border transition-colors",
135
- "focus:outline-none focus:ring-2 focus:ring-border-focus focus:ring-offset-2",
136
- active
137
- ? "bg-primary text-primary-foreground border-primary"
138
- : disabled
139
- ? "bg-transparent text-foreground-subtle border-transparent cursor-not-allowed"
140
- : "bg-transparent text-foreground border-border hover:bg-secondary-hover",
141
- className
142
- )}
143
- {...props}
144
- >
145
- {children}
146
- </button>
147
- )
145
+ ({ className, active, disabled, state, children, ...props }, ref) => {
146
+ const isActive = active || state === "active";
147
+ const isDisabled = disabled || state === "disabled";
148
+
149
+ return (
150
+ <button
151
+ ref={ref}
152
+ type="button"
153
+ disabled={isDisabled}
154
+ className={cn(
155
+ "flex h-9 min-w-9 items-center justify-center px-3 text-sm font-medium",
156
+ "border transition-colors",
157
+ "focus:outline-none focus:ring-2 focus:ring-border-focus focus:ring-offset-2",
158
+ isActive
159
+ ? "bg-primary text-primary-foreground border-primary"
160
+ : isDisabled
161
+ ? "bg-transparent text-foreground-subtle border-transparent cursor-not-allowed"
162
+ : "bg-transparent text-foreground border-border hover:bg-secondary-hover",
163
+ getButtonStateStyles(state),
164
+ className
165
+ )}
166
+ {...props}
167
+ >
168
+ {children}
169
+ </button>
170
+ );
171
+ }
148
172
  );
149
173
 
150
174
  PaginationButton.displayName = "PaginationButton";
@@ -0,0 +1,219 @@
1
+ import type { Meta, StoryObj } from '@storybook/nextjs-vite';
2
+ import { Popover, PopoverContent } from './popover';
3
+ import { Button } from './button';
4
+
5
+ const meta: Meta<typeof Popover> = {
6
+ title: 'Components/Overlays/Popover',
7
+ component: Popover,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component: 'A floating panel that appears next to a trigger element.',
13
+ },
14
+ },
15
+ layout: 'centered',
16
+ },
17
+ argTypes: {
18
+ position: {
19
+ control: 'select',
20
+ options: ['top', 'bottom', 'left', 'right'],
21
+ },
22
+ triggerOn: {
23
+ control: 'select',
24
+ options: ['click', 'hover'],
25
+ },
26
+ },
27
+ };
28
+
29
+ export default meta;
30
+ type Story = StoryObj<typeof meta>;
31
+
32
+ export const Default: Story = {
33
+ render: () => (
34
+ <Popover trigger={<Button variant="secondary">Click me</Button>}>
35
+ <PopoverContent>
36
+ <p className="text-foreground-secondary">
37
+ This is the popover content. Click outside to close.
38
+ </p>
39
+ </PopoverContent>
40
+ </Popover>
41
+ ),
42
+ };
43
+
44
+ export const OnHover: Story = {
45
+ render: () => (
46
+ <Popover trigger={<Button variant="secondary">Hover me</Button>} triggerOn="hover">
47
+ <PopoverContent>
48
+ <p className="text-foreground-secondary">
49
+ This popover appears on hover.
50
+ </p>
51
+ </PopoverContent>
52
+ </Popover>
53
+ ),
54
+ };
55
+
56
+ export const TopPosition: Story = {
57
+ render: () => (
58
+ <Popover trigger={<Button variant="secondary">Open Top</Button>} position="top">
59
+ <PopoverContent>
60
+ <p className="text-foreground-secondary">Popover on top</p>
61
+ </PopoverContent>
62
+ </Popover>
63
+ ),
64
+ };
65
+
66
+ export const LeftPosition: Story = {
67
+ render: () => (
68
+ <Popover trigger={<Button variant="secondary">Open Left</Button>} position="left">
69
+ <PopoverContent>
70
+ <p className="text-foreground-secondary">Popover on left</p>
71
+ </PopoverContent>
72
+ </Popover>
73
+ ),
74
+ };
75
+
76
+ export const RightPosition: Story = {
77
+ render: () => (
78
+ <Popover trigger={<Button variant="secondary">Open Right</Button>} position="right">
79
+ <PopoverContent>
80
+ <p className="text-foreground-secondary">Popover on right</p>
81
+ </PopoverContent>
82
+ </Popover>
83
+ ),
84
+ };
85
+
86
+ export const AllPositions: Story = {
87
+ render: () => (
88
+ <div className="flex items-center gap-8 p-16">
89
+ <Popover trigger={<Button variant="secondary" size="sm">Top</Button>} position="top">
90
+ <PopoverContent>
91
+ <p className="text-sm">Top position</p>
92
+ </PopoverContent>
93
+ </Popover>
94
+ <Popover trigger={<Button variant="secondary" size="sm">Bottom</Button>} position="bottom">
95
+ <PopoverContent>
96
+ <p className="text-sm">Bottom position</p>
97
+ </PopoverContent>
98
+ </Popover>
99
+ <Popover trigger={<Button variant="secondary" size="sm">Left</Button>} position="left">
100
+ <PopoverContent>
101
+ <p className="text-sm">Left position</p>
102
+ </PopoverContent>
103
+ </Popover>
104
+ <Popover trigger={<Button variant="secondary" size="sm">Right</Button>} position="right">
105
+ <PopoverContent>
106
+ <p className="text-sm">Right position</p>
107
+ </PopoverContent>
108
+ </Popover>
109
+ </div>
110
+ ),
111
+ };
112
+
113
+ export const MenuExample: Story = {
114
+ render: () => (
115
+ <Popover trigger={<Button variant="secondary">Actions</Button>}>
116
+ <div className="py-2">
117
+ {['Edit', 'Duplicate', 'Archive', 'Delete'].map((action) => (
118
+ <button
119
+ key={action}
120
+ className="w-full px-4 py-2 text-left text-sm text-foreground hover:bg-secondary-hover transition-colors"
121
+ >
122
+ {action}
123
+ </button>
124
+ ))}
125
+ </div>
126
+ </Popover>
127
+ ),
128
+ };
129
+
130
+ export const UserMenuExample: Story = {
131
+ render: () => (
132
+ <Popover
133
+ trigger={
134
+ <button className="flex items-center gap-2 p-2 hover:bg-secondary-hover rounded transition-colors">
135
+ <div className="w-8 h-8 rounded-full bg-primary" />
136
+ <span className="text-sm text-foreground">John Doe</span>
137
+ </button>
138
+ }
139
+ >
140
+ <div className="w-48">
141
+ <div className="px-4 py-3 border-b border-border">
142
+ <p className="text-sm font-medium text-foreground">John Doe</p>
143
+ <p className="text-xs text-foreground-muted">john@example.com</p>
144
+ </div>
145
+ <div className="py-2">
146
+ {['Profile', 'Settings', 'Billing'].map((item) => (
147
+ <button
148
+ key={item}
149
+ className="w-full px-4 py-2 text-left text-sm text-foreground hover:bg-secondary-hover transition-colors"
150
+ >
151
+ {item}
152
+ </button>
153
+ ))}
154
+ </div>
155
+ <div className="py-2 border-t border-border">
156
+ <button className="w-full px-4 py-2 text-left text-sm text-error hover:bg-error-light transition-colors">
157
+ Sign out
158
+ </button>
159
+ </div>
160
+ </div>
161
+ </Popover>
162
+ ),
163
+ };
164
+
165
+ // Responsive Matrix - Mobile, Tablet, Desktop
166
+ export const ResponsiveMatrix: Story = {
167
+ render: () => (
168
+ <div className="space-y-8">
169
+ {/* Mobile */}
170
+ <div>
171
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
172
+ <div className="w-[375px] border border-dashed border-border p-4 flex justify-center">
173
+ <Popover trigger={<Button variant="secondary" size="sm">Actions</Button>}>
174
+ <PopoverContent>
175
+ <p className="text-sm">Popover content</p>
176
+ </PopoverContent>
177
+ </Popover>
178
+ </div>
179
+ </div>
180
+ {/* Tablet */}
181
+ <div>
182
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
183
+ <div className="w-[768px] border border-dashed border-border p-4 flex justify-center gap-4">
184
+ <Popover trigger={<Button variant="secondary">Top</Button>} position="top">
185
+ <PopoverContent><p className="text-sm">Top popover</p></PopoverContent>
186
+ </Popover>
187
+ <Popover trigger={<Button variant="secondary">Bottom</Button>} position="bottom">
188
+ <PopoverContent><p className="text-sm">Bottom popover</p></PopoverContent>
189
+ </Popover>
190
+ </div>
191
+ </div>
192
+ {/* Desktop */}
193
+ <div>
194
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
195
+ <div className="w-[1280px] border border-dashed border-border p-4 flex justify-between items-center">
196
+ <Popover trigger={<Button variant="secondary">User Menu</Button>}>
197
+ <div className="w-48">
198
+ <div className="px-4 py-3 border-b border-border">
199
+ <p className="text-sm font-medium">John Doe</p>
200
+ <p className="text-xs text-foreground-muted">john@example.com</p>
201
+ </div>
202
+ <div className="py-2">
203
+ <button className="w-full px-4 py-2 text-left text-sm hover:bg-secondary-hover">Profile</button>
204
+ <button className="w-full px-4 py-2 text-left text-sm hover:bg-secondary-hover">Settings</button>
205
+ </div>
206
+ </div>
207
+ </Popover>
208
+ <Popover trigger={<Button variant="secondary">Actions</Button>}>
209
+ <div className="py-2">
210
+ {['Edit', 'Duplicate', 'Archive', 'Delete'].map((action) => (
211
+ <button key={action} className="w-full px-4 py-2 text-left text-sm hover:bg-secondary-hover">{action}</button>
212
+ ))}
213
+ </div>
214
+ </Popover>
215
+ </div>
216
+ </div>
217
+ </div>
218
+ ),
219
+ };