sonance-brand-mcp 1.3.1 → 1.3.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 (136) hide show
  1. package/dist/assets/api/sonance-analyze/route.ts +1116 -0
  2. package/dist/assets/api/sonance-assets/route.ts +113 -0
  3. package/dist/assets/api/sonance-components/route.ts +41 -0
  4. package/dist/assets/api/sonance-inject-id/route.ts +363 -0
  5. package/dist/assets/api/sonance-save-logo/route.ts +426 -0
  6. package/dist/assets/api/sonance-theme/route.ts +106 -0
  7. package/dist/assets/brand-system.ts +1265 -0
  8. package/dist/assets/components/accordion.stories.tsx +26 -26
  9. package/dist/assets/components/accordion.tsx +3 -3
  10. package/dist/assets/components/alert-dialog.stories.tsx +7 -7
  11. package/dist/assets/components/alert-dialog.tsx +2 -1
  12. package/dist/assets/components/alert.stories.tsx +3 -3
  13. package/dist/assets/components/alert.tsx +4 -3
  14. package/dist/assets/components/aspect-ratio.stories.tsx +4 -1
  15. package/dist/assets/components/autocomplete.stories.tsx +9 -9
  16. package/dist/assets/components/autocomplete.tsx +3 -3
  17. package/dist/assets/components/avatar.stories.tsx +5 -5
  18. package/dist/assets/components/avatar.tsx +4 -4
  19. package/dist/assets/components/badge.stories.tsx +10 -10
  20. package/dist/assets/components/badge.tsx +3 -3
  21. package/dist/assets/components/breadcrumbs.stories.tsx +7 -7
  22. package/dist/assets/components/breadcrumbs.tsx +13 -8
  23. package/dist/assets/components/button.stories.tsx +74 -74
  24. package/dist/assets/components/button.tsx +2 -0
  25. package/dist/assets/components/calendar.stories.tsx +11 -11
  26. package/dist/assets/components/calendar.tsx +4 -4
  27. package/dist/assets/components/card.stories.tsx +22 -22
  28. package/dist/assets/components/card.tsx +7 -3
  29. package/dist/assets/components/carousel.stories.tsx +6 -6
  30. package/dist/assets/components/carousel.tsx +10 -8
  31. package/dist/assets/components/chart.tsx +5 -5
  32. package/dist/assets/components/checkbox-group.stories.tsx +6 -6
  33. package/dist/assets/components/checkbox-group.tsx +3 -3
  34. package/dist/assets/components/checkbox.stories.tsx +23 -20
  35. package/dist/assets/components/checkbox.tsx +13 -16
  36. package/dist/assets/components/code.stories.tsx +24 -24
  37. package/dist/assets/components/code.tsx +7 -14
  38. package/dist/assets/components/collapsible.stories.tsx +3 -3
  39. package/dist/assets/components/command.stories.tsx +14 -14
  40. package/dist/assets/components/command.tsx +4 -3
  41. package/dist/assets/components/context-menu.stories.tsx +1 -1
  42. package/dist/assets/components/context-menu.tsx +3 -7
  43. package/dist/assets/components/date-input.stories.tsx +9 -9
  44. package/dist/assets/components/date-input.tsx +2 -2
  45. package/dist/assets/components/date-picker.stories.tsx +9 -9
  46. package/dist/assets/components/date-picker.tsx +3 -3
  47. package/dist/assets/components/date-range-picker.stories.tsx +12 -12
  48. package/dist/assets/components/date-range-picker.tsx +3 -3
  49. package/dist/assets/components/dialog.stories.tsx +40 -40
  50. package/dist/assets/components/dialog.tsx +8 -12
  51. package/dist/assets/components/divider.stories.tsx +30 -30
  52. package/dist/assets/components/divider.tsx +4 -8
  53. package/dist/assets/components/drawer.stories.tsx +32 -31
  54. package/dist/assets/components/drawer.tsx +7 -6
  55. package/dist/assets/components/dropdown-menu.tsx +3 -7
  56. package/dist/assets/components/dropdown.stories.tsx +12 -12
  57. package/dist/assets/components/dropdown.tsx +5 -5
  58. package/dist/assets/components/form.stories.tsx +30 -29
  59. package/dist/assets/components/form.tsx +5 -5
  60. package/dist/assets/components/hover-card.stories.tsx +12 -10
  61. package/dist/assets/components/hover-card.tsx +1 -1
  62. package/dist/assets/components/image.stories.tsx +48 -25
  63. package/dist/assets/components/image.tsx +8 -5
  64. package/dist/assets/components/input-otp.stories.tsx +15 -15
  65. package/dist/assets/components/input-otp.tsx +5 -5
  66. package/dist/assets/components/input.stories.tsx +30 -25
  67. package/dist/assets/components/input.tsx +7 -4
  68. package/dist/assets/components/kbd.stories.tsx +34 -34
  69. package/dist/assets/components/kbd.tsx +5 -5
  70. package/dist/assets/components/link.stories.tsx +36 -36
  71. package/dist/assets/components/link.tsx +4 -0
  72. package/dist/assets/components/listbox.stories.tsx +5 -5
  73. package/dist/assets/components/listbox.tsx +4 -4
  74. package/dist/assets/components/menubar.tsx +3 -7
  75. package/dist/assets/components/navbar.stories.tsx +24 -24
  76. package/dist/assets/components/navbar.tsx +8 -14
  77. package/dist/assets/components/navigation-menu.stories.tsx +11 -9
  78. package/dist/assets/components/navigation-menu.tsx +1 -1
  79. package/dist/assets/components/number-input.stories.tsx +11 -11
  80. package/dist/assets/components/number-input.tsx +3 -3
  81. package/dist/assets/components/pagination.stories.tsx +13 -13
  82. package/dist/assets/components/pagination.tsx +6 -6
  83. package/dist/assets/components/popover.stories.tsx +35 -35
  84. package/dist/assets/components/popover.tsx +98 -15
  85. package/dist/assets/components/progress.stories.tsx +5 -5
  86. package/dist/assets/components/progress.tsx +5 -5
  87. package/dist/assets/components/radio-group.stories.tsx +7 -7
  88. package/dist/assets/components/radio-group.tsx +3 -3
  89. package/dist/assets/components/range-calendar.stories.tsx +18 -18
  90. package/dist/assets/components/range-calendar.tsx +3 -3
  91. package/dist/assets/components/resizable.stories.tsx +23 -23
  92. package/dist/assets/components/resizable.tsx +1 -1
  93. package/dist/assets/components/scroll-area.stories.tsx +15 -15
  94. package/dist/assets/components/scroll-area.tsx +1 -1
  95. package/dist/assets/components/scroll-shadow.stories.tsx +17 -17
  96. package/dist/assets/components/scroll-shadow.tsx +2 -2
  97. package/dist/assets/components/select.stories.tsx +20 -19
  98. package/dist/assets/components/select.tsx +10 -6
  99. package/dist/assets/components/separator.tsx +1 -1
  100. package/dist/assets/components/sheet.tsx +3 -7
  101. package/dist/assets/components/sidebar.stories.tsx +30 -30
  102. package/dist/assets/components/sidebar.tsx +24 -27
  103. package/dist/assets/components/skeleton.stories.tsx +3 -3
  104. package/dist/assets/components/skeleton.tsx +2 -2
  105. package/dist/assets/components/slider.stories.tsx +6 -6
  106. package/dist/assets/components/slider.tsx +3 -3
  107. package/dist/assets/components/spacer.stories.tsx +11 -11
  108. package/dist/assets/components/spacer.tsx +2 -2
  109. package/dist/assets/components/spinner.stories.tsx +8 -8
  110. package/dist/assets/components/spinner.tsx +5 -5
  111. package/dist/assets/components/switch.stories.tsx +24 -20
  112. package/dist/assets/components/switch.tsx +14 -6
  113. package/dist/assets/components/table.stories.tsx +7 -7
  114. package/dist/assets/components/table.tsx +8 -8
  115. package/dist/assets/components/tabs.stories.tsx +37 -37
  116. package/dist/assets/components/tabs.tsx +3 -3
  117. package/dist/assets/components/textarea.stories.tsx +13 -12
  118. package/dist/assets/components/textarea.tsx +3 -3
  119. package/dist/assets/components/theme-toggle.stories.tsx +31 -30
  120. package/dist/assets/components/theme-toggle.tsx +2 -2
  121. package/dist/assets/components/time-input.stories.tsx +16 -16
  122. package/dist/assets/components/time-input.tsx +2 -2
  123. package/dist/assets/components/toast.stories.tsx +8 -5
  124. package/dist/assets/components/toast.tsx +6 -6
  125. package/dist/assets/components/toggle-group.tsx +1 -1
  126. package/dist/assets/components/toggle.tsx +1 -1
  127. package/dist/assets/components/tooltip.stories.tsx +49 -27
  128. package/dist/assets/components/tooltip.tsx +1 -1
  129. package/dist/assets/components/user.stories.tsx +23 -23
  130. package/dist/assets/components/user.tsx +7 -4
  131. package/dist/assets/dev-tools/SonanceDevTools.tsx +4201 -0
  132. package/dist/assets/dev-tools/index.ts +10 -0
  133. package/dist/assets/globals.css +9 -0
  134. package/dist/assets/styles/brand-overrides.css +37 -0
  135. package/dist/index.js +1776 -7
  136. package/package.json +1 -1
