@wakastellar/ui 2.3.4 → 2.4.0

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 (194) hide show
  1. package/dist/blocks/dashboard/index.d.ts +4 -1
  2. package/dist/blocks/empty-states/index.d.ts +4 -1
  3. package/dist/blocks/error-pages/index.d.ts +4 -1
  4. package/dist/blocks/index.d.ts +1 -1
  5. package/dist/blocks/landing/index.d.ts +4 -1
  6. package/dist/blocks/pricing/index.d.ts +5 -1
  7. package/dist/blocks/sidebar/index.d.ts +5 -1
  8. package/dist/index.cjs.js +130 -130
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.es.js +7905 -7856
  11. package/dist/stories/Button.d.ts +14 -0
  12. package/dist/stories/Button.stories.d.ts +8 -0
  13. package/dist/stories/Header.d.ts +11 -0
  14. package/dist/stories/Header.stories.d.ts +6 -0
  15. package/dist/stories/Page.d.ts +2 -0
  16. package/dist/stories/Page.stories.d.ts +6 -0
  17. package/dist/types/index.d.ts +1 -0
  18. package/dist/types/link.d.ts +23 -0
  19. package/package.json +11 -3
  20. package/src/blocks/activity-timeline/ActivityTimeline.stories.tsx +460 -0
  21. package/src/blocks/apm-overview/APMOverview.stories.tsx +435 -0
  22. package/src/blocks/auth-2fa/Auth2FA.stories.tsx +308 -0
  23. package/src/blocks/calendar-view/CalendarView.stories.tsx +398 -0
  24. package/src/blocks/chat/Chat.stories.tsx +466 -0
  25. package/src/blocks/chat-interface/ChatInterface.stories.tsx +412 -0
  26. package/src/blocks/checkout-flow/CheckoutFlow.stories.tsx +408 -0
  27. package/src/blocks/cicd-builder/CICDBuilder.stories.tsx +499 -0
  28. package/src/blocks/cloud-cost-dashboard/CloudCostDashboard.stories.tsx +356 -0
  29. package/src/blocks/container-orchestrator/ContainerOrchestrator.stories.tsx +461 -0
  30. package/src/blocks/dashboard/Dashboard.stories.tsx +559 -0
  31. package/src/blocks/dashboard/index.tsx +68 -27
  32. package/src/blocks/dashboard-kpi/DashboardKPI.stories.tsx +422 -0
  33. package/src/blocks/database-admin/DatabaseAdmin.stories.tsx +393 -0
  34. package/src/blocks/deployment-dashboard/DeploymentDashboard.stories.tsx +457 -0
  35. package/src/blocks/empty-states/EmptyStates.stories.tsx +467 -0
  36. package/src/blocks/empty-states/index.tsx +26 -8
  37. package/src/blocks/error-pages/ErrorPages.stories.tsx +401 -0
  38. package/src/blocks/error-pages/index.tsx +26 -8
  39. package/src/blocks/faq/FAQ.stories.tsx +416 -0
  40. package/src/blocks/file-manager/FileManager.stories.tsx +413 -0
  41. package/src/blocks/footer/Footer.stories.tsx +328 -0
  42. package/src/blocks/gitops-sync-status/GitOpsSyncStatus.stories.tsx +529 -0
  43. package/src/blocks/header/WakaHeader.stories.tsx +455 -0
  44. package/src/blocks/headtab/Headtab.stories.tsx +369 -0
  45. package/src/blocks/i18n-editor/I18nEditor.stories.tsx +451 -0
  46. package/src/blocks/incident-manager/IncidentManager.stories.tsx +464 -0
  47. package/src/blocks/index.ts +1 -1
  48. package/src/blocks/infrastructure-map/InfrastructureMap.stories.tsx +533 -0
  49. package/src/blocks/kanban-board/KanbanBoard.stories.tsx +494 -0
  50. package/src/blocks/landing/WakaLanding.stories.tsx +449 -0
  51. package/src/blocks/landing/index.tsx +125 -66
  52. package/src/blocks/language-selector/LanguageSelector.stories.tsx +345 -0
  53. package/src/blocks/layout/Layout.stories.tsx +373 -0
  54. package/src/blocks/login/Login.stories.tsx +443 -0
  55. package/src/blocks/on-call-schedule/OnCallSchedule.stories.tsx +381 -0
  56. package/src/blocks/player-profile/PlayerProfile.stories.tsx +316 -0
  57. package/src/blocks/pricing/WakaPricing.stories.tsx +530 -0
  58. package/src/blocks/pricing/index.tsx +38 -4
  59. package/src/blocks/profile/Profile.stories.tsx +371 -0
  60. package/src/blocks/release-notes/ReleaseNotes.stories.tsx +431 -0
  61. package/src/blocks/settings/Settings.stories.tsx +520 -0
  62. package/src/blocks/sidebar/WakaSidebar.stories.tsx +513 -0
  63. package/src/blocks/sidebar/index.tsx +49 -20
  64. package/src/blocks/theme-creator-block/ThemeCreatorBlock.stories.tsx +370 -0
  65. package/src/blocks/user-management/UserManagement.stories.tsx +411 -0
  66. package/src/blocks/wizard/Wizard.stories.tsx +683 -0
  67. package/src/components/accordion/Accordion.stories.tsx +93 -0
  68. package/src/components/alert/Alert.stories.tsx +95 -0
  69. package/src/components/alert-dialog/AlertDialog.stories.tsx +126 -0
  70. package/src/components/aspect-ratio/AspectRatio.stories.tsx +118 -0
  71. package/src/components/avatar/Avatar.stories.tsx +104 -0
  72. package/src/components/button/Button.stories.tsx +12 -1
  73. package/src/components/calendar/Calendar.stories.tsx +102 -0
  74. package/src/components/card/Card.stories.tsx +125 -0
  75. package/src/components/checkbox/Checkbox.stories.tsx +100 -0
  76. package/src/components/code/Code.stories.tsx +402 -0
  77. package/src/components/collapsible/Collapsible.stories.tsx +123 -0
  78. package/src/components/command/Command.stories.tsx +207 -0
  79. package/src/components/context-menu/ContextMenu.stories.tsx +220 -0
  80. package/src/components/dialog/Dialog.stories.tsx +157 -0
  81. package/src/components/dropdown-menu/DropdownMenu.stories.tsx +225 -0
  82. package/src/components/form/Form.stories.tsx +413 -0
  83. package/src/components/hover-card/HoverCard.stories.tsx +148 -0
  84. package/src/components/input-otp/InputOTP.stories.tsx +255 -0
  85. package/src/components/label/Label.stories.tsx +68 -0
  86. package/src/components/menubar/Menubar.stories.tsx +278 -0
  87. package/src/components/navigation-menu/NavigationMenu.stories.tsx +202 -0
  88. package/src/components/popover/Popover.stories.tsx +199 -0
  89. package/src/components/progress/Progress.stories.tsx +104 -0
  90. package/src/components/radio-group/RadioGroup.stories.tsx +138 -0
  91. package/src/components/scroll-area/ScrollArea.stories.tsx +153 -0
  92. package/src/components/select/Select.stories.tsx +146 -0
  93. package/src/components/separator/Separator.stories.tsx +117 -0
  94. package/src/components/sheet/Sheet.stories.tsx +195 -0
  95. package/src/components/skeleton/Skeleton.stories.tsx +114 -0
  96. package/src/components/slider/Slider.stories.tsx +157 -0
  97. package/src/components/switch/Switch.stories.tsx +114 -0
  98. package/src/components/table/Table.stories.tsx +153 -0
  99. package/src/components/tabs/Tabs.stories.tsx +155 -0
  100. package/src/components/textarea/Textarea.stories.tsx +116 -0
  101. package/src/components/toast/Toast.stories.tsx +160 -0
  102. package/src/components/toggle/Toggle.stories.tsx +125 -0
  103. package/src/components/tooltip/Tooltip.stories.tsx +133 -0
  104. package/src/components/typography/Typography.stories.tsx +207 -0
  105. package/src/components/waka-3d-pie-chart/Waka3DPieChart.stories.tsx +308 -0
  106. package/src/components/waka-achievement-unlock/WakaAchievementUnlock.stories.tsx +353 -0
  107. package/src/components/waka-artifact-list/WakaArtifactList.stories.tsx +258 -0
  108. package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +224 -0
  109. package/src/components/waka-badge-showcase/WakaBadgeShowcase.stories.tsx +269 -0
  110. package/src/components/waka-barcode/WakaBarcode.stories.tsx +227 -0
  111. package/src/components/waka-bottom-sheet/WakaBottomSheet.stories.tsx +408 -0
  112. package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +237 -0
  113. package/src/components/waka-build-matrix/WakaBuildMatrix.stories.tsx +328 -0
  114. package/src/components/waka-carousel/WakaCarousel.stories.tsx +296 -0
  115. package/src/components/waka-charts/WakaCharts.stories.tsx +519 -0
  116. package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +200 -0
  117. package/src/components/waka-combobox/WakaCombobox.stories.tsx +250 -0
  118. package/src/components/waka-container-list/WakaContainerList.stories.tsx +315 -0
  119. package/src/components/waka-contribution-graph/WakaContributionGraph.stories.tsx +354 -0
  120. package/src/components/waka-cost-breakdown/WakaCostBreakdown.stories.tsx +348 -0
  121. package/src/components/waka-daily-reward/WakaDailyReward.stories.tsx +365 -0
  122. package/src/components/waka-database-card/WakaDatabaseCard.stories.tsx +306 -0
  123. package/src/components/waka-date-range-picker/WakaDateRangePicker.stories.tsx +339 -0
  124. package/src/components/waka-datetime-picker/WakaDateTimePicker.stories.tsx +317 -0
  125. package/src/components/waka-deployment-lane/WakaDeploymentLane.stories.tsx +292 -0
  126. package/src/components/waka-dock/WakaDock.stories.tsx +332 -0
  127. package/src/components/waka-drawer/WakaDrawer.stories.tsx +437 -0
  128. package/src/components/waka-env-var-editor/WakaEnvVarEditor.stories.tsx +263 -0
  129. package/src/components/waka-error-shake/WakaErrorShake.stories.tsx +410 -0
  130. package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +239 -0
  131. package/src/components/waka-flow-diagram/WakaFlowDiagram.stories.tsx +365 -0
  132. package/src/components/waka-funnel-chart/WakaFunnelChart.stories.tsx +281 -0
  133. package/src/components/waka-glow-card/WakaGlowCard.stories.tsx +274 -0
  134. package/src/components/waka-haptic-button/WakaHapticButton.stories.tsx +349 -0
  135. package/src/components/waka-health-pulse/WakaHealthPulse.stories.tsx +293 -0
  136. package/src/components/waka-heatmap/WakaHeatmap.stories.tsx +376 -0
  137. package/src/components/waka-image/WakaImage.stories.tsx +255 -0
  138. package/src/components/waka-incident-timeline/WakaIncidentTimeline.stories.tsx +300 -0
  139. package/src/components/waka-kanban/WakaKanban.stories.tsx +399 -0
  140. package/src/components/waka-kubernetes-overview/WakaKubernetesOverview.stories.tsx +281 -0
  141. package/src/components/waka-leaderboard/WakaLeaderboard.stories.tsx +300 -0
  142. package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +313 -0
  143. package/src/components/waka-loading-orbit/WakaLoadingOrbit.stories.tsx +413 -0
  144. package/src/components/waka-log-viewer/WakaLogViewer.stories.tsx +312 -0
  145. package/src/components/waka-loot-box/WakaLootBox.stories.tsx +374 -0
  146. package/src/components/waka-metric-sparkline/WakaMetricSparkline.stories.tsx +312 -0
  147. package/src/components/waka-migration-list/WakaMigrationList.stories.tsx +289 -0
  148. package/src/components/waka-modal/WakaModal.stories.tsx +434 -0
  149. package/src/components/waka-morph-button/WakaMorphButton.stories.tsx +405 -0
  150. package/src/components/waka-network-topology/WakaNetworkTopology.stories.tsx +364 -0
  151. package/src/components/waka-notifications/WakaNotifications.stories.tsx +290 -0
  152. package/src/components/waka-number-input/WakaNumberInput.stories.tsx +282 -0
  153. package/src/components/waka-pagination/WakaPagination.stories.tsx +328 -0
  154. package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +318 -0
  155. package/src/components/waka-pipeline-view/WakaPipelineView.stories.tsx +386 -0
  156. package/src/components/waka-player-card/WakaPlayerCard.stories.tsx +333 -0
  157. package/src/components/waka-pod-card/WakaPodCard.stories.tsx +435 -0
  158. package/src/components/waka-qrcode/WakaQRCode.stories.tsx +232 -0
  159. package/src/components/waka-query-explain/WakaQueryExplain.stories.tsx +407 -0
  160. package/src/components/waka-quest-card/WakaQuestCard.stories.tsx +394 -0
  161. package/src/components/waka-quota-bar/WakaQuotaBar.stories.tsx +435 -0
  162. package/src/components/waka-radar-score/WakaRadarScore.stories.tsx +372 -0
  163. package/src/components/waka-resource-gauge/WakaResourceGauge.stories.tsx +366 -0
  164. package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +238 -0
  165. package/src/components/waka-sankey-diagram/WakaSankeyDiagram.stories.tsx +389 -0
  166. package/src/components/waka-scratch-card/WakaScratchCard.stories.tsx +388 -0
  167. package/src/components/waka-secret-card/WakaSecretCard.stories.tsx +314 -0
  168. package/src/components/waka-segmented-control/WakaSegmentedControl.stories.tsx +309 -0
  169. package/src/components/waka-server-rack/WakaServerRack.stories.tsx +382 -0
  170. package/src/components/waka-service-graph/WakaServiceGraph.stories.tsx +262 -0
  171. package/src/components/waka-skeleton-wave/WakaSkeletonWave.stories.tsx +321 -0
  172. package/src/components/waka-skill-tree/WakaSkillTree.stories.tsx +308 -0
  173. package/src/components/waka-spin-wheel/WakaSpinWheel.stories.tsx +368 -0
  174. package/src/components/waka-spinner/WakaSpinner.stories.tsx +156 -0
  175. package/src/components/waka-stat/WakaStat.stories.tsx +334 -0
  176. package/src/components/waka-status-matrix/WakaStatusMatrix.stories.tsx +331 -0
  177. package/src/components/waka-stepper/WakaStepper.stories.tsx +468 -0
  178. package/src/components/waka-streak-counter/WakaStreakCounter.stories.tsx +235 -0
  179. package/src/components/waka-success-explosion/WakaSuccessExplosion.stories.tsx +389 -0
  180. package/src/components/waka-tabs-morph/WakaTabsMorph.stories.tsx +471 -0
  181. package/src/components/waka-terminal-output/WakaTerminalOutput.stories.tsx +351 -0
  182. package/src/components/waka-test-report/WakaTestReport.stories.tsx +322 -0
  183. package/src/components/waka-tilt-card/WakaTiltCard.stories.tsx +300 -0
  184. package/src/components/waka-time-picker/WakaTimePicker.stories.tsx +227 -0
  185. package/src/components/waka-timeline/WakaTimeline.stories.tsx +383 -0
  186. package/src/components/waka-tournament-bracket/WakaTournamentBracket.stories.tsx +375 -0
  187. package/src/components/waka-trace-viewer/WakaTraceViewer.stories.tsx +445 -0
  188. package/src/components/waka-tree/WakaTree.stories.tsx +359 -0
  189. package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +378 -0
  190. package/src/components/waka-typewriter/WakaTypewriter.stories.tsx +366 -0
  191. package/src/components/waka-versus-card/WakaVersusCard.stories.tsx +530 -0
  192. package/src/components/waka-video/WakaVideo.stories.tsx +203 -0
  193. package/src/components/waka-virtual-list/WakaVirtualList.stories.tsx +273 -0
  194. package/src/components/waka-xp-bar/WakaXPBar.stories.tsx +305 -0
