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
@@ -112,8 +112,8 @@ export function RangeCalendar({
112
112
  const days = eachDayOfInterval({ start: calendarStart, end: calendarEnd });
113
113
 
114
114
  return (
115
- <div key={monthDate.toISOString()}>
116
- <h3 className="text-sm font-medium text-foreground text-center mb-4">
115
+ <div data-sonance-name="range-calendar" key={monthDate.toISOString()}>
116
+ <h3 id="h3-formatmonthdate-mmmm" className="text-sm font-medium text-foreground text-center mb-4">
117
117
  {format(monthDate, "MMMM yyyy")}
118
118
  </h3>
119
119
 
@@ -140,7 +140,7 @@ export function RangeCalendar({
140
140
  const isEnd = isRangeEnd(day);
141
141
 
142
142
  return (
143
- <button
143
+ <button data-sonance-name="range-calendar"
144
144
  key={day.toISOString()}
145
145
  type="button"
146
146
  onClick={() => handleSelectDate(day)}
@@ -25,13 +25,13 @@ export const Default: Story = {
25
25
  >
26
26
  <ResizablePanel defaultSize={50}>
27
27
  <div className="flex h-[200px] items-center justify-center p-6">
28
- <span className="font-medium text-foreground">One</span>
28
+ <span id="default-span-one" className="font-medium text-foreground">One</span>
29
29
  </div>
30
30
  </ResizablePanel>
31
31
  <ResizableHandle />
32
32
  <ResizablePanel defaultSize={50}>
33
33
  <div className="flex h-[200px] items-center justify-center p-6">
34
- <span className="font-medium text-foreground">Two</span>
34
+ <span id="default-span-two" className="font-medium text-foreground">Two</span>
35
35
  </div>
36
36
  </ResizablePanel>
37
37
  </ResizablePanelGroup>
@@ -46,13 +46,13 @@ export const Vertical: Story = {
46
46
  >
47
47
  <ResizablePanel defaultSize={25}>
48
48
  <div className="flex h-full items-center justify-center p-6">
49
- <span className="font-medium text-foreground">Header</span>
49
+ <span id="vertical-span-header" className="font-medium text-foreground">Header</span>
50
50
  </div>
51
51
  </ResizablePanel>
52
52
  <ResizableHandle />
53
53
  <ResizablePanel defaultSize={75}>
54
54
  <div className="flex h-full items-center justify-center p-6">
55
- <span className="font-medium text-foreground">Content</span>
55
+ <span id="vertical-span-content" className="font-medium text-foreground">Content</span>
56
56
  </div>
57
57
  </ResizablePanel>
58
58
  </ResizablePanelGroup>
@@ -67,13 +67,13 @@ export const WithHandle: Story = {
67
67
  >
68
68
  <ResizablePanel defaultSize={25}>
69
69
  <div className="flex h-full items-center justify-center p-6">
70
- <span className="font-medium text-foreground">Sidebar</span>
70
+ <span id="with-handle-span-sidebar" className="font-medium text-foreground">Sidebar</span>
71
71
  </div>
72
72
  </ResizablePanel>
73
73
  <ResizableHandle withHandle />
74
74
  <ResizablePanel defaultSize={75}>
75
75
  <div className="flex h-full items-center justify-center p-6">
76
- <span className="font-medium text-foreground">Content</span>
76
+ <span id="with-handle-span-content" className="font-medium text-foreground">Content</span>
77
77
  </div>
78
78
  </ResizablePanel>
79
79
  </ResizablePanelGroup>
@@ -88,19 +88,19 @@ export const ThreePanels: Story = {
88
88
  >
89
89
  <ResizablePanel defaultSize={20} minSize={15}>
90
90
  <div className="flex h-full items-center justify-center p-4">
91
- <span className="text-sm font-medium text-foreground">Nav</span>
91
+ <span id="three-panels-span-nav" className="text-sm font-medium text-foreground">Nav</span>
92
92
  </div>
93
93
  </ResizablePanel>
94
94
  <ResizableHandle withHandle />
95
95
  <ResizablePanel defaultSize={60}>
96
96
  <div className="flex h-full items-center justify-center p-4">
97
- <span className="font-medium text-foreground">Main Content</span>
97
+ <span id="three-panels-span-main-content" className="font-medium text-foreground">Main Content</span>
98
98
  </div>
99
99
  </ResizablePanel>
100
100
  <ResizableHandle withHandle />
101
101
  <ResizablePanel defaultSize={20} minSize={15}>
102
102
  <div className="flex h-full items-center justify-center p-4">
103
- <span className="text-sm font-medium text-foreground">Panel</span>
103
+ <span id="three-panels-span-panel" className="text-sm font-medium text-foreground">Panel</span>
104
104
  </div>
105
105
  </ResizablePanel>
106
106
  </ResizablePanelGroup>
@@ -115,7 +115,7 @@ export const NestedPanels: Story = {
115
115
  >
116
116
  <ResizablePanel defaultSize={25}>
117
117
  <div className="flex h-full items-center justify-center p-6">
118
- <span className="font-medium text-foreground">Sidebar</span>
118
+ <span id="nested-panels-span-sidebar" className="font-medium text-foreground">Sidebar</span>
119
119
  </div>
120
120
  </ResizablePanel>
121
121
  <ResizableHandle withHandle />
@@ -123,13 +123,13 @@ export const NestedPanels: Story = {
123
123
  <ResizablePanelGroup direction="vertical">
124
124
  <ResizablePanel defaultSize={50}>
125
125
  <div className="flex h-full items-center justify-center p-6">
126
- <span className="font-medium text-foreground">Top Panel</span>
126
+ <span id="nested-panels-span-top-panel" className="font-medium text-foreground">Top Panel</span>
127
127
  </div>
128
128
  </ResizablePanel>
129
129
  <ResizableHandle />
130
130
  <ResizablePanel defaultSize={50}>
131
131
  <div className="flex h-full items-center justify-center p-6">
132
- <span className="font-medium text-foreground">Bottom Panel</span>
132
+ <span id="nested-panels-span-bottom-panel" className="font-medium text-foreground">Bottom Panel</span>
133
133
  </div>
134
134
  </ResizablePanel>
135
135
  </ResizablePanelGroup>
@@ -146,14 +146,14 @@ export const IDELayout: Story = {
146
146
  >
147
147
  <ResizablePanel defaultSize={20} minSize={10}>
148
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">
149
+ <p id="i-d-e-layout-p-explorer" className="text-xs font-medium uppercase tracking-widest text-foreground-muted mb-2">
150
150
  Explorer
151
151
  </p>
152
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>
153
+ <p id="i-d-e-layout-p--src">📁 src</p>
154
+ <p id="i-d-e-layout-p--components" className="pl-4">📁 components</p>
155
+ <p id="i-d-e-layout-p--lib" className="pl-4">📁 lib</p>
156
+ <p id="i-d-e-layout-p--packagejson">📄 package.json</p>
157
157
  </div>
158
158
  </div>
159
159
  </ResizablePanel>
@@ -162,13 +162,13 @@ export const IDELayout: Story = {
162
162
  <ResizablePanelGroup direction="vertical">
163
163
  <ResizablePanel defaultSize={70}>
164
164
  <div className="flex h-full items-center justify-center bg-card p-6">
165
- <span className="font-medium text-foreground">Editor</span>
165
+ <span id="i-d-e-layout-span-editor" className="font-medium text-foreground">Editor</span>
166
166
  </div>
167
167
  </ResizablePanel>
168
168
  <ResizableHandle />
169
169
  <ResizablePanel defaultSize={30} minSize={15}>
170
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">
171
+ <p id="i-d-e-layout-p-terminal" className="text-xs font-medium uppercase tracking-widest text-foreground-muted mb-2">
172
172
  Terminal
173
173
  </p>
174
174
  <code className="text-sm text-foreground-secondary">
@@ -181,13 +181,13 @@ export const IDELayout: Story = {
181
181
  <ResizableHandle withHandle />
182
182
  <ResizablePanel defaultSize={20} minSize={10}>
183
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">
184
+ <p id="i-d-e-layout-p-outline" className="text-xs font-medium uppercase tracking-widest text-foreground-muted mb-2">
185
185
  Outline
186
186
  </p>
187
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>
188
+ <p id="button-p--function-button">• function Button</p>
189
+ <p id="card-p--function-card">• function Card</p>
190
+ <p id="dialog-p--function-dialog">• function Dialog</p>
191
191
  </div>
192
192
  </div>
193
193
  </ResizablePanel>
@@ -8,7 +8,7 @@ const ResizablePanelGroup = ({
8
8
  className,
9
9
  ...props
10
10
  }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
11
- <ResizablePrimitive.PanelGroup
11
+ <ResizablePrimitive.PanelGroup data-sonance-name="resizable"
12
12
  className={cn(
13
13
  "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
14
14
  className
@@ -22,7 +22,7 @@ export const Default: Story = {
22
22
  render: () => (
23
23
  <ScrollArea className="h-72 w-48 rounded-sm border border-border">
24
24
  <div className="p-4">
25
- <h4 className="mb-4 text-sm font-medium leading-none text-foreground">Tags</h4>
25
+ <h4 id="default-h4-tags" className="mb-4 text-sm font-medium leading-none text-foreground">Tags</h4>
26
26
  {tags.map((tag) => (
27
27
  <div key={tag}>
28
28
  <div className="text-sm text-foreground-secondary">{tag}</div>
@@ -65,12 +65,12 @@ export const Horizontal: Story = {
65
65
  <figure key={artwork.artist} className="shrink-0">
66
66
  <div className="overflow-hidden rounded-sm">
67
67
  <div className="h-[150px] w-[200px] bg-secondary-hover flex items-center justify-center">
68
- <span className="text-foreground-muted text-xs">{artwork.art}</span>
68
+ <span id="horizontal-span-artworkart" className="text-foreground-muted text-xs">{artwork.art}</span>
69
69
  </div>
70
70
  </div>
71
71
  <figcaption className="pt-2 text-xs text-foreground-muted">
72
72
  Photo by{" "}
73
- <span className="font-medium text-foreground">
73
+ <span id="horizontal-span-artworkartist" className="font-medium text-foreground">
74
74
  {artwork.artist}
75
75
  </span>
76
76
  </figcaption>
@@ -86,33 +86,33 @@ export const LargeContent: Story = {
86
86
  render: () => (
87
87
  <ScrollArea className="h-[400px] w-[350px] rounded-sm border border-border p-4">
88
88
  <div className="space-y-4">
89
- <h4 className="text-lg font-medium text-foreground">Sonance Brand Guidelines</h4>
90
- <p className="text-sm text-foreground-secondary leading-relaxed">
89
+ <h4 id="large-content-h4-sonance-brand-guidel" className="text-lg font-medium text-foreground">Sonance Brand Guidelines</h4>
90
+ <p id="large-content-p-welcome-to-the-sonan" className="text-sm text-foreground-secondary leading-relaxed">
91
91
  Welcome to the Sonance Brand Guidelines. This document outlines the visual
92
92
  identity and design standards for the Sonance family of brands.
93
93
  </p>
94
- <h5 className="text-sm font-medium text-foreground mt-6">Typography</h5>
95
- <p className="text-sm text-foreground-secondary leading-relaxed">
94
+ <h5 id="large-content-h5-typography" className="text-sm font-medium text-foreground mt-6">Typography</h5>
95
+ <p id="large-content-p-all-text-should-use-" className="text-sm text-foreground-secondary leading-relaxed">
96
96
  All text should use the Montserrat font family. Headlines use font-weight 300
97
97
  (Light) or 500 (Medium), while body text uses 400 (Regular).
98
98
  </p>
99
- <h5 className="text-sm font-medium text-foreground mt-6">Colors</h5>
100
- <p className="text-sm text-foreground-secondary leading-relaxed">
99
+ <h5 id="large-content-h5-colors" className="text-sm font-medium text-foreground mt-6">Colors</h5>
100
+ <p id="large-content-p-the-sonance-brand-us" className="text-sm text-foreground-secondary leading-relaxed">
101
101
  The Sonance brand uses a sophisticated palette centered around Charcoal
102
102
  (#333F48) as the primary color, with Sonance Blue (#00D3C8) as the accent.
103
103
  </p>
104
- <h5 className="text-sm font-medium text-foreground mt-6">Logo Usage</h5>
105
- <p className="text-sm text-foreground-secondary leading-relaxed">
104
+ <h5 id="large-content-h5-logo-usage" className="text-sm font-medium text-foreground mt-6">Logo Usage</h5>
105
+ <p id="large-content-p-the-sonance-logo-sho" className="text-sm text-foreground-secondary leading-relaxed">
106
106
  The Sonance logo should always have adequate clear space and never be
107
107
  stretched, rotated, or modified in any way.
108
108
  </p>
109
- <h5 className="text-sm font-medium text-foreground mt-6">Photography</h5>
110
- <p className="text-sm text-foreground-secondary leading-relaxed">
109
+ <h5 id="large-content-h5-photography" className="text-sm font-medium text-foreground mt-6">Photography</h5>
110
+ <p id="large-content-p-use-photorealistic-i" className="text-sm text-foreground-secondary leading-relaxed">
111
111
  Use photo-realistic imagery only. Avoid cartoons, illustrations, or
112
112
  AI-generated images that don&apos;t meet our quality standards.
113
113
  </p>
114
- <h5 className="text-sm font-medium text-foreground mt-6">Design Principles</h5>
115
- <p className="text-sm text-foreground-secondary leading-relaxed">
114
+ <h5 id="large-content-h5-design-principles" className="text-sm font-medium text-foreground mt-6">Design Principles</h5>
115
+ <p id="large-content-p-embrace-generous-whi" className="text-sm text-foreground-secondary leading-relaxed">
116
116
  Embrace generous whitespace, minimal borders, refined shadows, and clean
117
117
  backgrounds. Every element should feel premium and intentional.
118
118
  </p>
@@ -8,7 +8,7 @@ const ScrollArea = React.forwardRef<
8
8
  React.ElementRef<typeof ScrollAreaPrimitive.Root>,
9
9
  React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
10
10
  >(({ className, children, ...props }, ref) => (
11
- <ScrollAreaPrimitive.Root
11
+ <ScrollAreaPrimitive.Root data-sonance-name="scroll-area"
12
12
  ref={ref}
13
13
  className={cn("relative overflow-hidden", className)}
14
14
  {...props}
@@ -41,8 +41,8 @@ type Story = StoryObj<typeof meta>;
41
41
 
42
42
  const sampleContent = Array.from({ length: 20 }, (_, i) => (
43
43
  <div key={i} className="p-4 border-b border-border">
44
- <h4 className="font-medium">Item {i + 1}</h4>
45
- <p className="text-sm text-foreground-muted">
44
+ <h4 id="h4-item-i-1" className="font-medium">Item {i + 1}</h4>
45
+ <p id="p-this-is-sample-conte" className="text-sm text-foreground-muted">
46
46
  This is sample content for item {i + 1}. Scroll to see the shadow effect.
47
47
  </p>
48
48
  </div>
@@ -53,8 +53,8 @@ const horizontalItems = Array.from({ length: 15 }, (_, i) => (
53
53
  key={i}
54
54
  className="flex-shrink-0 w-48 h-32 p-4 border border-border rounded-sm bg-card"
55
55
  >
56
- <h4 className="font-medium">Card {i + 1}</h4>
57
- <p className="text-sm text-foreground-muted">Scroll horizontally</p>
56
+ <h4 id="h4-card-i-1" className="font-medium">Card {i + 1}</h4>
57
+ <p id="p-scroll-horizontally" className="text-sm text-foreground-muted">Scroll horizontally</p>
58
58
  </div>
59
59
  ));
60
60
 
@@ -141,7 +141,7 @@ export const LargeShadow: Story = {
141
141
  export const HiddenScrollbar: Story = {
142
142
  render: () => (
143
143
  <div className="space-y-4">
144
- <p className="text-sm text-foreground-muted">
144
+ <p id="hidden-scrollbar-p-scrollbar-is-hidden-" className="text-sm text-foreground-muted">
145
145
  Scrollbar is hidden but scrolling still works
146
146
  </p>
147
147
  <ScrollShadow
@@ -171,19 +171,19 @@ export const ProductListExample: Story = {
171
171
  ];
172
172
 
173
173
  return (
174
- <div className="w-80 border border-border rounded-sm">
174
+ <div data-sonance-name="scroll-shadow.stories" className="w-80 border border-border rounded-sm">
175
175
  <div className="p-4 border-b border-border">
176
- <h3 className="font-medium">Products ({products.length})</h3>
176
+ <h3 id="product-list-example-h3-products-productslen" className="font-medium">Products ({products.length})</h3>
177
177
  </div>
178
178
  <ScrollShadow className="h-64">
179
179
  {products.map((product, i) => (
180
180
  <div key={i} className="p-4 border-b border-border hover:bg-secondary-hover transition-colors cursor-pointer">
181
181
  <div className="flex justify-between items-start">
182
182
  <div>
183
- <h4 className="font-medium text-sm">{product.name}</h4>
184
- <p className="text-xs text-foreground-muted">{product.category}</p>
183
+ <h4 id="product-list-example-h4-productname" className="font-medium text-sm">{product.name}</h4>
184
+ <p id="product-list-example-p-productcategory" className="text-xs text-foreground-muted">{product.category}</p>
185
185
  </div>
186
- <span className="font-medium">{product.price}</span>
186
+ <span id="product-list-example-span-productprice" className="font-medium">{product.price}</span>
187
187
  </div>
188
188
  </div>
189
189
  ))}
@@ -203,7 +203,7 @@ export const ImageGalleryExample: Story = {
203
203
 
204
204
  return (
205
205
  <div className="space-y-2">
206
- <h3 className="font-medium">Gallery</h3>
206
+ <h3 id="image-gallery-example-h3-gallery" className="font-medium">Gallery</h3>
207
207
  <ScrollShadow
208
208
  orientation="horizontal"
209
209
  hideScrollbar
@@ -265,19 +265,19 @@ export const AllSizesComparison: Story = {
265
265
  render: () => (
266
266
  <div className="flex gap-8">
267
267
  <div className="space-y-2">
268
- <p className="text-sm font-medium">Small</p>
268
+ <p id="all-sizes-comparison-p-small" className="text-sm font-medium">Small</p>
269
269
  <ScrollShadow size="sm" className="h-48 w-64 border border-border rounded-sm">
270
270
  {sampleContent.slice(0, 10)}
271
271
  </ScrollShadow>
272
272
  </div>
273
273
  <div className="space-y-2">
274
- <p className="text-sm font-medium">Medium</p>
274
+ <p id="all-sizes-comparison-p-medium" className="text-sm font-medium">Medium</p>
275
275
  <ScrollShadow size="md" className="h-48 w-64 border border-border rounded-sm">
276
276
  {sampleContent.slice(0, 10)}
277
277
  </ScrollShadow>
278
278
  </div>
279
279
  <div className="space-y-2">
280
- <p className="text-sm font-medium">Large</p>
280
+ <p id="all-sizes-comparison-p-large" className="text-sm font-medium">Large</p>
281
281
  <ScrollShadow size="lg" className="h-48 w-64 border border-border rounded-sm">
282
282
  {sampleContent.slice(0, 10)}
283
283
  </ScrollShadow>
@@ -292,7 +292,7 @@ export const ResponsiveMatrix: Story = {
292
292
  <div className="space-y-8">
293
293
  {/* Mobile */}
294
294
  <div>
295
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
295
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
296
296
  <div className="w-[375px] border border-dashed border-border p-4">
297
297
  <ScrollShadow className="h-48 border border-border rounded-sm">
298
298
  {sampleContent.slice(0, 8)}
@@ -301,7 +301,7 @@ export const ResponsiveMatrix: Story = {
301
301
  </div>
302
302
  {/* Tablet */}
303
303
  <div>
304
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
304
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
305
305
  <div className="w-[768px] border border-dashed border-border p-4">
306
306
  <ScrollShadow
307
307
  orientation="horizontal"
@@ -315,7 +315,7 @@ export const ResponsiveMatrix: Story = {
315
315
  </div>
316
316
  {/* Desktop */}
317
317
  <div>
318
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
318
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
319
319
  <div className="w-[1280px] border border-dashed border-border p-4">
320
320
  <div className="grid grid-cols-3 gap-4">
321
321
  <ScrollShadow size="sm" className="h-48 border border-border rounded-sm">
@@ -92,9 +92,9 @@ export function ScrollShadow({
92
92
  const isHorizontal = orientation === "horizontal" || orientation === "both";
93
93
 
94
94
  return (
95
- <div className={cn("relative", className)} style={style}>
95
+ <div data-sonance-name="scroll-shadow" className={cn("relative", className)} style={style}>
96
96
  {/* Start shadow (top/left) */}
97
- <div
97
+ <div data-sonance-name="scroll-shadow"
98
98
  className={cn(
99
99
  "pointer-events-none absolute z-10 transition-opacity duration-200",
100
100
  isVertical && "inset-x-0 top-0",
@@ -101,11 +101,11 @@ export const WithDisabledOption: Story = {
101
101
  export const AllStates: Story = {
102
102
  render: () => (
103
103
  <div className="space-y-6 w-72">
104
- <Select options={defaultOptions} placeholder="Default select" />
105
- <Select options={countryOptions} label="With Label" placeholder="Select..." />
106
- <Select options={countryOptions} label="With Value" defaultValue="uk" />
107
- <Select options={countryOptions} label="With Error" error="Required field" />
108
- <Select options={countryOptions} label="Disabled" defaultValue="us" disabled />
104
+ <Select id="all-states-select-default-select" options={defaultOptions} placeholder="Default select" />
105
+ <Select id="all-states-select" options={countryOptions} label="With Label" placeholder="Select..." />
106
+ <Select id="all-states-select" options={countryOptions} label="With Value" defaultValue="uk" />
107
+ <Select id="all-states-select" options={countryOptions} label="With Error" error="Required field" />
108
+ <Select id="all-states-select" options={countryOptions} label="Disabled" defaultValue="us" disabled />
109
109
  </div>
110
110
  ),
111
111
  };
@@ -132,13 +132,14 @@ export const StateMatrix: Story = {
132
132
  render: () => {
133
133
  const states: SelectState[] = ['default', 'hover', 'focus', 'open', 'error', 'disabled'];
134
134
  return (
135
- <div className="space-y-6 w-80">
136
- <h3 className="text-sm font-medium text-foreground-muted">Select States</h3>
135
+ <div data-sonance-name="select.stories" className="space-y-6 w-80">
136
+ <h3 id="state-matrix-h3-select-states" className="text-sm font-medium text-foreground-muted">Select States</h3>
137
137
  <div className="grid grid-cols-1 gap-4">
138
138
  {states.map((state) => (
139
139
  <div key={state} className="flex items-center gap-4">
140
- <span className="text-xs font-medium text-foreground-muted uppercase w-20">{state}</span>
140
+ <span id="state-matrix-span-state" className="text-xs font-medium text-foreground-muted uppercase w-20">{state}</span>
141
141
  <Select
142
+ id="state-matrix-select-select-option"
142
143
  state={state}
143
144
  options={defaultOptions}
144
145
  placeholder="Select option"
@@ -159,31 +160,31 @@ export const ResponsiveMatrix: Story = {
159
160
  <div className="space-y-8">
160
161
  {/* Mobile */}
161
162
  <div>
162
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
163
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
163
164
  <div className="w-[375px] border border-dashed border-border p-4 space-y-4">
164
- <Select options={countryOptions} label="Country" placeholder="Select..." />
165
- <Select options={defaultOptions} label="Option" placeholder="Choose..." />
165
+ <Select id="responsive-matrix-select" options={countryOptions} label="Country" placeholder="Select..." />
166
+ <Select id="responsive-matrix-select-choose" options={defaultOptions} label="Option" placeholder="Choose..." />
166
167
  </div>
167
168
  </div>
168
169
  {/* Tablet */}
169
170
  <div>
170
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
171
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
171
172
  <div className="w-[768px] border border-dashed border-border p-4">
172
173
  <div className="grid grid-cols-2 gap-4">
173
- <Select options={countryOptions} label="Country" placeholder="Select country..." />
174
- <Select options={defaultOptions} label="Category" placeholder="Select category..." />
174
+ <Select id="responsive-matrix-select-select-country" options={countryOptions} label="Country" placeholder="Select country..." />
175
+ <Select id="responsive-matrix-select-select-category" options={defaultOptions} label="Category" placeholder="Select category..." />
175
176
  </div>
176
177
  </div>
177
178
  </div>
178
179
  {/* Desktop */}
179
180
  <div>
180
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
181
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
181
182
  <div className="w-[1280px] border border-dashed border-border p-4">
182
183
  <div className="grid grid-cols-4 gap-4">
183
- <Select options={countryOptions} label="Country" defaultValue="us" />
184
- <Select options={defaultOptions} label="Default" placeholder="Select..." />
185
- <Select options={countryOptions} label="With Error" error="Required" />
186
- <Select options={countryOptions} label="Disabled" defaultValue="uk" disabled />
184
+ <Select id="responsive-matrix-select" options={countryOptions} label="Country" defaultValue="us" />
185
+ <Select id="responsive-matrix-select" options={defaultOptions} label="Default" placeholder="Select..." />
186
+ <Select id="responsive-matrix-select" options={countryOptions} label="With Error" error="Required" />
187
+ <Select id="responsive-matrix-select" options={countryOptions} label="Disabled" defaultValue="uk" disabled />
187
188
  </div>
188
189
  </div>
189
190
  </div>
@@ -39,6 +39,8 @@ interface SelectProps {
39
39
  className?: string;
40
40
  /** Visual state for Storybook/Figma documentation */
41
41
  state?: SelectState;
42
+ /** Style for the select button */
43
+ style?: React.CSSProperties;
42
44
  }
43
45
 
44
46
  export function Select({
@@ -52,6 +54,7 @@ export function Select({
52
54
  disabled = false,
53
55
  className,
54
56
  state,
57
+ style,
55
58
  }: SelectProps) {
56
59
  const isDisabled = disabled || state === "disabled";
57
60
  const hasError = error || state === "error";
@@ -94,7 +97,7 @@ export function Select({
94
97
  }, []);
95
98
 
96
99
  return (
97
- <div className={cn("w-full", className)} ref={containerRef}>
100
+ <div data-sonance-name="select" className={cn("w-full", className)} ref={containerRef}>
98
101
  {label && (
99
102
  <label className="mb-2 block text-xs font-medium uppercase tracking-widest text-foreground-muted">
100
103
  {label}
@@ -105,6 +108,7 @@ export function Select({
105
108
  type="button"
106
109
  onClick={() => !isDisabled && setIsOpen(!isOpen)}
107
110
  disabled={isDisabled}
111
+ style={style}
108
112
  className={cn(
109
113
  "flex w-full items-center justify-between border border-input-border bg-input px-4 py-3",
110
114
  "text-left text-foreground transition-colors duration-200",
@@ -115,7 +119,7 @@ export function Select({
115
119
  getStateStyles(state)
116
120
  )}
117
121
  >
118
- <span className={cn(!selectedOption && "text-input-placeholder")}>
122
+ <span id="span-selectedoptionlabel-" className={cn(!selectedOption && "text-input-placeholder")}>
119
123
  {selectedOption?.label || placeholder}
120
124
  </span>
121
125
  <ChevronDown
@@ -155,7 +159,7 @@ export function Select({
155
159
  </div>
156
160
  )}
157
161
  </div>
158
- {error && <p className="mt-1 text-sm text-error">{error}</p>}
162
+ {error && <p id="p-error" className="mt-1 text-sm text-error">{error}</p>}
159
163
  </div>
160
164
  );
161
165
  }
@@ -191,7 +195,7 @@ export const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
191
195
  const hasError = error || state === "error";
192
196
 
193
197
  return (
194
- <div className="w-full">
198
+ <div data-sonance-name="select" className="w-full">
195
199
  {label && (
196
200
  <label className="mb-2 block text-xs font-medium uppercase tracking-widest text-foreground-muted">
197
201
  {label}
@@ -209,7 +213,7 @@ export const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
209
213
  hasError && "border-error",
210
214
  getNativeSelectStateStyles(state),
211
215
  className
212
- )}
216
+ )} data-sonance-name="select"
213
217
  {...props}
214
218
  >
215
219
  {options.map((option) => (
@@ -220,7 +224,7 @@ export const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
220
224
  </select>
221
225
  <ChevronDown className="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-foreground-muted" />
222
226
  </div>
223
- {error && <p className="mt-1 text-sm text-error">{error}</p>}
227
+ {error && <p id="native-select-p-error" className="mt-1 text-sm text-error">{error}</p>}
224
228
  </div>
225
229
  );
226
230
  }
@@ -13,7 +13,7 @@ const Separator = React.forwardRef<
13
13
  { className, orientation = "horizontal", decorative = true, ...props },
14
14
  ref
15
15
  ) => (
16
- <SeparatorPrimitive.Root
16
+ <SeparatorPrimitive.Root data-sonance-name="separator"
17
17
  ref={ref}
18
18
  decorative={decorative}
19
19
  orientation={orientation}
@@ -67,7 +67,7 @@ const SheetContent = React.forwardRef<
67
67
  {children}
68
68
  <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
69
69
  <X className="h-4 w-4" />
70
- <span className="sr-only">Close</span>
70
+ <span id="sheet-content-span-close" className="sr-only">Close</span>
71
71
  </SheetPrimitive.Close>
72
72
  </SheetPrimitive.Content>
73
73
  </SheetPortal>
@@ -78,11 +78,7 @@ const SheetHeader = ({
78
78
  className,
79
79
  ...props
80
80
  }: React.HTMLAttributes<HTMLDivElement>) => (
81
- <div
82
- className={cn(
83
- "flex flex-col space-y-2 text-center sm:text-left",
84
- className
85
- )}
81
+ <div data-sonance-name="sheet"
86
82
  {...props}
87
83
  />
88
84
  )
@@ -96,7 +92,7 @@ const SheetFooter = ({
96
92
  className={cn(
97
93
  "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
98
94
  className
99
- )}
95
+ )} data-sonance-name="sheet"
100
96
  {...props}
101
97
  />
102
98
  )