@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,405 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaMorphButton, WakaAsyncButton, useMorphButton } from './index'
3
+ import type { MorphState } from './index'
4
+ import * as React from 'react'
5
+ import { Send, Download, Trash2, Upload, Check, X, Loader2 } from 'lucide-react'
6
+
7
+ const meta: Meta<typeof WakaMorphButton> = {
8
+ title: 'Components/Effects/WakaMorphButton',
9
+ component: WakaMorphButton,
10
+ parameters: {
11
+ layout: 'centered',
12
+ docs: {
13
+ description: {
14
+ component: 'A morphing button that transitions between states (idle, loading, success, error) with smooth animations.',
15
+ },
16
+ },
17
+ },
18
+ tags: ['autodocs'],
19
+ argTypes: {
20
+ state: {
21
+ control: 'select',
22
+ options: ['idle', 'loading', 'success', 'error'],
23
+ description: 'Current button state',
24
+ },
25
+ variant: {
26
+ control: 'select',
27
+ options: ['default', 'outline', 'ghost'],
28
+ description: 'Button variant',
29
+ },
30
+ size: {
31
+ control: 'select',
32
+ options: ['sm', 'default', 'lg'],
33
+ description: 'Button size',
34
+ },
35
+ rounded: {
36
+ control: 'select',
37
+ options: ['default', 'sm', 'lg', 'full'],
38
+ description: 'Border radius',
39
+ },
40
+ hapticFeedback: {
41
+ control: 'boolean',
42
+ description: 'Enable haptic feedback on mobile',
43
+ },
44
+ animationDuration: {
45
+ control: { type: 'range', min: 100, max: 500, step: 50 },
46
+ description: 'Animation duration in ms',
47
+ },
48
+ },
49
+ }
50
+
51
+ export default meta
52
+ type Story = StoryObj<typeof WakaMorphButton>
53
+
54
+ export const Default: Story = {
55
+ args: {},
56
+ render: (args) => {
57
+ const [state, setState] = React.useState<MorphState>('idle')
58
+
59
+ const handleClick = () => {
60
+ setState('loading')
61
+ setTimeout(() => {
62
+ setState('success')
63
+ }, 2000)
64
+ }
65
+
66
+ return (
67
+ <WakaMorphButton
68
+ state={state}
69
+ idleText="Submit"
70
+ loadingText="Submitting..."
71
+ successText="Done!"
72
+ onClick={handleClick}
73
+ onReset={() => setState('idle')}
74
+ />
75
+ )
76
+ },
77
+ }
78
+
79
+ export const States: Story = {
80
+ render: () => (
81
+ <div className="flex flex-wrap gap-4">
82
+ <WakaMorphButton state="idle" idleText="Idle State" />
83
+ <WakaMorphButton state="loading" idleText="Submit" loadingText="Loading..." />
84
+ <WakaMorphButton state="success" idleText="Submit" successText="Success!" />
85
+ <WakaMorphButton state="error" idleText="Submit" errorText="Failed!" />
86
+ </div>
87
+ ),
88
+ }
89
+
90
+ export const Variants: Story = {
91
+ render: () => {
92
+ const [states, setStates] = React.useState<Record<string, MorphState>>({
93
+ default: 'idle',
94
+ outline: 'idle',
95
+ ghost: 'idle',
96
+ })
97
+
98
+ const handleClick = (variant: string) => {
99
+ setStates((prev) => ({ ...prev, [variant]: 'loading' }))
100
+ setTimeout(() => {
101
+ setStates((prev) => ({ ...prev, [variant]: 'success' }))
102
+ }, 1500)
103
+ }
104
+
105
+ return (
106
+ <div className="flex gap-4">
107
+ <WakaMorphButton
108
+ variant="default"
109
+ state={states.default}
110
+ idleText="Default"
111
+ onClick={() => handleClick('default')}
112
+ onReset={() => setStates((p) => ({ ...p, default: 'idle' }))}
113
+ />
114
+ <WakaMorphButton
115
+ variant="outline"
116
+ state={states.outline}
117
+ idleText="Outline"
118
+ onClick={() => handleClick('outline')}
119
+ onReset={() => setStates((p) => ({ ...p, outline: 'idle' }))}
120
+ />
121
+ <WakaMorphButton
122
+ variant="ghost"
123
+ state={states.ghost}
124
+ idleText="Ghost"
125
+ onClick={() => handleClick('ghost')}
126
+ onReset={() => setStates((p) => ({ ...p, ghost: 'idle' }))}
127
+ />
128
+ </div>
129
+ )
130
+ },
131
+ }
132
+
133
+ export const Sizes: Story = {
134
+ render: () => (
135
+ <div className="flex items-center gap-4">
136
+ <WakaMorphButton size="sm" idleText="Small" />
137
+ <WakaMorphButton size="default" idleText="Default" />
138
+ <WakaMorphButton size="lg" idleText="Large" />
139
+ </div>
140
+ ),
141
+ }
142
+
143
+ export const Rounded: Story = {
144
+ render: () => (
145
+ <div className="flex gap-4">
146
+ <WakaMorphButton rounded="sm" idleText="Small" />
147
+ <WakaMorphButton rounded="default" idleText="Default" />
148
+ <WakaMorphButton rounded="lg" idleText="Large" />
149
+ <WakaMorphButton rounded="full" idleText="Full" />
150
+ </div>
151
+ ),
152
+ }
153
+
154
+ export const WithCustomIcons: Story = {
155
+ render: () => {
156
+ const [state, setState] = React.useState<MorphState>('idle')
157
+
158
+ const handleClick = () => {
159
+ setState('loading')
160
+ setTimeout(() => {
161
+ setState('success')
162
+ }, 2000)
163
+ }
164
+
165
+ return (
166
+ <WakaMorphButton
167
+ state={state}
168
+ idleText="Send Message"
169
+ loadingText="Sending..."
170
+ successText="Sent!"
171
+ errorText="Failed"
172
+ idleIcon={<Send className="h-4 w-4" />}
173
+ loadingIcon={<Loader2 className="h-4 w-4 animate-spin" />}
174
+ successIcon={<Check className="h-4 w-4" />}
175
+ errorIcon={<X className="h-4 w-4" />}
176
+ onClick={handleClick}
177
+ onReset={() => setState('idle')}
178
+ />
179
+ )
180
+ },
181
+ }
182
+
183
+ export const ErrorState: Story = {
184
+ render: () => {
185
+ const [state, setState] = React.useState<MorphState>('idle')
186
+
187
+ const handleClick = () => {
188
+ setState('loading')
189
+ setTimeout(() => {
190
+ setState('error')
191
+ }, 2000)
192
+ }
193
+
194
+ return (
195
+ <WakaMorphButton
196
+ state={state}
197
+ idleText="Delete Item"
198
+ loadingText="Deleting..."
199
+ successText="Deleted!"
200
+ errorText="Delete Failed"
201
+ idleIcon={<Trash2 className="h-4 w-4" />}
202
+ onClick={handleClick}
203
+ onReset={() => setState('idle')}
204
+ />
205
+ )
206
+ },
207
+ }
208
+
209
+ export const AsyncButton: Story = {
210
+ render: () => {
211
+ const simulateUpload = async () => {
212
+ await new Promise((resolve) => setTimeout(resolve, 2000))
213
+ }
214
+
215
+ return (
216
+ <div className="space-y-4">
217
+ <p className="text-sm text-muted-foreground">
218
+ WakaAsyncButton handles async state automatically
219
+ </p>
220
+ <WakaAsyncButton
221
+ idleText="Upload File"
222
+ loadingText="Uploading..."
223
+ successText="Uploaded!"
224
+ errorText="Upload Failed"
225
+ idleIcon={<Upload className="h-4 w-4" />}
226
+ onClick={simulateUpload}
227
+ />
228
+ </div>
229
+ )
230
+ },
231
+ }
232
+
233
+ export const AsyncButtonWithError: Story = {
234
+ render: () => {
235
+ const simulateFailedUpload = async () => {
236
+ await new Promise((_, reject) =>
237
+ setTimeout(() => reject(new Error('Network error')), 2000)
238
+ )
239
+ }
240
+
241
+ return (
242
+ <div className="space-y-4">
243
+ <p className="text-sm text-muted-foreground">
244
+ Click to see error state
245
+ </p>
246
+ <WakaAsyncButton
247
+ idleText="Upload File"
248
+ loadingText="Uploading..."
249
+ successText="Uploaded!"
250
+ errorText="Upload Failed"
251
+ idleIcon={<Upload className="h-4 w-4" />}
252
+ onClick={simulateFailedUpload}
253
+ onError={(err) => console.log('Error:', err)}
254
+ />
255
+ </div>
256
+ )
257
+ },
258
+ }
259
+
260
+ export const WithHook: Story = {
261
+ render: () => {
262
+ const fetchData = async () => {
263
+ await new Promise((resolve) => setTimeout(resolve, 2000))
264
+ return { success: true }
265
+ }
266
+
267
+ const { state, execute, isLoading, isSuccess } = useMorphButton(fetchData, {
268
+ onSuccess: () => console.log('Success!'),
269
+ resetDelay: 3000,
270
+ })
271
+
272
+ return (
273
+ <div className="space-y-4">
274
+ <WakaMorphButton
275
+ state={state}
276
+ idleText="Fetch Data"
277
+ loadingText="Fetching..."
278
+ successText="Data Loaded!"
279
+ idleIcon={<Download className="h-4 w-4" />}
280
+ onClick={execute}
281
+ />
282
+ <p className="text-sm text-muted-foreground">
283
+ Loading: {isLoading ? 'Yes' : 'No'} | Success: {isSuccess ? 'Yes' : 'No'}
284
+ </p>
285
+ </div>
286
+ )
287
+ },
288
+ }
289
+
290
+ export const FormSubmission: Story = {
291
+ render: () => {
292
+ const [state, setState] = React.useState<MorphState>('idle')
293
+ const [email, setEmail] = React.useState('')
294
+
295
+ const handleSubmit = (e: React.FormEvent) => {
296
+ e.preventDefault()
297
+ setState('loading')
298
+ setTimeout(() => {
299
+ if (email.includes('@')) {
300
+ setState('success')
301
+ } else {
302
+ setState('error')
303
+ }
304
+ }, 1500)
305
+ }
306
+
307
+ return (
308
+ <form onSubmit={handleSubmit} className="w-[300px] space-y-4">
309
+ <div>
310
+ <label className="text-sm font-medium">Email</label>
311
+ <input
312
+ type="text"
313
+ value={email}
314
+ onChange={(e) => setEmail(e.target.value)}
315
+ className="w-full mt-1 px-3 py-2 border rounded-md"
316
+ placeholder="you@example.com"
317
+ />
318
+ </div>
319
+ <WakaMorphButton
320
+ type="submit"
321
+ className="w-full"
322
+ state={state}
323
+ idleText="Subscribe"
324
+ loadingText="Subscribing..."
325
+ successText="Subscribed!"
326
+ errorText="Invalid Email"
327
+ onReset={() => setState('idle')}
328
+ />
329
+ </form>
330
+ )
331
+ },
332
+ }
333
+
334
+ export const CustomResetDelay: Story = {
335
+ render: () => {
336
+ const [state, setState] = React.useState<MorphState>('idle')
337
+
338
+ return (
339
+ <div className="space-y-4">
340
+ <p className="text-sm text-muted-foreground">
341
+ Success state persists for 5 seconds
342
+ </p>
343
+ <WakaMorphButton
344
+ state={state}
345
+ idleText="Long Success"
346
+ loadingText="Processing..."
347
+ successText="Done! (5s)"
348
+ resetDelay={5000}
349
+ onClick={() => {
350
+ setState('loading')
351
+ setTimeout(() => setState('success'), 1500)
352
+ }}
353
+ onReset={() => setState('idle')}
354
+ />
355
+ </div>
356
+ )
357
+ },
358
+ }
359
+
360
+ export const NoHaptic: Story = {
361
+ render: () => {
362
+ const [state, setState] = React.useState<MorphState>('idle')
363
+
364
+ return (
365
+ <WakaMorphButton
366
+ state={state}
367
+ idleText="No Vibration"
368
+ hapticFeedback={false}
369
+ onClick={() => {
370
+ setState('loading')
371
+ setTimeout(() => setState('success'), 1500)
372
+ }}
373
+ onReset={() => setState('idle')}
374
+ />
375
+ )
376
+ },
377
+ }
378
+
379
+ export const CustomAnimationDuration: Story = {
380
+ render: () => (
381
+ <div className="flex gap-4">
382
+ <div className="text-center">
383
+ <WakaMorphButton
384
+ idleText="Fast (100ms)"
385
+ animationDuration={100}
386
+ state="loading"
387
+ />
388
+ </div>
389
+ <div className="text-center">
390
+ <WakaMorphButton
391
+ idleText="Normal (300ms)"
392
+ animationDuration={300}
393
+ state="loading"
394
+ />
395
+ </div>
396
+ <div className="text-center">
397
+ <WakaMorphButton
398
+ idleText="Slow (500ms)"
399
+ animationDuration={500}
400
+ state="loading"
401
+ />
402
+ </div>
403
+ </div>
404
+ ),
405
+ }