@@ -26,19 +26,19 @@ export const Default: Story = {
26
26
  const [open, setOpen] = useState(false);
27
27
  return (
28
28
  <>
29
- <Button onClick={() => setOpen(true)}>Open Drawer</Button>
29
+ <Button id="default-button" onClick={() => setOpen(true)}>Open Drawer</Button>
30
30
  <Drawer open={open} onClose={() => setOpen(false)}>
31
31
  <DrawerHeader onClose={() => setOpen(false)}>
32
32
  <DrawerTitle>Drawer Title</DrawerTitle>
33
33
  </DrawerHeader>
34
34
  <DrawerBody>
35
- <p className="text-foreground-secondary">
35
+ <p id="default-p-this-is-the-drawer-c" className="text-foreground-secondary">
36
36
  This is the drawer content area. You can add any content here.
37
37
  </p>
38
38
  </DrawerBody>
39
39
  <DrawerFooter>
40
- <Button variant="secondary" onClick={() => setOpen(false)}>Cancel</Button>
41
- <Button onClick={() => setOpen(false)}>Save</Button>
40
+ <Button id="default-button-secondary" variant="secondary" onClick={() => setOpen(false)}>Cancel</Button>
41
+ <Button id="default-button" onClick={() => setOpen(false)}>Save</Button>
42
42
  </DrawerFooter>
43
43
  </Drawer>
44
44
  </>
@@ -51,7 +51,7 @@ export const LeftPosition: Story = {
51
51
  const [open, setOpen] = useState(false);
52
52
  return (
53
53
  <>
54
- <Button onClick={() => setOpen(true)}>Open Left Drawer</Button>
54
+ <Button id="left-position-button" onClick={() => setOpen(true)}>Open Left Drawer</Button>
55
55
  <Drawer open={open} onClose={() => setOpen(false)} position="left">
56
56
  <DrawerHeader onClose={() => setOpen(false)}>
57
57
  <DrawerTitle>Navigation</DrawerTitle>
@@ -60,6 +60,7 @@ export const LeftPosition: Story = {
60
60
  <nav className="space-y-2">
61
61
  {['Dashboard', 'Products', 'Orders', 'Customers', 'Settings'].map((item) => (
62
62
  <a
63
+ id="nav-a"
63
64
  key={item}
64
65
  href="#"
65
66
  className="block px-4 py-2 text-foreground hover:bg-secondary-hover rounded transition-colors"
@@ -80,13 +81,13 @@ export const TopPosition: Story = {
80
81
  const [open, setOpen] = useState(false);
81
82
  return (
82
83
  <>
83
- <Button onClick={() => setOpen(true)}>Open Top Drawer</Button>
84
+ <Button id="top-position-button" onClick={() => setOpen(true)}>Open Top Drawer</Button>
84
85
  <Drawer open={open} onClose={() => setOpen(false)} position="top">
85
86
  <DrawerHeader onClose={() => setOpen(false)}>
86
87
  <DrawerTitle>Notifications</DrawerTitle>
87
88
  </DrawerHeader>
88
89
  <DrawerBody>
89
- <p className="text-foreground-secondary">
90
+ <p id="top-position-p-top-drawer-content-a" className="text-foreground-secondary">
90
91
  Top drawer content appears from the top of the screen.
91
92
  </p>
92
93
  </DrawerBody>
@@ -101,7 +102,7 @@ export const BottomPosition: Story = {
101
102
  const [open, setOpen] = useState(false);
102
103
  return (
103
104
  <>
104
- <Button onClick={() => setOpen(true)}>Open Bottom Drawer</Button>
105
+ <Button id="bottom-position-button" onClick={() => setOpen(true)}>Open Bottom Drawer</Button>
105
106
  <Drawer open={open} onClose={() => setOpen(false)} position="bottom">
106
107
  <DrawerHeader onClose={() => setOpen(false)}>
107
108
  <DrawerTitle>Quick Actions</DrawerTitle>
@@ -114,7 +115,7 @@ export const BottomPosition: Story = {
114
115
  className="flex flex-col items-center gap-2 p-4 hover:bg-secondary-hover rounded transition-colors"
115
116
  >
116
117
  <div className="w-10 h-10 rounded-full bg-primary" />
117
- <span className="text-sm text-foreground">{action}</span>
118
+ <span id="bottom-position-span-action" className="text-sm text-foreground">{action}</span>
118
119
  </button>
119
120
  ))}
120
121
  </div>
@@ -130,21 +131,21 @@ export const FormDrawer: Story = {
130
131
  const [open, setOpen] = useState(false);
131
132
  return (
132
133
  <>
133
- <Button onClick={() => setOpen(true)}>Edit Profile</Button>
134
+ <Button id="form-drawer-button" onClick={() => setOpen(true)}>Edit Profile</Button>
134
135
  <Drawer open={open} onClose={() => setOpen(false)}>
135
136
  <DrawerHeader onClose={() => setOpen(false)}>
136
137
  <DrawerTitle>Edit Profile</DrawerTitle>
137
138
  </DrawerHeader>
138
139
  <DrawerBody>
139
140
  <form className="space-y-4">
140
- <Input label="Full Name" placeholder="John Doe" />
141
- <Input label="Email" type="email" placeholder="john@example.com" />
142
- <Input label="Phone" type="tel" placeholder="+1 (555) 000-0000" />
141
+ <Input id="form-drawer-input-john-doe" label="Full Name" placeholder="John Doe" />
142
+ <Input id="form-drawer-input-johnexamplecom" label="Email" type="email" placeholder="john@example.com" />
143
+ <Input id="form-drawer-input-1-555-0000000" label="Phone" type="tel" placeholder="+1 (555) 000-0000" />
143
144
  </form>
144
145
  </DrawerBody>
145
146
  <DrawerFooter>
146
- <Button variant="secondary" onClick={() => setOpen(false)}>Cancel</Button>
147
- <Button onClick={() => setOpen(false)}>Save Changes</Button>
147
+ <Button id="form-drawer-button-secondary" variant="secondary" onClick={() => setOpen(false)}>Cancel</Button>
148
+ <Button id="form-drawer-button" onClick={() => setOpen(false)}>Save Changes</Button>
148
149
  </DrawerFooter>
149
150
  </Drawer>
150
151
  </>
@@ -158,16 +159,16 @@ export const ResponsiveMatrix: Story = {
158
159
  <div className="space-y-8">
159
160
  {/* Mobile */}
160
161
  <div>
161
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
162
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
162
163
  <div className="w-[375px] h-[400px] border border-dashed border-border relative overflow-hidden">
163
164
  <div className="absolute right-0 top-0 bottom-0 w-[280px] bg-background border-l border-border shadow-lg">
164
165
  <div className="p-4 border-b border-border">
165
- <h3 className="font-semibold">Drawer Title</h3>
166
+ <h3 id="responsive-matrix-h3-drawer-title" className="font-semibold">Drawer Title</h3>
166
167
  </div>
167
168
  <div className="p-4">
168
- <p className="text-sm text-foreground-secondary">Full-height drawer on mobile.</p>
169
+ <p id="responsive-matrix-p-fullheight-drawer-on" className="text-sm text-foreground-secondary">Full-height drawer on mobile.</p>
169
170
  <div className="mt-4 space-y-4">
170
- <Input label="Name" placeholder="Enter name" />
171
+ <Input id="responsive-matrix-input-enter-name" label="Name" placeholder="Enter name" />
171
172
  </div>
172
173
  </div>
173
174
  </div>
@@ -175,38 +176,38 @@ export const ResponsiveMatrix: Story = {
175
176
  </div>
176
177
  {/* Tablet */}
177
178
  <div>
178
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
179
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
179
180
  <div className="w-[768px] h-[300px] border border-dashed border-border relative overflow-hidden">
180
181
  <div className="absolute right-0 top-0 bottom-0 w-[400px] bg-background border-l border-border shadow-lg">
181
182
  <div className="p-4 border-b border-border">
182
- <h3 className="font-semibold">Edit Profile</h3>
183
+ <h3 id="responsive-matrix-h3-edit-profile" className="font-semibold">Edit Profile</h3>
183
184
  </div>
184
185
  <div className="p-4 space-y-4">
185
- <Input label="Name" placeholder="John Doe" />
186
- <Input label="Email" placeholder="john@example.com" />
186
+ <Input id="responsive-matrix-input-john-doe" label="Name" placeholder="John Doe" />
187
+ <Input id="responsive-matrix-input-johnexamplecom" label="Email" placeholder="john@example.com" />
187
188
  </div>
188
189
  <div className="absolute bottom-0 left-0 right-0 p-4 border-t border-border flex justify-end gap-2">
189
- <Button variant="secondary" size="sm">Cancel</Button>
190
- <Button size="sm">Save</Button>
190
+ <Button id="responsive-matrix-button-secondary" variant="secondary" size="sm">Cancel</Button>
191
+ <Button id="responsive-matrix-button" size="sm">Save</Button>
191
192
  </div>
192
193
  </div>
193
194
  </div>
194
195
  </div>
195
196
  {/* Desktop */}
196
197
  <div>
197
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
198
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
198
199
  <div className="w-[1280px] h-[300px] border border-dashed border-border relative overflow-hidden bg-black/20">
199
200
  <div className="absolute right-0 top-0 bottom-0 w-[480px] bg-background border-l border-border shadow-lg">
200
201
  <div className="p-6 border-b border-border">
201
- <h3 className="text-lg font-semibold">Settings Panel</h3>
202
+ <h3 id="responsive-matrix-h3-settings-panel" className="text-lg font-semibold">Settings Panel</h3>
202
203
  </div>
203
204
  <div className="p-6 space-y-4">
204
- <Input label="Display Name" placeholder="Enter display name" />
205
- <Input label="Email" type="email" placeholder="email@example.com" />
205
+ <Input id="responsive-matrix-input-enter-display-n" label="Display Name" placeholder="Enter display name" />
206
+ <Input id="responsive-matrix-input-emailexamplecom" label="Email" type="email" placeholder="email@example.com" />
206
207
  </div>
207
208
  <div className="absolute bottom-0 left-0 right-0 p-6 border-t border-border flex justify-end gap-2">
208
- <Button variant="secondary">Cancel</Button>
209
- <Button>Save Changes</Button>
209
+ <Button id="responsive-matrix-button-secondary" variant="secondary">Cancel</Button>
210
+ <Button id="responsive-matrix-button">Save Changes</Button>
210
211
  </div>
211
212
  </div>
212
213
  </div>
@@ -54,14 +54,14 @@ export function Drawer({
54
54
  };
55
55
 
56
56
  return (
57
- <div className="fixed inset-0 z-50">
57
+ <div data-sonance-name="drawer" className="fixed inset-0 z-50">
58
58
  {/* Backdrop */}
59
59
  <div
60
60
  className="absolute inset-0 bg-overlay animate-in fade-in duration-200"
61
61
  onClick={onClose}
62
62
  />
63
63
  {/* Drawer panel */}
64
- <div
64
+ <div data-sonance-name="drawer"
65
65
  className={cn(
66
66
  "absolute bg-background border-border shadow-xl",
67
67
  position === "left" && "border-r",
@@ -87,7 +87,7 @@ export const DrawerHeader = forwardRef<
87
87
  className={cn(
88
88
  "flex items-center justify-between px-6 py-4 border-b border-border",
89
89
  className
90
- )}
90
+ )} data-sonance-name="drawer"
91
91
  {...props}
92
92
  >
93
93
  <div>{children}</div>
@@ -97,7 +97,7 @@ export const DrawerHeader = forwardRef<
97
97
  className="p-1 text-foreground-muted hover:text-foreground transition-colors"
98
98
  >
99
99
  <X className="h-5 w-5" />
100
- <span className="sr-only">Close</span>
100
+ <span id="drawer-header-span-close" className="sr-only">Close</span>
101
101
  </button>
102
102
  )}
103
103
  </div>
@@ -110,6 +110,7 @@ export const DrawerTitle = forwardRef<
110
110
  React.HTMLAttributes<HTMLHeadingElement>
111
111
  >(({ className, ...props }, ref) => (
112
112
  <h2
113
+ id="drawer-title-h2"
113
114
  ref={ref}
114
115
  className={cn("text-lg font-medium text-foreground", className)}
115
116
  {...props}
@@ -124,7 +125,7 @@ export const DrawerBody = forwardRef<
124
125
  >(({ className, ...props }, ref) => (
125
126
  <div
126
127
  ref={ref}
127
- className={cn("flex-1 overflow-auto p-6", className)}
128
+ className={cn("flex-1 overflow-auto p-6", className)} data-sonance-name="drawer"
128
129
  {...props}
129
130
  />
130
131
  ));
@@ -140,7 +141,7 @@ export const DrawerFooter = forwardRef<
140
141
  className={cn(
141
142
  "flex items-center justify-end gap-3 px-6 py-4 border-t border-border",
142
143
  className
143
- )}
144
+ )} data-sonance-name="drawer"
144
145
  {...props}
145
146
  />
146
147
  ));
@@ -117,7 +117,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
117
117
  checked={checked}
118
118
  {...props}
119
119
  >
120
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
120
+ <span id="dropdown-menu-checkbox-item-span" className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
121
121
  <DropdownMenuPrimitive.ItemIndicator>
122
122
  <Check className="h-4 w-4" />
123
123
  </DropdownMenuPrimitive.ItemIndicator>
@@ -141,7 +141,7 @@ const DropdownMenuRadioItem = React.forwardRef<
141
141
  )}
142
142
  {...props}
143
143
  >
144
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
144
+ <span id="dropdown-menu-radio-item-span" className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
145
145
  <DropdownMenuPrimitive.ItemIndicator>
146
146
  <Circle className="h-2 w-2 fill-current" />
147
147
  </DropdownMenuPrimitive.ItemIndicator>
@@ -186,11 +186,7 @@ const DropdownMenuShortcut = ({
186
186
  ...props
187
187
  }: React.HTMLAttributes<HTMLSpanElement>) => {
188
188
  return (
189
- <span
190
- className={cn(
191
- "ml-auto text-xs tracking-widest text-foreground-muted",
192
- className
193
- )}
189
+ <span id="dropdown-menu-shortcut-span" data-sonance-name="dropdown-menu"
194
190
  {...props}
195
191
  />
196
192
  );
@@ -178,7 +178,7 @@ export const CustomTrigger: Story = {
178
178
  render: () => (
179
179
  <Dropdown>
180
180
  <DropdownTrigger asChild>
181
- <Button variant="secondary">Custom Button Trigger</Button>
181
+ <Button id="custom-trigger-button-secondary" variant="secondary">Custom Button Trigger</Button>
182
182
  </DropdownTrigger>
183
183
  <DropdownMenu>
184
184
  <DropdownItem>Action 1</DropdownItem>
@@ -197,13 +197,13 @@ export const UserMenu: Story = {
197
197
  <div className="w-8 h-8 rounded-full bg-primary flex items-center justify-center text-primary-foreground text-sm font-medium">
198
198
  JD
199
199
  </div>
200
- <span className="text-sm font-medium text-foreground">John Doe</span>
200
+ <span id="user-menu-span-john-doe" className="text-sm font-medium text-foreground">John Doe</span>
201
201
  </button>
202
202
  </DropdownTrigger>
203
203
  <DropdownMenu align="end">
204
204
  <div className="px-3 py-2 border-b border-border">
205
- <p className="text-sm font-medium text-foreground">John Doe</p>
206
- <p className="text-xs text-foreground-muted">john@sonance.com</p>
205
+ <p id="user-menu-p-john-doe" className="text-sm font-medium text-foreground">John Doe</p>
206
+ <p id="user-menu-p-johnsonancecom" className="text-xs text-foreground-muted">john@sonance.com</p>
207
207
  </div>
208
208
  <DropdownItem icon={<User className="h-4 w-4" />}>Profile</DropdownItem>
209
209
  <DropdownItem icon={<Settings className="h-4 w-4" />}>Settings</DropdownItem>
@@ -222,13 +222,13 @@ export const StateMatrix: Story = {
222
222
  const triggerStates: DropdownTriggerState[] = ['default', 'hover', 'focus', 'open', 'disabled'];
223
223
  const itemStates: DropdownItemState[] = ['default', 'hover', 'focus', 'selected', 'disabled'];
224
224
  return (
225
- <div className="space-y-8">
225
+ <div data-sonance-name="dropdown.stories" className="space-y-8">
226
226
  <div>
227
- <h3 className="text-sm font-medium text-foreground-muted mb-4">DropdownTrigger States</h3>
227
+ <h3 id="state-matrix-h3-dropdowntrigger-stat" className="text-sm font-medium text-foreground-muted mb-4">DropdownTrigger States</h3>
228
228
  <div className="flex flex-wrap gap-4">
229
229
  {triggerStates.map((state) => (
230
230
  <div key={state} className="flex flex-col items-center gap-2">
231
- <span className="text-xs font-medium text-foreground-muted uppercase">{state}</span>
231
+ <span id="state-matrix-span-state" className="text-xs font-medium text-foreground-muted uppercase">{state}</span>
232
232
  <Dropdown>
233
233
  <DropdownTrigger state={state}>{state}</DropdownTrigger>
234
234
  <DropdownMenu>
@@ -240,7 +240,7 @@ export const StateMatrix: Story = {
240
240
  </div>
241
241
  </div>
242
242
  <div>
243
- <h3 className="text-sm font-medium text-foreground-muted mb-4">DropdownItem States (Open menu to see)</h3>
243
+ <h3 id="state-matrix-h3-dropdownitem-states-" className="text-sm font-medium text-foreground-muted mb-4">DropdownItem States (Open menu to see)</h3>
244
244
  <Dropdown>
245
245
  <DropdownTrigger state="open">View Item States</DropdownTrigger>
246
246
  <DropdownMenu>
@@ -263,7 +263,7 @@ export const ResponsiveMatrix: Story = {
263
263
  <div className="space-y-8">
264
264
  {/* Mobile */}
265
265
  <div>
266
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
266
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
267
267
  <div className="w-[375px] border border-dashed border-border p-4 flex justify-center">
268
268
  <Dropdown>
269
269
  <DropdownTrigger>Actions</DropdownTrigger>
@@ -278,7 +278,7 @@ export const ResponsiveMatrix: Story = {
278
278
  </div>
279
279
  {/* Tablet */}
280
280
  <div>
281
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
281
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
282
282
  <div className="w-[768px] border border-dashed border-border p-4 flex justify-between">
283
283
  <Dropdown>
284
284
  <DropdownTrigger>File</DropdownTrigger>
@@ -301,7 +301,7 @@ export const ResponsiveMatrix: Story = {
301
301
  </div>
302
302
  {/* Desktop */}
303
303
  <div>
304
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
304
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
305
305
  <div className="w-[1280px] border border-dashed border-border p-4 flex justify-between items-center">
306
306
  <div className="flex gap-4">
307
307
  <Dropdown>
@@ -325,7 +325,7 @@ export const ResponsiveMatrix: Story = {
325
325
  <DropdownTrigger asChild>
326
326
  <button className="flex items-center gap-2 p-2 hover:bg-secondary-hover rounded">
327
327
  <div className="w-8 h-8 rounded-full bg-primary flex items-center justify-center text-primary-foreground text-sm font-medium">JD</div>
328
- <span className="text-sm font-medium">John Doe</span>
328
+ <span id="responsive-matrix-span-john-doe" className="text-sm font-medium">John Doe</span>
329
329
  </button>
330
330
  </DropdownTrigger>
331
331
  <DropdownMenu align="end">
@@ -106,14 +106,14 @@ export function DropdownTrigger({ children, className, asChild, disabled, state
106
106
 
107
107
  if (asChild) {
108
108
  return (
109
- <span onClick={() => !isDisabled && setIsOpen(!isOpen)} className={className}>
109
+ <span id="dropdown-trigger-span-children" data-sonance-name="dropdown" onClick={() => !isDisabled && setIsOpen(!isOpen)} className={className}>
110
110
  {children}
111
111
  </span>
112
112
  );
113
113
  }
114
114
 
115
115
  return (
116
- <button
116
+ <button data-sonance-name="dropdown"
117
117
  type="button"
118
118
  onClick={() => !isDisabled && setIsOpen(!isOpen)}
119
119
  disabled={isDisabled}
@@ -234,11 +234,11 @@ export function DropdownItem({
234
234
  className
235
235
  )}
236
236
  >
237
- {icon && <span className="w-4 h-4 shrink-0">{icon}</span>}
238
- <span className="flex-1">{children}</span>
237
+ {icon && <span id="dropdown-item-span-icon" className="w-4 h-4 shrink-0">{icon}</span>}
238
+ <span id="dropdown-item-span-children" className="flex-1">{children}</span>
239
239
  {isSelected && !icon && <Check className="h-4 w-4 ml-auto" />}
240
240
  {shortcut && (
241
- <span className="ml-auto text-xs text-foreground-muted">{shortcut}</span>
241
+ <span id="dropdown-item-span-shortcut" className="ml-auto text-xs text-foreground-muted">{shortcut}</span>
242
242
  )}
243
243
  </button>
244
244
  );
@@ -29,10 +29,10 @@ export const Default: Story = {
29
29
  };
30
30
 
31
31
  return (
32
- <Form onSubmit={handleSubmit} className="w-80 space-y-4">
32
+ <Form data-sonance-name="form.stories" onSubmit={handleSubmit} className="w-80 space-y-4">
33
33
  <FormField name="email">
34
34
  <FormLabel>Email</FormLabel>
35
- <Input name="email" type="email" placeholder="Enter your email" />
35
+ <Input id="default-input-email" name="email" type="email" placeholder="Enter your email" />
36
36
  </FormField>
37
37
  <FormSubmit>Subscribe</FormSubmit>
38
38
  </Form>
@@ -75,13 +75,13 @@ export const WithValidation: Story = {
75
75
  >
76
76
  <FormField name="email">
77
77
  <FormLabel required>Email</FormLabel>
78
- <Input name="email" type="email" placeholder="you@example.com" />
78
+ <Input id="with-validation-input-email" name="email" type="email" placeholder="you@example.com" />
79
79
  <FormMessage />
80
80
  </FormField>
81
81
 
82
82
  <FormField name="password">
83
83
  <FormLabel required>Password</FormLabel>
84
- <Input name="password" type="password" placeholder="Enter password" />
84
+ <Input id="with-validation-input-password" name="password" type="password" placeholder="Enter password" />
85
85
  <FormDescription>Must be at least 8 characters</FormDescription>
86
86
  <FormMessage />
87
87
  </FormField>
@@ -121,13 +121,13 @@ export const ContactForm: Story = {
121
121
  <div className="grid grid-cols-2 gap-4">
122
122
  <FormField name="name">
123
123
  <FormLabel required>Name</FormLabel>
124
- <Input name="name" placeholder="Your name" />
124
+ <Input id="contact-form-input-name" name="name" placeholder="Your name" />
125
125
  <FormMessage />
126
126
  </FormField>
127
127
 
128
128
  <FormField name="email">
129
129
  <FormLabel required>Email</FormLabel>
130
- <Input name="email" type="email" placeholder="you@example.com" />
130
+ <Input id="contact-form-input-email" name="email" type="email" placeholder="you@example.com" />
131
131
  <FormMessage />
132
132
  </FormField>
133
133
  </div>
@@ -135,6 +135,7 @@ export const ContactForm: Story = {
135
135
  <FormField name="subject">
136
136
  <FormLabel required>Subject</FormLabel>
137
137
  <Select
138
+ id="contact-form-select-select-a-topic"
138
139
  placeholder="Select a topic"
139
140
  options={[
140
141
  { value: 'sales', label: 'Sales Inquiry' },
@@ -148,7 +149,7 @@ export const ContactForm: Story = {
148
149
 
149
150
  <FormField name="message">
150
151
  <FormLabel required>Message</FormLabel>
151
- <Textarea name="message" placeholder="How can we help?" rows={4} />
152
+ <Textarea id="contact-form-textarea-message" name="message" placeholder="How can we help?" rows={4} />
152
153
  <FormMessage />
153
154
  </FormField>
154
155
 
@@ -201,38 +202,38 @@ export const RegistrationForm: Story = {
201
202
  <div className="grid grid-cols-2 gap-4">
202
203
  <FormField name="firstName">
203
204
  <FormLabel required>First Name</FormLabel>
204
- <Input name="firstName" placeholder="John" />
205
+ <Input id="registration-form-input-firstname" name="firstName" placeholder="John" />
205
206
  <FormMessage />
206
207
  </FormField>
207
208
 
208
209
  <FormField name="lastName">
209
210
  <FormLabel required>Last Name</FormLabel>
210
- <Input name="lastName" placeholder="Doe" />
211
+ <Input id="registration-form-input-lastname" name="lastName" placeholder="Doe" />
211
212
  <FormMessage />
212
213
  </FormField>
213
214
  </div>
214
215
 
215
216
  <FormField name="email">
216
217
  <FormLabel required>Email</FormLabel>
217
- <Input name="email" type="email" placeholder="john@example.com" />
218
+ <Input id="registration-form-input-email" name="email" type="email" placeholder="john@example.com" />
218
219
  <FormMessage />
219
220
  </FormField>
220
221
 
221
222
  <FormField name="password">
222
223
  <FormLabel required>Password</FormLabel>
223
- <Input name="password" type="password" />
224
+ <Input id="registration-form-input-password" name="password" type="password" />
224
225
  <FormDescription>Minimum 8 characters</FormDescription>
225
226
  <FormMessage />
226
227
  </FormField>
227
228
 
228
229
  <FormField name="confirmPassword">
229
230
  <FormLabel required>Confirm Password</FormLabel>
230
- <Input name="confirmPassword" type="password" />
231
+ <Input id="registration-form-input-confirmpassword" name="confirmPassword" type="password" />
231
232
  <FormMessage />
232
233
  </FormField>
233
234
 
234
235
  <FormField name="terms">
235
- <Checkbox name="terms" value="accepted" label="I accept the terms and conditions" />
236
+ <Checkbox id="registration-form-checkbox-terms" name="terms" value="accepted" label="I accept the terms and conditions" />
236
237
  <FormMessage />
237
238
  </FormField>
238
239
 
@@ -247,25 +248,25 @@ export const ComponentsShowcase: Story = {
247
248
  render: () => (
248
249
  <div className="w-80 space-y-6">
249
250
  <div>
250
- <h4 className="text-sm font-medium mb-2">FormLabel</h4>
251
+ <h4 id="components-showcase-h4-formlabel" className="text-sm font-medium mb-2">FormLabel</h4>
251
252
  <FormLabel>Regular Label</FormLabel>
252
253
  <FormLabel required>Required Label</FormLabel>
253
254
  </div>
254
255
 
255
256
  <div>
256
- <h4 className="text-sm font-medium mb-2">FormDescription</h4>
257
+ <h4 id="components-showcase-h4-formdescription" className="text-sm font-medium mb-2">FormDescription</h4>
257
258
  <FormDescription>
258
259
  This is helper text that provides additional context for the field.
259
260
  </FormDescription>
260
261
  </div>
261
262
 
262
263
  <div>
263
- <h4 className="text-sm font-medium mb-2">FormMessage (Error)</h4>
264
+ <h4 id="components-showcase-h4-formmessage-error" className="text-sm font-medium mb-2">FormMessage (Error)</h4>
264
265
  <FormMessage>This field is required</FormMessage>
265
266
  </div>
266
267
 
267
268
  <div>
268
- <h4 className="text-sm font-medium mb-2">FormSubmit</h4>
269
+ <h4 id="components-showcase-h4-formsubmit" className="text-sm font-medium mb-2">FormSubmit</h4>
269
270
  <FormSubmit>Submit Button</FormSubmit>
270
271
  </div>
271
272
  </div>
@@ -285,7 +286,7 @@ export const AsyncSubmission: Story = {
285
286
  <Form onSubmit={handleSubmit} className="w-80 space-y-4">
286
287
  <FormField name="data">
287
288
  <FormLabel>Data</FormLabel>
288
- <Input name="data" placeholder="Enter something" />
289
+ <Input id="async-submission-input-data" name="data" placeholder="Enter something" />
289
290
  <FormDescription>
290
291
  The submit button shows loading state during submission
291
292
  </FormDescription>
@@ -302,12 +303,12 @@ export const ResponsiveMatrix: Story = {
302
303
  <div className="space-y-8">
303
304
  {/* Mobile */}
304
305
  <div>
305
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
306
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
306
307
  <div className="w-[375px] border border-dashed border-border p-4">
307
308
  <Form className="space-y-4">
308
309
  <FormField name="email">
309
310
  <FormLabel>Email</FormLabel>
310
- <Input name="email" type="email" placeholder="you@example.com" />
311
+ <Input id="responsive-matrix-input-email" name="email" type="email" placeholder="you@example.com" />
311
312
  </FormField>
312
313
  <FormSubmit className="w-full">Subscribe</FormSubmit>
313
314
  </Form>
@@ -315,22 +316,22 @@ export const ResponsiveMatrix: Story = {
315
316
  </div>
316
317
  {/* Tablet */}
317
318
  <div>
318
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
319
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
319
320
  <div className="w-[768px] border border-dashed border-border p-4">
320
321
  <Form className="space-y-4">
321
322
  <div className="grid grid-cols-2 gap-4">
322
323
  <FormField name="firstName">
323
324
  <FormLabel>First Name</FormLabel>
324
- <Input name="firstName" placeholder="John" />
325
+ <Input id="responsive-matrix-input-firstname" name="firstName" placeholder="John" />
325
326
  </FormField>
326
327
  <FormField name="lastName">
327
328
  <FormLabel>Last Name</FormLabel>
328
- <Input name="lastName" placeholder="Doe" />
329
+ <Input id="responsive-matrix-input-lastname" name="lastName" placeholder="Doe" />
329
330
  </FormField>
330
331
  </div>
331
332
  <FormField name="email">
332
333
  <FormLabel>Email</FormLabel>
333
- <Input name="email" type="email" placeholder="john@example.com" />
334
+ <Input id="responsive-matrix-input-email" name="email" type="email" placeholder="john@example.com" />
334
335
  </FormField>
335
336
  <FormSubmit>Submit</FormSubmit>
336
337
  </Form>
@@ -338,29 +339,29 @@ export const ResponsiveMatrix: Story = {
338
339
  </div>
339
340
  {/* Desktop */}
340
341
  <div>
341
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
342
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
342
343
  <div className="w-[1280px] border border-dashed border-border p-4">
343
344
  <Form className="space-y-4 max-w-2xl">
344
345
  <div className="grid grid-cols-3 gap-4">
345
346
  <FormField name="firstName">
346
347
  <FormLabel required>First Name</FormLabel>
347
- <Input name="firstName" placeholder="John" />
348
+ <Input id="responsive-matrix-input-firstname" name="firstName" placeholder="John" />
348
349
  <FormMessage />
349
350
  </FormField>
350
351
  <FormField name="lastName">
351
352
  <FormLabel required>Last Name</FormLabel>
352
- <Input name="lastName" placeholder="Doe" />
353
+ <Input id="responsive-matrix-input-lastname" name="lastName" placeholder="Doe" />
353
354
  <FormMessage />
354
355
  </FormField>
355
356
  <FormField name="email">
356
357
  <FormLabel required>Email</FormLabel>
357
- <Input name="email" type="email" placeholder="john@example.com" />
358
+ <Input id="responsive-matrix-input-email" name="email" type="email" placeholder="john@example.com" />
358
359
  <FormMessage />
359
360
  </FormField>
360
361
  </div>
361
362
  <FormField name="message">
362
363
  <FormLabel>Message</FormLabel>
363
- <Textarea name="message" placeholder="How can we help?" rows={3} />
364
+ <Textarea id="responsive-matrix-textarea-message" name="message" placeholder="How can we help?" rows={3} />
364
365
  <FormDescription>Optional message</FormDescription>
365
366
  </FormField>
366
367
  <FormSubmit>Send Message</FormSubmit>