@@ -0,0 +1,413 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import {
3
+ Form,
4
+ FormControl,
5
+ FormDescription,
6
+ FormField,
7
+ FormItem,
8
+ FormLabel,
9
+ FormMessage,
10
+ } from './index'
11
+ import { Input } from '../input'
12
+ import { Button } from '../button'
13
+ import { Textarea } from '../textarea'
14
+ import { Checkbox } from '../checkbox'
15
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../select'
16
+ import * as React from 'react'
17
+ import { useForm } from 'react-hook-form'
18
+
19
+ const meta: Meta<typeof Form> = {
20
+ title: 'Components/Forms/Form',
21
+ component: Form,
22
+ parameters: {
23
+ layout: 'centered',
24
+ docs: {
25
+ description: {
26
+ component: 'Form components for building accessible forms with React Hook Form.',
27
+ },
28
+ },
29
+ },
30
+ tags: ['autodocs'],
31
+ }
32
+
33
+ export default meta
34
+ type Story = StoryObj<typeof Form>
35
+
36
+ interface LoginFormData {
37
+ email: string
38
+ password: string
39
+ }
40
+
41
+ export const LoginForm: Story = {
42
+ render: function LoginFormDemo() {
43
+ const form = useForm<LoginFormData>({
44
+ defaultValues: {
45
+ email: '',
46
+ password: '',
47
+ },
48
+ })
49
+
50
+ const onSubmit = (data: LoginFormData) => {
51
+ console.log('Form submitted:', data)
52
+ alert(`Login: ${data.email}`)
53
+ }
54
+
55
+ return (
56
+ <Form {...form}>
57
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4 w-[350px]">
58
+ <FormField
59
+ control={form.control}
60
+ name="email"
61
+ rules={{ required: 'Email is required' }}
62
+ render={({ field }) => (
63
+ <FormItem>
64
+ <FormLabel>Email</FormLabel>
65
+ <FormControl>
66
+ <Input type="email" placeholder="email@example.com" {...field} />
67
+ </FormControl>
68
+ <FormMessage />
69
+ </FormItem>
70
+ )}
71
+ />
72
+ <FormField
73
+ control={form.control}
74
+ name="password"
75
+ rules={{ required: 'Password is required', minLength: { value: 8, message: 'Minimum 8 characters' } }}
76
+ render={({ field }) => (
77
+ <FormItem>
78
+ <FormLabel>Password</FormLabel>
79
+ <FormControl>
80
+ <Input type="password" placeholder="********" {...field} />
81
+ </FormControl>
82
+ <FormMessage />
83
+ </FormItem>
84
+ )}
85
+ />
86
+ <Button type="submit" className="w-full">
87
+ Sign In
88
+ </Button>
89
+ </form>
90
+ </Form>
91
+ )
92
+ },
93
+ }
94
+
95
+ interface ContactFormData {
96
+ name: string
97
+ email: string
98
+ subject: string
99
+ message: string
100
+ }
101
+
102
+ export const ContactForm: Story = {
103
+ render: function ContactFormDemo() {
104
+ const form = useForm<ContactFormData>({
105
+ defaultValues: {
106
+ name: '',
107
+ email: '',
108
+ subject: '',
109
+ message: '',
110
+ },
111
+ })
112
+
113
+ const onSubmit = (data: ContactFormData) => {
114
+ console.log('Contact form:', data)
115
+ alert('Message sent!')
116
+ }
117
+
118
+ return (
119
+ <Form {...form}>
120
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4 w-[400px]">
121
+ <div className="grid grid-cols-2 gap-4">
122
+ <FormField
123
+ control={form.control}
124
+ name="name"
125
+ rules={{ required: 'Name is required' }}
126
+ render={({ field }) => (
127
+ <FormItem>
128
+ <FormLabel>Name</FormLabel>
129
+ <FormControl>
130
+ <Input placeholder="Your name" {...field} />
131
+ </FormControl>
132
+ <FormMessage />
133
+ </FormItem>
134
+ )}
135
+ />
136
+ <FormField
137
+ control={form.control}
138
+ name="email"
139
+ rules={{ required: 'Email is required' }}
140
+ render={({ field }) => (
141
+ <FormItem>
142
+ <FormLabel>Email</FormLabel>
143
+ <FormControl>
144
+ <Input type="email" placeholder="email@example.com" {...field} />
145
+ </FormControl>
146
+ <FormMessage />
147
+ </FormItem>
148
+ )}
149
+ />
150
+ </div>
151
+ <FormField
152
+ control={form.control}
153
+ name="subject"
154
+ rules={{ required: 'Subject is required' }}
155
+ render={({ field }) => (
156
+ <FormItem>
157
+ <FormLabel>Subject</FormLabel>
158
+ <FormControl>
159
+ <Input placeholder="Subject" {...field} />
160
+ </FormControl>
161
+ <FormMessage />
162
+ </FormItem>
163
+ )}
164
+ />
165
+ <FormField
166
+ control={form.control}
167
+ name="message"
168
+ rules={{ required: 'Message is required' }}
169
+ render={({ field }) => (
170
+ <FormItem>
171
+ <FormLabel>Message</FormLabel>
172
+ <FormControl>
173
+ <Textarea placeholder="Your message..." rows={4} {...field} />
174
+ </FormControl>
175
+ <FormDescription>
176
+ Please provide as much detail as possible.
177
+ </FormDescription>
178
+ <FormMessage />
179
+ </FormItem>
180
+ )}
181
+ />
182
+ <Button type="submit" className="w-full">
183
+ Send Message
184
+ </Button>
185
+ </form>
186
+ </Form>
187
+ )
188
+ },
189
+ }
190
+
191
+ interface ProfileFormData {
192
+ username: string
193
+ bio: string
194
+ role: string
195
+ notifications: boolean
196
+ }
197
+
198
+ export const ProfileForm: Story = {
199
+ render: function ProfileFormDemo() {
200
+ const form = useForm<ProfileFormData>({
201
+ defaultValues: {
202
+ username: '',
203
+ bio: '',
204
+ role: '',
205
+ notifications: true,
206
+ },
207
+ })
208
+
209
+ const onSubmit = (data: ProfileFormData) => {
210
+ console.log('Profile:', data)
211
+ alert('Profile updated!')
212
+ }
213
+
214
+ return (
215
+ <Form {...form}>
216
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6 w-[400px]">
217
+ <FormField
218
+ control={form.control}
219
+ name="username"
220
+ rules={{ required: 'Username is required' }}
221
+ render={({ field }) => (
222
+ <FormItem>
223
+ <FormLabel>Username</FormLabel>
224
+ <FormControl>
225
+ <Input placeholder="username" {...field} />
226
+ </FormControl>
227
+ <FormDescription>
228
+ This is your public display name.
229
+ </FormDescription>
230
+ <FormMessage />
231
+ </FormItem>
232
+ )}
233
+ />
234
+ <FormField
235
+ control={form.control}
236
+ name="bio"
237
+ render={({ field }) => (
238
+ <FormItem>
239
+ <FormLabel>Bio</FormLabel>
240
+ <FormControl>
241
+ <Textarea placeholder="Tell us about yourself" rows={3} {...field} />
242
+ </FormControl>
243
+ <FormDescription>
244
+ Brief description for your profile.
245
+ </FormDescription>
246
+ <FormMessage />
247
+ </FormItem>
248
+ )}
249
+ />
250
+ <FormField
251
+ control={form.control}
252
+ name="role"
253
+ rules={{ required: 'Please select a role' }}
254
+ render={({ field }) => (
255
+ <FormItem>
256
+ <FormLabel>Role</FormLabel>
257
+ <Select onValueChange={field.onChange} defaultValue={field.value}>
258
+ <FormControl>
259
+ <SelectTrigger>
260
+ <SelectValue placeholder="Select your role" />
261
+ </SelectTrigger>
262
+ </FormControl>
263
+ <SelectContent>
264
+ <SelectItem value="developer">Developer</SelectItem>
265
+ <SelectItem value="designer">Designer</SelectItem>
266
+ <SelectItem value="manager">Manager</SelectItem>
267
+ <SelectItem value="other">Other</SelectItem>
268
+ </SelectContent>
269
+ </Select>
270
+ <FormMessage />
271
+ </FormItem>
272
+ )}
273
+ />
274
+ <FormField
275
+ control={form.control}
276
+ name="notifications"
277
+ render={({ field }) => (
278
+ <FormItem className="flex flex-row items-start space-x-3 space-y-0 rounded-md border p-4">
279
+ <FormControl>
280
+ <Checkbox
281
+ checked={field.value}
282
+ onCheckedChange={field.onChange}
283
+ />
284
+ </FormControl>
285
+ <div className="space-y-1 leading-none">
286
+ <FormLabel>Email notifications</FormLabel>
287
+ <FormDescription>
288
+ Receive emails about account activity.
289
+ </FormDescription>
290
+ </div>
291
+ </FormItem>
292
+ )}
293
+ />
294
+ <Button type="submit" className="w-full">
295
+ Save Profile
296
+ </Button>
297
+ </form>
298
+ </Form>
299
+ )
300
+ },
301
+ }
302
+
303
+ interface SettingsFormData {
304
+ displayName: string
305
+ email: string
306
+ marketing: boolean
307
+ security: boolean
308
+ }
309
+
310
+ export const SettingsForm: Story = {
311
+ render: function SettingsFormDemo() {
312
+ const form = useForm<SettingsFormData>({
313
+ defaultValues: {
314
+ displayName: 'John Doe',
315
+ email: 'john@example.com',
316
+ marketing: false,
317
+ security: true,
318
+ },
319
+ })
320
+
321
+ const onSubmit = (data: SettingsFormData) => {
322
+ console.log('Settings:', data)
323
+ alert('Settings saved!')
324
+ }
325
+
326
+ return (
327
+ <Form {...form}>
328
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6 w-[400px]">
329
+ <div>
330
+ <h3 className="text-lg font-medium">Account Settings</h3>
331
+ <p className="text-sm text-muted-foreground">
332
+ Manage your account preferences
333
+ </p>
334
+ </div>
335
+ <div className="space-y-4">
336
+ <FormField
337
+ control={form.control}
338
+ name="displayName"
339
+ render={({ field }) => (
340
+ <FormItem>
341
+ <FormLabel>Display Name</FormLabel>
342
+ <FormControl>
343
+ <Input {...field} />
344
+ </FormControl>
345
+ <FormMessage />
346
+ </FormItem>
347
+ )}
348
+ />
349
+ <FormField
350
+ control={form.control}
351
+ name="email"
352
+ render={({ field }) => (
353
+ <FormItem>
354
+ <FormLabel>Email</FormLabel>
355
+ <FormControl>
356
+ <Input type="email" {...field} />
357
+ </FormControl>
358
+ <FormMessage />
359
+ </FormItem>
360
+ )}
361
+ />
362
+ </div>
363
+ <div>
364
+ <h4 className="text-sm font-medium mb-3">Email Preferences</h4>
365
+ <div className="space-y-3">
366
+ <FormField
367
+ control={form.control}
368
+ name="marketing"
369
+ render={({ field }) => (
370
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-3">
371
+ <div className="space-y-0.5">
372
+ <FormLabel className="text-base">Marketing emails</FormLabel>
373
+ <FormDescription>
374
+ Receive product updates and promotions.
375
+ </FormDescription>
376
+ </div>
377
+ <FormControl>
378
+ <Checkbox
379
+ checked={field.value}
380
+ onCheckedChange={field.onChange}
381
+ />
382
+ </FormControl>
383
+ </FormItem>
384
+ )}
385
+ />
386
+ <FormField
387
+ control={form.control}
388
+ name="security"
389
+ render={({ field }) => (
390
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-3">
391
+ <div className="space-y-0.5">
392
+ <FormLabel className="text-base">Security alerts</FormLabel>
393
+ <FormDescription>
394
+ Get notified about security events.
395
+ </FormDescription>
396
+ </div>
397
+ <FormControl>
398
+ <Checkbox
399
+ checked={field.value}
400
+ onCheckedChange={field.onChange}
401
+ />
402
+ </FormControl>
403
+ </FormItem>
404
+ )}
405
+ />
406
+ </div>
407
+ </div>
408
+ <Button type="submit">Save Changes</Button>
409
+ </form>
410
+ </Form>
411
+ )
412
+ },
413
+ }
@@ -0,0 +1,148 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { HoverCard, HoverCardContent, HoverCardTrigger } from './index'
3
+ import { Avatar, AvatarFallback, AvatarImage } from '../avatar'
4
+ import { Button } from '../button'
5
+ import { CalendarDays } from 'lucide-react'
6
+
7
+ const meta: Meta<typeof HoverCard> = {
8
+ title: 'Components/HoverCard',
9
+ component: HoverCard,
10
+ parameters: {
11
+ layout: 'centered',
12
+ docs: {
13
+ description: {
14
+ component: 'For sighted users to preview content available behind a link.',
15
+ },
16
+ },
17
+ },
18
+ tags: ['autodocs'],
19
+ }
20
+
21
+ export default meta
22
+ type Story = StoryObj<typeof HoverCard>
23
+
24
+ export const Default: Story = {
25
+ args: {},
26
+ render: (args) => (
27
+ <HoverCard {...args}>
28
+ <HoverCardTrigger asChild>
29
+ <Button variant="link">@nextjs</Button>
30
+ </HoverCardTrigger>
31
+ <HoverCardContent className="w-80">
32
+ <div className="flex justify-between space-x-4">
33
+ <Avatar>
34
+ <AvatarImage src="https://github.com/vercel.png" />
35
+ <AvatarFallback>VC</AvatarFallback>
36
+ </Avatar>
37
+ <div className="space-y-1">
38
+ <h4 className="text-sm font-semibold">@nextjs</h4>
39
+ <p className="text-sm">
40
+ The React Framework – created and maintained by @vercel.
41
+ </p>
42
+ <div className="flex items-center pt-2">
43
+ <CalendarDays className="mr-2 h-4 w-4 opacity-70" />{' '}
44
+ <span className="text-xs text-muted-foreground">
45
+ Joined December 2021
46
+ </span>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </HoverCardContent>
51
+ </HoverCard>
52
+ ),
53
+ }
54
+
55
+ export const UserProfile: Story = {
56
+ render: () => (
57
+ <HoverCard>
58
+ <HoverCardTrigger asChild>
59
+ <a href="#" className="text-sm font-medium hover:underline">John Doe</a>
60
+ </HoverCardTrigger>
61
+ <HoverCardContent className="w-80">
62
+ <div className="flex space-x-4">
63
+ <Avatar className="h-12 w-12">
64
+ <AvatarImage src="https://github.com/shadcn.png" />
65
+ <AvatarFallback>JD</AvatarFallback>
66
+ </Avatar>
67
+ <div className="space-y-1">
68
+ <h4 className="text-sm font-semibold">John Doe</h4>
69
+ <p className="text-sm text-muted-foreground">
70
+ Software Engineer at Acme Inc.
71
+ </p>
72
+ <div className="flex items-center gap-4 pt-2 text-xs text-muted-foreground">
73
+ <span><strong className="text-foreground">1.2k</strong> followers</span>
74
+ <span><strong className="text-foreground">342</strong> following</span>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ </HoverCardContent>
79
+ </HoverCard>
80
+ ),
81
+ }
82
+
83
+ export const ProductPreview: Story = {
84
+ render: () => (
85
+ <HoverCard>
86
+ <HoverCardTrigger asChild>
87
+ <Button variant="outline">View Product</Button>
88
+ </HoverCardTrigger>
89
+ <HoverCardContent className="w-80">
90
+ <div className="space-y-3">
91
+ <div className="h-32 bg-muted rounded-md" />
92
+ <div>
93
+ <h4 className="font-semibold">Premium Headphones</h4>
94
+ <p className="text-sm text-muted-foreground">
95
+ High-quality wireless headphones with active noise cancellation.
96
+ </p>
97
+ </div>
98
+ <div className="flex items-center justify-between">
99
+ <span className="text-lg font-bold">$299.00</span>
100
+ <span className="text-sm text-green-600">In Stock</span>
101
+ </div>
102
+ </div>
103
+ </HoverCardContent>
104
+ </HoverCard>
105
+ ),
106
+ }
107
+
108
+ export const Positions: Story = {
109
+ render: () => (
110
+ <div className="flex gap-8 items-center">
111
+ <HoverCard>
112
+ <HoverCardTrigger asChild>
113
+ <Button variant="outline">Top</Button>
114
+ </HoverCardTrigger>
115
+ <HoverCardContent side="top">
116
+ <p className="text-sm">This appears on top</p>
117
+ </HoverCardContent>
118
+ </HoverCard>
119
+
120
+ <HoverCard>
121
+ <HoverCardTrigger asChild>
122
+ <Button variant="outline">Right</Button>
123
+ </HoverCardTrigger>
124
+ <HoverCardContent side="right">
125
+ <p className="text-sm">This appears on the right</p>
126
+ </HoverCardContent>
127
+ </HoverCard>
128
+
129
+ <HoverCard>
130
+ <HoverCardTrigger asChild>
131
+ <Button variant="outline">Bottom</Button>
132
+ </HoverCardTrigger>
133
+ <HoverCardContent side="bottom">
134
+ <p className="text-sm">This appears on bottom</p>
135
+ </HoverCardContent>
136
+ </HoverCard>
137
+
138
+ <HoverCard>
139
+ <HoverCardTrigger asChild>
140
+ <Button variant="outline">Left</Button>
141
+ </HoverCardTrigger>
142
+ <HoverCardContent side="left">
143
+ <p className="text-sm">This appears on the left</p>
144
+ </HoverCardContent>
145
+ </HoverCard>
146
+ </div>
147
+ ),
148
+ }