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
@@ -55,11 +55,11 @@ export const Disabled: Story = {
55
55
  export const AllStates: Story = {
56
56
  render: () => (
57
57
  <div className="space-y-6 w-96">
58
- <Textarea placeholder="Default textarea" />
59
- <Textarea label="With Label" placeholder="Enter text..." />
60
- <Textarea label="With Error" error="This field is required" />
61
- <Textarea label="Disabled" placeholder="Cannot edit..." disabled />
62
- <Textarea label="With Content" defaultValue="This textarea has pre-filled content that can be edited by the user." />
58
+ <Textarea id="all-states-textarea-default-textare" placeholder="Default textarea" />
59
+ <Textarea id="all-states-textarea-enter-text" label="With Label" placeholder="Enter text..." />
60
+ <Textarea id="all-states-textarea" label="With Error" error="This field is required" />
61
+ <Textarea id="all-states-textarea-cannot-edit" label="Disabled" placeholder="Cannot edit..." disabled />
62
+ <Textarea id="all-states-textarea" label="With Content" defaultValue="This textarea has pre-filled content that can be edited by the user." />
63
63
  </div>
64
64
  ),
65
65
  };
@@ -70,27 +70,28 @@ export const ResponsiveMatrix: Story = {
70
70
  <div className="space-y-8">
71
71
  {/* Mobile */}
72
72
  <div>
73
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
73
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
74
74
  <div className="w-[375px] border border-dashed border-border p-4 space-y-4">
75
- <Textarea label="Message" placeholder="Enter your message..." />
76
- <Textarea label="Feedback" placeholder="Share your thoughts..." rows={4} />
75
+ <Textarea id="responsive-matrix-textarea-enter-your-mess" label="Message" placeholder="Enter your message..." />
76
+ <Textarea id="responsive-matrix-textarea-share-your-thou" label="Feedback" placeholder="Share your thoughts..." rows={4} />
77
77
  </div>
78
78
  </div>
79
79
  {/* Tablet */}
80
80
  <div>
81
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
81
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
82
82
  <div className="w-[768px] border border-dashed border-border p-4">
83
83
  <div className="grid grid-cols-2 gap-4">
84
- <Textarea label="Description" placeholder="Enter description..." />
85
- <Textarea label="Notes" placeholder="Additional notes..." />
84
+ <Textarea id="responsive-matrix-textarea-enter-descripti" label="Description" placeholder="Enter description..." />
85
+ <Textarea id="responsive-matrix-textarea-additional-note" label="Notes" placeholder="Additional notes..." />
86
86
  </div>
87
87
  </div>
88
88
  </div>
89
89
  {/* Desktop */}
90
90
  <div>
91
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
91
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
92
92
  <div className="w-[1280px] border border-dashed border-border p-4">
93
93
  <Textarea
94
+ id="responsive-matrix-textarea-describe-your-p"
94
95
  label="Project Brief"
95
96
  placeholder="Describe your project requirements..."
96
97
  rows={6}
@@ -30,7 +30,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
30
30
  const hasError = error || state === "error";
31
31
 
32
32
  return (
33
- <div className="w-full">
33
+ <div data-sonance-name="textarea" className="w-full">
34
34
  {label && (
35
35
  <label className="mb-2 block text-xs font-medium uppercase tracking-widest text-foreground-muted">
36
36
  {label}
@@ -49,10 +49,10 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
49
49
  hasError && "border-error",
50
50
  getStateStyles(state),
51
51
  className
52
- )}
52
+ )} data-sonance-name="textarea"
53
53
  {...props}
54
54
  />
55
- {error && <p className="mt-1 text-sm text-error">{error}</p>}
55
+ {error && <p id="textarea-p-error" className="mt-1 text-sm text-error">{error}</p>}
56
56
  </div>
57
57
  );
58
58
  }
