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.
- package/dist/assets/api/sonance-analyze/route.ts +1116 -0
- package/dist/assets/api/sonance-assets/route.ts +113 -0
- package/dist/assets/api/sonance-components/route.ts +41 -0
- package/dist/assets/api/sonance-inject-id/route.ts +363 -0
- package/dist/assets/api/sonance-save-logo/route.ts +426 -0
- package/dist/assets/api/sonance-theme/route.ts +106 -0
- package/dist/assets/brand-system.ts +1265 -0
- package/dist/assets/components/accordion.stories.tsx +26 -26
- package/dist/assets/components/accordion.tsx +3 -3
- package/dist/assets/components/alert-dialog.stories.tsx +7 -7
- package/dist/assets/components/alert-dialog.tsx +2 -1
- package/dist/assets/components/alert.stories.tsx +3 -3
- package/dist/assets/components/alert.tsx +4 -3
- package/dist/assets/components/aspect-ratio.stories.tsx +4 -1
- package/dist/assets/components/autocomplete.stories.tsx +9 -9
- package/dist/assets/components/autocomplete.tsx +3 -3
- package/dist/assets/components/avatar.stories.tsx +5 -5
- package/dist/assets/components/avatar.tsx +4 -4
- package/dist/assets/components/badge.stories.tsx +10 -10
- package/dist/assets/components/badge.tsx +3 -3
- package/dist/assets/components/breadcrumbs.stories.tsx +7 -7
- package/dist/assets/components/breadcrumbs.tsx +13 -8
- package/dist/assets/components/button.stories.tsx +74 -74
- package/dist/assets/components/button.tsx +2 -0
- package/dist/assets/components/calendar.stories.tsx +11 -11
- package/dist/assets/components/calendar.tsx +4 -4
- package/dist/assets/components/card.stories.tsx +22 -22
- package/dist/assets/components/card.tsx +7 -3
- package/dist/assets/components/carousel.stories.tsx +6 -6
- package/dist/assets/components/carousel.tsx +10 -8
- package/dist/assets/components/chart.tsx +5 -5
- package/dist/assets/components/checkbox-group.stories.tsx +6 -6
- package/dist/assets/components/checkbox-group.tsx +3 -3
- package/dist/assets/components/checkbox.stories.tsx +23 -20
- package/dist/assets/components/checkbox.tsx +13 -16
- package/dist/assets/components/code.stories.tsx +24 -24
- package/dist/assets/components/code.tsx +7 -14
- package/dist/assets/components/collapsible.stories.tsx +3 -3
- package/dist/assets/components/command.stories.tsx +14 -14
- package/dist/assets/components/command.tsx +4 -3
- package/dist/assets/components/context-menu.stories.tsx +1 -1
- package/dist/assets/components/context-menu.tsx +3 -7
- package/dist/assets/components/date-input.stories.tsx +9 -9
- package/dist/assets/components/date-input.tsx +2 -2
- package/dist/assets/components/date-picker.stories.tsx +9 -9
- package/dist/assets/components/date-picker.tsx +3 -3
- package/dist/assets/components/date-range-picker.stories.tsx +12 -12
- package/dist/assets/components/date-range-picker.tsx +3 -3
- package/dist/assets/components/dialog.stories.tsx +40 -40
- package/dist/assets/components/dialog.tsx +8 -12
- package/dist/assets/components/divider.stories.tsx +30 -30
- package/dist/assets/components/divider.tsx +4 -8
- package/dist/assets/components/drawer.stories.tsx +32 -31
- package/dist/assets/components/drawer.tsx +7 -6
- package/dist/assets/components/dropdown-menu.tsx +3 -7
- package/dist/assets/components/dropdown.stories.tsx +12 -12
- package/dist/assets/components/dropdown.tsx +5 -5
- package/dist/assets/components/form.stories.tsx +30 -29
- package/dist/assets/components/form.tsx +5 -5
- package/dist/assets/components/hover-card.stories.tsx +12 -10
- package/dist/assets/components/hover-card.tsx +1 -1
- package/dist/assets/components/image.stories.tsx +48 -25
- package/dist/assets/components/image.tsx +8 -5
- package/dist/assets/components/input-otp.stories.tsx +15 -15
- package/dist/assets/components/input-otp.tsx +5 -5
- package/dist/assets/components/input.stories.tsx +30 -25
- package/dist/assets/components/input.tsx +7 -4
- package/dist/assets/components/kbd.stories.tsx +34 -34
- package/dist/assets/components/kbd.tsx +5 -5
- package/dist/assets/components/link.stories.tsx +36 -36
- package/dist/assets/components/link.tsx +4 -0
- package/dist/assets/components/listbox.stories.tsx +5 -5
- package/dist/assets/components/listbox.tsx +4 -4
- package/dist/assets/components/menubar.tsx +3 -7
- package/dist/assets/components/navbar.stories.tsx +24 -24
- package/dist/assets/components/navbar.tsx +8 -14
- package/dist/assets/components/navigation-menu.stories.tsx +11 -9
- package/dist/assets/components/navigation-menu.tsx +1 -1
- package/dist/assets/components/number-input.stories.tsx +11 -11
- package/dist/assets/components/number-input.tsx +3 -3
- package/dist/assets/components/pagination.stories.tsx +13 -13
- package/dist/assets/components/pagination.tsx +6 -6
- package/dist/assets/components/popover.stories.tsx +35 -35
- package/dist/assets/components/popover.tsx +98 -15
- package/dist/assets/components/progress.stories.tsx +5 -5
- package/dist/assets/components/progress.tsx +5 -5
- package/dist/assets/components/radio-group.stories.tsx +7 -7
- package/dist/assets/components/radio-group.tsx +3 -3
- package/dist/assets/components/range-calendar.stories.tsx +18 -18
- package/dist/assets/components/range-calendar.tsx +3 -3
- package/dist/assets/components/resizable.stories.tsx +23 -23
- package/dist/assets/components/resizable.tsx +1 -1
- package/dist/assets/components/scroll-area.stories.tsx +15 -15
- package/dist/assets/components/scroll-area.tsx +1 -1
- package/dist/assets/components/scroll-shadow.stories.tsx +17 -17
- package/dist/assets/components/scroll-shadow.tsx +2 -2
- package/dist/assets/components/select.stories.tsx +20 -19
- package/dist/assets/components/select.tsx +10 -6
- package/dist/assets/components/separator.tsx +1 -1
- package/dist/assets/components/sheet.tsx +3 -7
- package/dist/assets/components/sidebar.stories.tsx +30 -30
- package/dist/assets/components/sidebar.tsx +24 -27
- package/dist/assets/components/skeleton.stories.tsx +3 -3
- package/dist/assets/components/skeleton.tsx +2 -2
- package/dist/assets/components/slider.stories.tsx +6 -6
- package/dist/assets/components/slider.tsx +3 -3
- package/dist/assets/components/spacer.stories.tsx +11 -11
- package/dist/assets/components/spacer.tsx +2 -2
- package/dist/assets/components/spinner.stories.tsx +8 -8
- package/dist/assets/components/spinner.tsx +5 -5
- package/dist/assets/components/switch.stories.tsx +24 -20
- package/dist/assets/components/switch.tsx +14 -6
- package/dist/assets/components/table.stories.tsx +7 -7
- package/dist/assets/components/table.tsx +8 -8
- package/dist/assets/components/tabs.stories.tsx +37 -37
- package/dist/assets/components/tabs.tsx +3 -3
- package/dist/assets/components/textarea.stories.tsx +13 -12
- package/dist/assets/components/textarea.tsx +3 -3
- package/dist/assets/components/theme-toggle.stories.tsx +31 -30
- package/dist/assets/components/theme-toggle.tsx +2 -2
- package/dist/assets/components/time-input.stories.tsx +16 -16
- package/dist/assets/components/time-input.tsx +2 -2
- package/dist/assets/components/toast.stories.tsx +8 -5
- package/dist/assets/components/toast.tsx +6 -6
- package/dist/assets/components/toggle-group.tsx +1 -1
- package/dist/assets/components/toggle.tsx +1 -1
- package/dist/assets/components/tooltip.stories.tsx +49 -27
- package/dist/assets/components/tooltip.tsx +1 -1
- package/dist/assets/components/user.stories.tsx +23 -23
- package/dist/assets/components/user.tsx +7 -4
- package/dist/assets/dev-tools/SonanceDevTools.tsx +4201 -0
- package/dist/assets/dev-tools/index.ts +10 -0
- package/dist/assets/globals.css +9 -0
- package/dist/assets/styles/brand-overrides.css +37 -0
- package/dist/index.js +1776 -7
- 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>
|