@@ -21,7 +21,7 @@ type Story = StoryObj<typeof meta>;
21
21
  export const Default: Story = {
22
22
  render: () => (
23
23
  <div className="space-y-4">
24
- <p className="text-sm text-foreground-muted">
24
+ <p id="default-p-threeway-toggle-ligh" className="text-sm text-foreground-muted">
25
25
  Three-way toggle: Light, Dark, and System
26
26
  </p>
27
27
  <ThemeToggle />
@@ -33,7 +33,7 @@ export const Default: Story = {
33
33
  export const Simple: Story = {
34
34
  render: () => (
35
35
  <div className="space-y-4">
36
- <p className="text-sm text-foreground-muted">
36
+ <p id="simple-p-simple-toggle-switch" className="text-sm text-foreground-muted">
37
37
  Simple toggle: switches between Light and Dark
38
38
  </p>
39
39
  <SimpleThemeToggle />
@@ -47,13 +47,13 @@ export const InNavbar: Story = {
47
47
  <div className="flex items-center justify-between p-4 border border-border rounded-sm bg-card">
48
48
  <div className="flex items-center gap-2">
49
49
  <div className="w-8 h-8 bg-primary rounded-sm" />
50
- <span className="font-medium">Sonance</span>
50
+ <span id="in-navbar-span-sonance" className="font-medium">Sonance</span>
51
51
  </div>
52
52
  <div className="flex items-center gap-4">
53
53
  <nav className="flex gap-4 text-sm">
54
- <a href="#" className="hover:text-primary">Products</a>
55
- <a href="#" className="hover:text-primary">About</a>
56
- <a href="#" className="hover:text-primary">Contact</a>
54
+ <a id="nav-a" href="#" className="hover:text-primary">Products</a>
55
+ <a id="nav-a" href="#" className="hover:text-primary">About</a>
56
+ <a id="nav-a" href="#" className="hover:text-primary">Contact</a>
57
57
  </nav>
58
58
  <SimpleThemeToggle />
59
59
  </div>
@@ -65,13 +65,13 @@ export const InNavbar: Story = {
65
65
  export const InSettingsPanel: Story = {
66
66
  render: () => (
67
67
  <div className="w-80 p-6 border border-border rounded-sm bg-card space-y-6">
68
- <h3 className="font-medium">Appearance</h3>
68
+ <h3 id="nav-h3-appearance" className="font-medium">Appearance</h3>
69
69
  <div className="space-y-4">
70
70
  <div className="space-y-2">
71
71
  <label className="text-sm text-foreground-muted">Theme</label>
72
72
  <ThemeToggle />
73
73
  </div>
74
- <p className="text-xs text-foreground-muted">
74
+ <p id="in-settings-panel-p-choose-your-preferre" className="text-xs text-foreground-muted">
75
75
  Choose your preferred color scheme. System will match your device settings.
76
76
  </p>
77
77
  </div>
@@ -84,11 +84,11 @@ export const WithLabels: Story = {
84
84
  render: () => (
85
85
  <div className="space-y-6">
86
86
  <div className="flex items-center justify-between w-64">
87
- <span className="text-sm">Dark Mode</span>
87
+ <span id="with-labels-span-dark-mode" className="text-sm">Dark Mode</span>
88
88
  <SimpleThemeToggle />
89
89
  </div>
90
90
  <div className="space-y-2">
91
- <span className="text-sm">Color Theme</span>
91
+ <span id="with-labels-span-color-theme" className="text-sm">Color Theme</span>
92
92
  <ThemeToggle />
93
93
  </div>
94
94
  </div>
@@ -100,11 +100,11 @@ export const SizeComparison: Story = {
100
100
  render: () => (
101
101
  <div className="space-y-8">
102
102
  <div className="space-y-2">
103
- <p className="text-sm font-medium">Full Toggle (3 options)</p>
103
+ <p id="size-comparison-p-full-toggle-3-option" className="text-sm font-medium">Full Toggle (3 options)</p>
104
104
  <ThemeToggle />
105
105
  </div>
106
106
  <div className="space-y-2">
107
- <p className="text-sm font-medium">Simple Toggle (2 options)</p>
107
+ <p id="size-comparison-p-simple-toggle-2-opti" className="text-sm font-medium">Simple Toggle (2 options)</p>
108
108
  <SimpleThemeToggle />
109
109
  </div>
110
110
  </div>
@@ -117,13 +117,13 @@ export const OnDarkBackground: Story = {
117
117
  <div className="space-y-4">
118
118
  <div className="p-6 bg-sonance-charcoal rounded-sm">
119
119
  <div className="flex items-center justify-between">
120
- <span className="text-white text-sm">On dark background</span>
120
+ <span id="on-dark-background-span" className="text-white text-sm">On dark background</span>
121
121
  <SimpleThemeToggle className="[&_button]:text-white [&_button:hover]:bg-white/10" />
122
122
  </div>
123
123
  </div>
124
124
  <div className="p-6 bg-card border border-border rounded-sm">
125
125
  <div className="flex items-center justify-between">
126
- <span className="text-sm">On light background</span>
126
+ <span id="on-dark-background-span-on-light-background" className="text-sm">On light background</span>
127
127
  <SimpleThemeToggle />
128
128
  </div>
129
129
  </div>
@@ -136,12 +136,12 @@ export const InFooter: Story = {
136
136
  render: () => (
137
137
  <div className="p-6 border-t border-border bg-background-secondary">
138
138
  <div className="flex items-center justify-between">
139
- <p className="text-sm text-foreground-muted">
139
+ <p id="in-footer-p-copy-2024-sonance-al" className="text-sm text-foreground-muted">
140
140
  &copy; 2024 Sonance. All rights reserved.
141
141
  </p>
142
142
  <div className="flex items-center gap-4">
143
- <a href="#" className="text-sm text-foreground-muted hover:text-foreground">Privacy</a>
144
- <a href="#" className="text-sm text-foreground-muted hover:text-foreground">Terms</a>
143
+ <a id="in-footer-a" href="#" className="text-sm text-foreground-muted hover:text-foreground">Privacy</a>
144
+ <a id="in-footer-a" href="#" className="text-sm text-foreground-muted hover:text-foreground">Terms</a>
145
145
  <div className="w-px h-4 bg-border" />
146
146
  <SimpleThemeToggle />
147
147
  </div>
@@ -155,7 +155,7 @@ export const InMobileMenu: Story = {
155
155
  render: () => (
156
156
  <div className="w-72 p-4 border border-border rounded-sm bg-card space-y-4">
157
157
  <div className="flex items-center justify-between pb-4 border-b border-border">
158
- <span className="font-medium">Menu</span>
158
+ <span id="in-mobile-menu-span-menu" className="font-medium">Menu</span>
159
159
  <button className="p-1 hover:bg-secondary-hover rounded-sm">
160
160
  <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
161
161
  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
@@ -165,6 +165,7 @@ export const InMobileMenu: Story = {
165
165
  <nav className="space-y-1">
166
166
  {['Home', 'Products', 'About', 'Contact'].map((item) => (
167
167
  <a
168
+ id="nav-a"
168
169
  key={item}
169
170
  href="#"
170
171
  className="block px-3 py-2 rounded-sm hover:bg-secondary-hover"
@@ -175,7 +176,7 @@ export const InMobileMenu: Story = {
175
176
  </nav>
176
177
  <div className="pt-4 border-t border-border">
177
178
  <div className="flex items-center justify-between px-3">
178
- <span className="text-sm text-foreground-muted">Theme</span>
179
+ <span id="nav-span-theme" className="text-sm text-foreground-muted">Theme</span>
179
180
  <ThemeToggle />
180
181
  </div>
181
182
  </div>
@@ -188,11 +189,11 @@ export const AllVariants: Story = {
188
189
  render: () => (
189
190
  <div className="space-y-8">
190
191
  <div>
191
- <h4 className="text-sm font-medium mb-3">ThemeToggle (Light / Dark / System)</h4>
192
+ <h4 id="all-variants-h4-themetoggle-light-da" className="text-sm font-medium mb-3">ThemeToggle (Light / Dark / System)</h4>
192
193
  <ThemeToggle />
193
194
  </div>
194
195
  <div>
195
- <h4 className="text-sm font-medium mb-3">SimpleThemeToggle (Light / Dark)</h4>
196
+ <h4 id="all-variants-h4-simplethemetoggle-li" className="text-sm font-medium mb-3">SimpleThemeToggle (Light / Dark)</h4>
196
197
  <SimpleThemeToggle />
197
198
  </div>
198
199
  </div>
@@ -205,38 +206,38 @@ export const ResponsiveMatrix: Story = {
205
206
  <div className="space-y-8">
206
207
  {/* Mobile */}
207
208
  <div>
208
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
209
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
209
210
  <div className="w-[375px] border border-dashed border-border p-4">
210
211
  <div className="flex items-center justify-between">
211
- <span className="text-sm">Dark Mode</span>
212
+ <span id="responsive-matrix-span-dark-mode" className="text-sm">Dark Mode</span>
212
213
  <SimpleThemeToggle />
213
214
  </div>
214
215
  </div>
215
216
  </div>
216
217
  {/* Tablet */}
217
218
  <div>
218
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
219
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
219
220
  <div className="w-[768px] border border-dashed border-border p-4">
220
221
  <div className="flex items-center justify-between">
221
- <span className="text-sm">Theme Preference</span>
222
+ <span id="responsive-matrix-span-theme-preference" className="text-sm">Theme Preference</span>
222
223
  <ThemeToggle />
223
224
  </div>
224
225
  </div>
225
226
  </div>
226
227
  {/* Desktop */}
227
228
  <div>
228
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
229
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
229
230
  <div className="w-[1280px] border border-dashed border-border p-4">
230
231
  <div className="flex items-center justify-between p-4 border border-border rounded-sm bg-card">
231
232
  <div className="flex items-center gap-2">
232
233
  <div className="w-8 h-8 bg-primary rounded-sm" />
233
- <span className="font-medium">Sonance</span>
234
+ <span id="responsive-matrix-span-sonance" className="font-medium">Sonance</span>
234
235
  </div>
235
236
  <div className="flex items-center gap-4">
236
237
  <nav className="flex gap-4 text-sm">
237
- <a href="#" className="hover:text-primary">Products</a>
238
- <a href="#" className="hover:text-primary">About</a>
239
- <a href="#" className="hover:text-primary">Contact</a>
238
+ <a id="nav-a" href="#" className="hover:text-primary">Products</a>
239
+ <a id="nav-a" href="#" className="hover:text-primary">About</a>
240
+ <a id="nav-a" href="#" className="hover:text-primary">Contact</a>
240
241
  </nav>
241
242
  <SimpleThemeToggle />
242
243
  </div>
@@ -16,7 +16,7 @@ export function ThemeToggle({ className }: { className?: string }) {
16
16
  }
17
17
 
18
18
  return (
19
- <div className={cn("flex items-center gap-1 p-1 bg-background-secondary rounded-sm", className)}>
19
+ <div data-sonance-name="theme-toggle" className={cn("flex items-center gap-1 p-1 bg-background-secondary rounded-sm", className)}>
20
20
  <button
21
21
  onClick={() => setTheme("light")}
22
22
  className={cn(
@@ -62,7 +62,7 @@ export function SimpleThemeToggle({ className }: { className?: string }) {
62
62
  }
63
63
 
64
64
  return (
65
- <button
65
+ <button data-sonance-name="theme-toggle"
66
66
  onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}
67
67
  className={cn(
68
68
  "p-2 rounded-sm hover:bg-secondary-hover transition-colors",
@@ -57,12 +57,12 @@ export const Default: Story = {
57
57
  render: () => {
58
58
  const [time, setTime] = useState<TimeValue>({ hours: 12, minutes: 0 });
59
59
  return (
60
- <div className="w-48 space-y-4">
60
+ <div data-sonance-name="time-input.stories" className="w-48 space-y-4">
61
61
  <TimeInput
62
62
  value={time}
63
63
  onValueChange={setTime}
64
64
  />
65
- <p className="text-sm text-foreground-muted">
65
+ <p id="default-p-selected-timehoursti" className="text-sm text-foreground-muted">
66
66
  Selected: {time.hours}:{time.minutes.toString().padStart(2, '0')}
67
67
  </p>
68
68
  </div>
@@ -98,7 +98,7 @@ export const Use24Hour: Story = {
98
98
  value={time}
99
99
  onValueChange={setTime}
100
100
  />
101
- <p className="text-sm text-foreground-muted">
101
+ <p id="use24-hour-p-24hour-format-timeho" className="text-sm text-foreground-muted">
102
102
  24-hour format: {time.hours}:{time.minutes.toString().padStart(2, '0')}
103
103
  </p>
104
104
  </div>
@@ -184,7 +184,7 @@ export const AppointmentBookingExample: Story = {
184
184
 
185
185
  return (
186
186
  <div className="w-64 space-y-4 p-4 border border-border rounded-sm">
187
- <h3 className="font-medium">Schedule Appointment</h3>
187
+ <h3 id="appointment-booking-example-h3-schedule-appointment" className="font-medium">Schedule Appointment</h3>
188
188
  <TimeInput
189
189
  label="Start Time"
190
190
  value={startTime}
@@ -197,7 +197,7 @@ export const AppointmentBookingExample: Story = {
197
197
  error={hasError ? "End time must be after start time" : undefined}
198
198
  />
199
199
  {!hasError && (
200
- <p className="text-sm text-foreground-muted">
200
+ <p id="appointment-booking-example-p-duration-mathfloordu" className="text-sm text-foreground-muted">
201
201
  Duration: {Math.floor(durationMinutes / 60)}h {durationMinutes % 60}m
202
202
  </p>
203
203
  )}
@@ -233,16 +233,16 @@ export const TimeZoneExample: Story = {
233
233
  />
234
234
  <div className="space-y-2 text-sm">
235
235
  <div className="flex justify-between">
236
- <span className="text-foreground-muted">UTC</span>
237
- <span>{formatTime(utcHours)}</span>
236
+ <span id="time-zone-example-span-utc" className="text-foreground-muted">UTC</span>
237
+ <span id="time-zone-example-span-formattimeutchours">{formatTime(utcHours)}</span>
238
238
  </div>
239
239
  <div className="flex justify-between">
240
- <span className="text-foreground-muted">London (GMT)</span>
241
- <span>{formatTime(londonHours)}</span>
240
+ <span id="time-zone-example-span-london-gmt" className="text-foreground-muted">London (GMT)</span>
241
+ <span id="time-zone-example-span-formattimelondonhour">{formatTime(londonHours)}</span>
242
242
  </div>
243
243
  <div className="flex justify-between">
244
- <span className="text-foreground-muted">Tokyo (JST)</span>
245
- <span>{formatTime(tokyoHours)}</span>
244
+ <span id="time-zone-example-span-tokyo-jst" className="text-foreground-muted">Tokyo (JST)</span>
245
+ <span id="time-zone-example-span-formattimetokyohours">{formatTime(tokyoHours)}</span>
246
246
  </div>
247
247
  </div>
248
248
  </div>
@@ -309,11 +309,11 @@ export const StateMatrix: Story = {
309
309
  const states: TimeInputState[] = ['default', 'hover', 'focus', 'error', 'disabled'];
310
310
  return (
311
311
  <div className="space-y-6 w-48">
312
- <h3 className="text-sm font-medium text-foreground-muted">TimeInput States</h3>
312
+ <h3 id="state-matrix-h3-timeinput-states" className="text-sm font-medium text-foreground-muted">TimeInput States</h3>
313
313
  <div className="space-y-4">
314
314
  {states.map((state) => (
315
315
  <div key={state}>
316
- <span className="text-xs font-medium text-foreground-muted uppercase">{state}</span>
316
+ <span id="state-matrix-span-state" className="text-xs font-medium text-foreground-muted uppercase">{state}</span>
317
317
  <TimeInput
318
318
  state={state}
319
319
  defaultValue={{ hours: 9, minutes: 30 }}
@@ -333,14 +333,14 @@ export const ResponsiveMatrix: Story = {
333
333
  <div className="space-y-8">
334
334
  {/* Mobile */}
335
335
  <div>
336
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
336
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
337
337
  <div className="w-[375px] border border-dashed border-border p-4">
338
338
  <TimeInput label="Start Time" defaultValue={{ hours: 9, minutes: 0 }} />
339
339
  </div>
340
340
  </div>
341
341
  {/* Tablet */}
342
342
  <div>
343
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
343
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
344
344
  <div className="w-[768px] border border-dashed border-border p-4">
345
345
  <div className="grid grid-cols-2 gap-4">
346
346
  <TimeInput label="Start Time" defaultValue={{ hours: 9, minutes: 0 }} />
@@ -350,7 +350,7 @@ export const ResponsiveMatrix: Story = {
350
350
  </div>
351
351
  {/* Desktop */}
352
352
  <div>
353
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
353
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
354
354
  <div className="w-[1280px] border border-dashed border-border p-4">
355
355
  <div className="grid grid-cols-4 gap-4">
356
356
  <TimeInput label="12-Hour" defaultValue={{ hours: 9, minutes: 30 }} />
@@ -108,7 +108,7 @@ export const TimeInput = forwardRef<HTMLInputElement, TimeInputProps>(
108
108
  };
109
109
 
110
110
  return (
111
- <div className={cn("w-full", className)}>
111
+ <div data-sonance-name="time-input" className={cn("w-full", className)}>
112
112
  {label && (
113
113
  <label className="mb-2 block text-xs font-medium uppercase tracking-widest text-foreground-muted">
114
114
  {label}
@@ -154,7 +154,7 @@ export const TimeInput = forwardRef<HTMLInputElement, TimeInputProps>(
154
154
  </button>
155
155
  )}
156
156
  </div>
157
- {error && <p className="mt-1 text-sm text-error">{error}</p>}
157
+ {error && <p id="p-error" className="mt-1 text-sm text-error">{error}</p>}
158
158
  </div>
159
159
  );
160
160
  }
@@ -89,7 +89,7 @@ export const WithAction: Story = {
89
89
  description: 'A new version of the app is ready to install.',
90
90
  onClose: () => {},
91
91
  action: (
92
- <Button size="sm" variant="secondary">
92
+ <Button id="with-action-button-secondary" size="sm" variant="secondary">
93
93
  Update now
94
94
  </Button>
95
95
  ),
@@ -108,8 +108,9 @@ function ToastDemo() {
108
108
  const { addToast } = useToast();
109
109
 
110
110
  return (
111
- <div className="space-y-4">
111
+ <div data-sonance-name="toast.stories" className="space-y-4">
112
112
  <Button
113
+ id="toast-demo-button"
113
114
  onClick={() =>
114
115
  addToast({
115
116
  title: 'Success',
@@ -121,6 +122,7 @@ function ToastDemo() {
121
122
  Show Success Toast
122
123
  </Button>
123
124
  <Button
125
+ id="toast-demo-button-secondary"
124
126
  variant="secondary"
125
127
  onClick={() =>
126
128
  addToast({
@@ -133,6 +135,7 @@ function ToastDemo() {
133
135
  Show Error Toast
134
136
  </Button>
135
137
  <Button
138
+ id="toast-demo-button-ghost"
136
139
  variant="ghost"
137
140
  onClick={() =>
138
141
  addToast({
@@ -162,7 +165,7 @@ export const ResponsiveMatrix: Story = {
162
165
  <div className="space-y-8">
163
166
  {/* Mobile */}
164
167
  <div>
165
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
168
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
166
169
  <div className="w-[375px] border border-dashed border-border p-4 space-y-2">
167
170
  <Toast variant="success" title="Success" description="Changes saved." onClose={() => {}} />
168
171
  <Toast variant="error" title="Error" description="Failed to save." onClose={() => {}} />
@@ -170,7 +173,7 @@ export const ResponsiveMatrix: Story = {
170
173
  </div>
171
174
  {/* Tablet */}
172
175
  <div>
173
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
176
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
174
177
  <div className="w-[768px] border border-dashed border-border p-4">
175
178
  <div className="flex gap-4">
176
179
  <Toast variant="success" title="Success" description="Your changes have been saved." onClose={() => {}} />
@@ -180,7 +183,7 @@ export const ResponsiveMatrix: Story = {
180
183
  </div>
181
184
  {/* Desktop */}
182
185
  <div>
183
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
186
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
184
187
  <div className="w-[1280px] border border-dashed border-border p-4">
185
188
  <div className="flex gap-4">
186
189
  <Toast variant="default" title="Notification" description="Default toast notification." onClose={() => {}} />
@@ -47,17 +47,17 @@ export const Toast = forwardRef<HTMLDivElement, ToastProps>(
47
47
  const Icon = iconMap[variant || "default"];
48
48
 
49
49
  return (
50
- <div
50
+ <div data-sonance-name="toast"
51
51
  ref={ref}
52
52
  role="alert"
53
- className={cn(toastVariants({ variant }), className)}
53
+ className={cn(toastVariants({ variant }), className)}
54
54
  {...props}
55
55
  >
56
56
  <Icon className="h-5 w-5 shrink-0 mt-0.5" />
57
57
  <div className="flex-1 space-y-1">
58
- {title && <p className="text-sm font-medium">{title}</p>}
58
+ {title && <p id="icon-p-title" className="text-sm font-medium">{title}</p>}
59
59
  {description && (
60
- <p className={cn("text-sm", variant === "default" && "text-foreground-secondary")}>
60
+ <p id="icon-p-description" className={cn("text-sm", variant === "default" && "text-foreground-secondary")}>
61
61
  {description}
62
62
  </p>
63
63
  )}
@@ -70,7 +70,7 @@ export const Toast = forwardRef<HTMLDivElement, ToastProps>(
70
70
  className="shrink-0 p-1 opacity-70 hover:opacity-100 transition-opacity"
71
71
  >
72
72
  <X className="h-4 w-4" />
73
- <span className="sr-only">Dismiss</span>
73
+ <span id="icon-span-dismiss" className="sr-only">Dismiss</span>
74
74
  </button>
75
75
  )}
76
76
  </div>
@@ -163,7 +163,7 @@ export function ToastProvider({
163
163
  return (
164
164
  <ToastContext.Provider value={{ toasts, addToast, removeToast, clearToasts }}>
165
165
  {children}
166
- <div
166
+ <div data-sonance-name="toast"
167
167
  className={cn(
168
168
  "fixed z-[100] flex flex-col gap-2 pointer-events-none",
169
169
  positionClasses[position]
@@ -18,7 +18,7 @@ const ToggleGroup = React.forwardRef<
18
18
  React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
19
19
  VariantProps<typeof toggleVariants>
20
20
  >(({ className, variant, size, children, ...props }, ref) => (
21
- <ToggleGroupPrimitive.Root
21
+ <ToggleGroupPrimitive.Root data-sonance-name="toggle-group"
22
22
  ref={ref}
23
23
  className={cn("flex items-center justify-center gap-1", className)}
24
24
  {...props}
@@ -33,7 +33,7 @@ const Toggle = React.forwardRef<
33
33
  React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
34
34
  VariantProps<typeof toggleVariants>
35
35
  >(({ className, variant, size, ...props }, ref) => (
36
- <TogglePrimitive.Root
36
+ <TogglePrimitive.Root data-sonance-name="toggle"
37
37
  ref={ref}
38
38
  className={cn(toggleVariants({ variant, size, className }))}
39
39
  {...props}