@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,255 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaImage, WakaImageGallery } from './index'
3
+ import * as React from 'react'
4
+
5
+ const meta: Meta<typeof WakaImage> = {
6
+ title: 'Components/Display/WakaImage',
7
+ component: WakaImage,
8
+ parameters: {
9
+ layout: 'centered',
10
+ docs: {
11
+ description: {
12
+ component: 'An image component with lazy loading, zoom functionality, and error handling.',
13
+ },
14
+ },
15
+ },
16
+ tags: ['autodocs'],
17
+ argTypes: {
18
+ objectFit: {
19
+ control: 'select',
20
+ options: ['contain', 'cover', 'fill', 'none', 'scale-down'],
21
+ description: 'How the image should fit its container',
22
+ },
23
+ rounded: {
24
+ control: 'select',
25
+ options: ['none', 'sm', 'md', 'lg', 'xl', 'full'],
26
+ description: 'Border radius',
27
+ },
28
+ zoomable: {
29
+ control: 'boolean',
30
+ description: 'Enable zoom on click',
31
+ },
32
+ lazy: {
33
+ control: 'boolean',
34
+ description: 'Enable lazy loading',
35
+ },
36
+ },
37
+ }
38
+
39
+ export default meta
40
+ type Story = StoryObj<typeof WakaImage>
41
+
42
+ const sampleImage = 'https://images.unsplash.com/photo-1682687220742-aba13b6e50ba?w=800&q=80'
43
+ const sampleImage2 = 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&q=80'
44
+
45
+ export const Default: Story = {
46
+ args: {
47
+ src: sampleImage,
48
+ alt: 'Beautiful landscape',
49
+ width: 400,
50
+ height: 300,
51
+ },
52
+ }
53
+
54
+ export const Zoomable: Story = {
55
+ args: {
56
+ src: sampleImage,
57
+ alt: 'Zoomable image',
58
+ width: 400,
59
+ height: 300,
60
+ zoomable: true,
61
+ },
62
+ }
63
+
64
+ export const AspectRatios: Story = {
65
+ render: () => (
66
+ <div className="space-y-6">
67
+ <div>
68
+ <p className="text-sm text-muted-foreground mb-2">16:9</p>
69
+ <WakaImage
70
+ src={sampleImage}
71
+ alt="16:9 aspect ratio"
72
+ aspectRatio="16/9"
73
+ width={400}
74
+ />
75
+ </div>
76
+ <div>
77
+ <p className="text-sm text-muted-foreground mb-2">4:3</p>
78
+ <WakaImage
79
+ src={sampleImage}
80
+ alt="4:3 aspect ratio"
81
+ aspectRatio="4/3"
82
+ width={400}
83
+ />
84
+ </div>
85
+ <div>
86
+ <p className="text-sm text-muted-foreground mb-2">1:1 (Square)</p>
87
+ <WakaImage
88
+ src={sampleImage}
89
+ alt="Square"
90
+ aspectRatio="1/1"
91
+ width={300}
92
+ />
93
+ </div>
94
+ </div>
95
+ ),
96
+ }
97
+
98
+ export const RoundedVariants: Story = {
99
+ render: () => (
100
+ <div className="grid grid-cols-3 gap-4">
101
+ {(['none', 'sm', 'md', 'lg', 'xl', 'full'] as const).map((rounded) => (
102
+ <div key={rounded} className="text-center">
103
+ <WakaImage
104
+ src={sampleImage}
105
+ alt={`Rounded ${rounded}`}
106
+ width={150}
107
+ height={150}
108
+ rounded={rounded}
109
+ />
110
+ <p className="text-xs text-muted-foreground mt-2">{rounded}</p>
111
+ </div>
112
+ ))}
113
+ </div>
114
+ ),
115
+ }
116
+
117
+ export const ObjectFit: Story = {
118
+ render: () => (
119
+ <div className="grid grid-cols-3 gap-4">
120
+ {(['contain', 'cover', 'fill', 'none', 'scale-down'] as const).map((fit) => (
121
+ <div key={fit} className="text-center">
122
+ <WakaImage
123
+ src={sampleImage2}
124
+ alt={`Object fit ${fit}`}
125
+ width={150}
126
+ height={150}
127
+ objectFit={fit}
128
+ containerClassName="border"
129
+ />
130
+ <p className="text-xs text-muted-foreground mt-2">{fit}</p>
131
+ </div>
132
+ ))}
133
+ </div>
134
+ ),
135
+ }
136
+
137
+ export const WithPlaceholder: Story = {
138
+ render: () => (
139
+ <div className="space-y-4">
140
+ <p className="text-sm text-muted-foreground">Images with color placeholder while loading</p>
141
+ <div className="flex gap-4">
142
+ <WakaImage
143
+ src={sampleImage}
144
+ alt="With placeholder"
145
+ width={200}
146
+ height={150}
147
+ placeholderColor="bg-blue-100"
148
+ />
149
+ <WakaImage
150
+ src={sampleImage2}
151
+ alt="With placeholder"
152
+ width={200}
153
+ height={150}
154
+ placeholderColor="bg-purple-100"
155
+ />
156
+ </div>
157
+ </div>
158
+ ),
159
+ }
160
+
161
+ export const ErrorState: Story = {
162
+ render: () => (
163
+ <div className="space-y-4">
164
+ <p className="text-sm text-muted-foreground">Image with invalid URL shows error state</p>
165
+ <WakaImage
166
+ src="https://invalid-url.com/image.jpg"
167
+ alt="Broken image"
168
+ width={300}
169
+ height={200}
170
+ />
171
+ </div>
172
+ ),
173
+ }
174
+
175
+ export const NoLoader: Story = {
176
+ args: {
177
+ src: sampleImage,
178
+ alt: 'No loader',
179
+ width: 400,
180
+ height: 300,
181
+ showLoader: false,
182
+ },
183
+ }
184
+
185
+ export const Gallery: Story = {
186
+ render: () => (
187
+ <div className="w-[600px]">
188
+ <WakaImageGallery
189
+ images={[
190
+ { src: 'https://images.unsplash.com/photo-1682687220742-aba13b6e50ba?w=800&q=80', alt: 'Mountain' },
191
+ { src: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&q=80', alt: 'Lake' },
192
+ { src: 'https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=800&q=80', alt: 'Forest' },
193
+ { src: 'https://images.unsplash.com/photo-1501785888041-af3ef285b470?w=800&q=80', alt: 'Beach' },
194
+ { src: 'https://images.unsplash.com/photo-1426604966848-d7adac402bff?w=800&q=80', alt: 'Valley' },
195
+ { src: 'https://images.unsplash.com/photo-1472214103451-9374bd1c798e?w=800&q=80', alt: 'Sunset' },
196
+ ]}
197
+ columns={3}
198
+ gap={4}
199
+ aspectRatio="1/1"
200
+ />
201
+ </div>
202
+ ),
203
+ }
204
+
205
+ export const GalleryCustomColumns: Story = {
206
+ render: () => (
207
+ <div className="space-y-8 w-[700px]">
208
+ <div>
209
+ <p className="text-sm text-muted-foreground mb-2">2 Columns</p>
210
+ <WakaImageGallery
211
+ images={[
212
+ { src: 'https://images.unsplash.com/photo-1682687220742-aba13b6e50ba?w=800&q=80', alt: 'Mountain' },
213
+ { src: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&q=80', alt: 'Lake' },
214
+ { src: 'https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=800&q=80', alt: 'Forest' },
215
+ { src: 'https://images.unsplash.com/photo-1501785888041-af3ef285b470?w=800&q=80', alt: 'Beach' },
216
+ ]}
217
+ columns={2}
218
+ aspectRatio="16/9"
219
+ />
220
+ </div>
221
+ <div>
222
+ <p className="text-sm text-muted-foreground mb-2">4 Columns</p>
223
+ <WakaImageGallery
224
+ images={[
225
+ { src: 'https://images.unsplash.com/photo-1682687220742-aba13b6e50ba?w=800&q=80', alt: 'Mountain' },
226
+ { src: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&q=80', alt: 'Lake' },
227
+ { src: 'https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=800&q=80', alt: 'Forest' },
228
+ { src: 'https://images.unsplash.com/photo-1501785888041-af3ef285b470?w=800&q=80', alt: 'Beach' },
229
+ ]}
230
+ columns={4}
231
+ aspectRatio="1/1"
232
+ />
233
+ </div>
234
+ </div>
235
+ ),
236
+ }
237
+
238
+ export const ProductImage: Story = {
239
+ render: () => (
240
+ <div className="p-6 border rounded-lg w-[400px]">
241
+ <WakaImage
242
+ src={sampleImage}
243
+ alt="Product image"
244
+ aspectRatio="1/1"
245
+ zoomable
246
+ rounded="lg"
247
+ />
248
+ <div className="mt-4">
249
+ <h3 className="font-semibold">Product Name</h3>
250
+ <p className="text-sm text-muted-foreground">Click image to zoom</p>
251
+ <p className="text-lg font-bold mt-2">$99.99</p>
252
+ </div>
253
+ </div>
254
+ ),
255
+ }
@@ -0,0 +1,300 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaIncidentTimeline } from './index'
3
+ import type { Incident, IncidentSeverity, IncidentStatus } from './index'
4
+ import * as React from 'react'
5
+
6
+ const sampleIncidents: Incident[] = [
7
+ {
8
+ id: 'inc-001',
9
+ title: 'Database Connection Failures',
10
+ description: 'Multiple services experiencing intermittent database connection issues.',
11
+ severity: 'critical',
12
+ status: 'investigating',
13
+ startedAt: new Date(Date.now() - 30 * 60 * 1000),
14
+ impact: { services: 5, users: 12500 },
15
+ updates: [
16
+ { message: 'Investigating increased error rates in database connections.', timestamp: new Date(Date.now() - 25 * 60 * 1000), status: 'Investigating' },
17
+ { message: 'Identified potential connection pool exhaustion.', timestamp: new Date(Date.now() - 15 * 60 * 1000), status: 'Identified' },
18
+ ],
19
+ },
20
+ {
21
+ id: 'inc-002',
22
+ title: 'API Latency Degradation',
23
+ description: 'API response times elevated above normal thresholds.',
24
+ severity: 'major',
25
+ status: 'identified',
26
+ startedAt: new Date(Date.now() - 2 * 60 * 60 * 1000),
27
+ impact: { services: 2, users: 8000 },
28
+ updates: [
29
+ { message: 'Identified upstream cache invalidation causing increased load.', timestamp: new Date(Date.now() - 90 * 60 * 1000), status: 'Identified' },
30
+ ],
31
+ },
32
+ {
33
+ id: 'inc-003',
34
+ title: 'CDN Cache Purge',
35
+ description: 'Scheduled maintenance for CDN cache refresh.',
36
+ severity: 'info',
37
+ status: 'monitoring',
38
+ startedAt: new Date(Date.now() - 4 * 60 * 60 * 1000),
39
+ },
40
+ {
41
+ id: 'inc-004',
42
+ title: 'Authentication Service Outage',
43
+ description: 'Users unable to log in or authenticate.',
44
+ severity: 'critical',
45
+ status: 'resolved',
46
+ startedAt: new Date(Date.now() - 24 * 60 * 60 * 1000),
47
+ resolvedAt: new Date(Date.now() - 20 * 60 * 60 * 1000),
48
+ impact: { services: 3, users: 45000 },
49
+ updates: [
50
+ { message: 'Investigating auth service unavailability.', timestamp: new Date(Date.now() - 24 * 60 * 60 * 1000), status: 'Investigating' },
51
+ { message: 'Root cause identified: SSL certificate expiration.', timestamp: new Date(Date.now() - 22 * 60 * 60 * 1000), status: 'Identified' },
52
+ { message: 'Certificate renewed and services recovering.', timestamp: new Date(Date.now() - 21 * 60 * 60 * 1000), status: 'Monitoring' },
53
+ { message: 'All services fully restored.', timestamp: new Date(Date.now() - 20 * 60 * 60 * 1000), status: 'Resolved' },
54
+ ],
55
+ },
56
+ {
57
+ id: 'inc-005',
58
+ title: 'Minor UI Bug in Dashboard',
59
+ description: 'Some chart tooltips not displaying correctly.',
60
+ severity: 'minor',
61
+ status: 'resolved',
62
+ startedAt: new Date(Date.now() - 48 * 60 * 60 * 1000),
63
+ resolvedAt: new Date(Date.now() - 46 * 60 * 60 * 1000),
64
+ },
65
+ ]
66
+
67
+ const meta: Meta<typeof WakaIncidentTimeline> = {
68
+ title: 'Components/DevOps/WakaIncidentTimeline',
69
+ component: WakaIncidentTimeline,
70
+ parameters: {
71
+ layout: 'centered',
72
+ docs: {
73
+ description: {
74
+ component: 'An incident timeline with severity indicators, status badges, duration tracking, impact metrics, and filtering capabilities.',
75
+ },
76
+ },
77
+ },
78
+ tags: ['autodocs'],
79
+ argTypes: {
80
+ showFilters: {
81
+ control: 'boolean',
82
+ description: 'Show filter controls',
83
+ },
84
+ showImpact: {
85
+ control: 'boolean',
86
+ description: 'Show impact indicators',
87
+ },
88
+ maxItems: {
89
+ control: { type: 'number', min: 1, max: 20, step: 1 },
90
+ description: 'Maximum number of incidents to display',
91
+ },
92
+ },
93
+ }
94
+
95
+ export default meta
96
+ type Story = StoryObj<typeof WakaIncidentTimeline>
97
+
98
+ export const Default: Story = {
99
+ args: {
100
+ incidents: sampleIncidents,
101
+ },
102
+ render: (args) => (
103
+ <div className="w-[600px]">
104
+ <WakaIncidentTimeline {...args} onIncidentClick={(id) => console.log('Clicked:', id)} />
105
+ </div>
106
+ ),
107
+ }
108
+
109
+ export const AllSeverities: Story = {
110
+ render: () => {
111
+ const severityIncidents: Incident[] = [
112
+ { id: '1', title: 'Critical: Service Down', severity: 'critical', status: 'investigating', startedAt: new Date(Date.now() - 30 * 60 * 1000) },
113
+ { id: '2', title: 'Major: High Latency', severity: 'major', status: 'identified', startedAt: new Date(Date.now() - 60 * 60 * 1000) },
114
+ { id: '3', title: 'Minor: UI Glitch', severity: 'minor', status: 'monitoring', startedAt: new Date(Date.now() - 2 * 60 * 60 * 1000) },
115
+ { id: '4', title: 'Info: Scheduled Maintenance', severity: 'info', status: 'resolved', startedAt: new Date(Date.now() - 3 * 60 * 60 * 1000), resolvedAt: new Date(Date.now() - 2.5 * 60 * 60 * 1000) },
116
+ ]
117
+
118
+ return (
119
+ <div className="w-[600px]">
120
+ <WakaIncidentTimeline incidents={severityIncidents} />
121
+ </div>
122
+ )
123
+ },
124
+ }
125
+
126
+ export const AllStatuses: Story = {
127
+ render: () => {
128
+ const statusIncidents: Incident[] = [
129
+ { id: '1', title: 'Investigating Issue', severity: 'major', status: 'investigating', startedAt: new Date(Date.now() - 15 * 60 * 1000) },
130
+ { id: '2', title: 'Root Cause Identified', severity: 'major', status: 'identified', startedAt: new Date(Date.now() - 45 * 60 * 1000) },
131
+ { id: '3', title: 'Fix Deployed - Monitoring', severity: 'minor', status: 'monitoring', startedAt: new Date(Date.now() - 90 * 60 * 1000) },
132
+ { id: '4', title: 'Issue Resolved', severity: 'minor', status: 'resolved', startedAt: new Date(Date.now() - 4 * 60 * 60 * 1000), resolvedAt: new Date(Date.now() - 3 * 60 * 60 * 1000) },
133
+ ]
134
+
135
+ return (
136
+ <div className="w-[600px]">
137
+ <WakaIncidentTimeline incidents={statusIncidents} />
138
+ </div>
139
+ )
140
+ },
141
+ }
142
+
143
+ export const WithFilters: Story = {
144
+ render: () => (
145
+ <div className="w-[600px]">
146
+ <WakaIncidentTimeline
147
+ incidents={sampleIncidents}
148
+ showFilters
149
+ onIncidentClick={(id) => console.log('Clicked:', id)}
150
+ />
151
+ </div>
152
+ ),
153
+ }
154
+
155
+ export const NoFilters: Story = {
156
+ render: () => (
157
+ <div className="w-[600px]">
158
+ <WakaIncidentTimeline
159
+ incidents={sampleIncidents}
160
+ showFilters={false}
161
+ />
162
+ </div>
163
+ ),
164
+ }
165
+
166
+ export const WithImpact: Story = {
167
+ render: () => (
168
+ <div className="w-[600px]">
169
+ <WakaIncidentTimeline
170
+ incidents={sampleIncidents}
171
+ showImpact
172
+ />
173
+ </div>
174
+ ),
175
+ }
176
+
177
+ export const NoImpact: Story = {
178
+ render: () => (
179
+ <div className="w-[600px]">
180
+ <WakaIncidentTimeline
181
+ incidents={sampleIncidents}
182
+ showImpact={false}
183
+ />
184
+ </div>
185
+ ),
186
+ }
187
+
188
+ export const LimitedItems: Story = {
189
+ render: () => (
190
+ <div className="w-[600px]">
191
+ <p className="text-sm text-muted-foreground mb-4">
192
+ Limited to 3 incidents
193
+ </p>
194
+ <WakaIncidentTimeline
195
+ incidents={sampleIncidents}
196
+ maxItems={3}
197
+ />
198
+ </div>
199
+ ),
200
+ }
201
+
202
+ export const Empty: Story = {
203
+ render: () => (
204
+ <div className="w-[600px]">
205
+ <WakaIncidentTimeline incidents={[]} />
206
+ </div>
207
+ ),
208
+ }
209
+
210
+ export const Interactive: Story = {
211
+ render: () => {
212
+ const [incidents, setIncidents] = React.useState<Incident[]>([
213
+ { id: '1', title: 'Current Investigation', severity: 'major', status: 'investigating', startedAt: new Date() },
214
+ ])
215
+
216
+ const addIncident = (severity: IncidentSeverity) => {
217
+ const newIncident: Incident = {
218
+ id: `inc-${Date.now()}`,
219
+ title: `New ${severity} incident`,
220
+ description: `Auto-generated ${severity} incident for demo`,
221
+ severity,
222
+ status: 'investigating',
223
+ startedAt: new Date(),
224
+ impact: { services: Math.floor(Math.random() * 5) + 1, users: Math.floor(Math.random() * 10000) },
225
+ }
226
+ setIncidents(prev => [newIncident, ...prev])
227
+ }
228
+
229
+ const updateStatus = (id: string, status: IncidentStatus) => {
230
+ setIncidents(prev => prev.map(inc =>
231
+ inc.id === id
232
+ ? { ...inc, status, resolvedAt: status === 'resolved' ? new Date() : undefined }
233
+ : inc
234
+ ))
235
+ }
236
+
237
+ return (
238
+ <div className="w-[600px] space-y-4">
239
+ <WakaIncidentTimeline
240
+ incidents={incidents}
241
+ showFilters
242
+ showImpact
243
+ onIncidentClick={(id) => console.log('Clicked:', id)}
244
+ />
245
+
246
+ <div className="flex flex-wrap gap-2">
247
+ <button
248
+ onClick={() => addIncident('critical')}
249
+ className="px-3 py-1.5 text-xs rounded bg-red-500 text-white"
250
+ >
251
+ Add Critical
252
+ </button>
253
+ <button
254
+ onClick={() => addIncident('major')}
255
+ className="px-3 py-1.5 text-xs rounded bg-orange-500 text-white"
256
+ >
257
+ Add Major
258
+ </button>
259
+ <button
260
+ onClick={() => addIncident('minor')}
261
+ className="px-3 py-1.5 text-xs rounded bg-yellow-500 text-black"
262
+ >
263
+ Add Minor
264
+ </button>
265
+ {incidents.length > 0 && incidents[0].status !== 'resolved' && (
266
+ <button
267
+ onClick={() => updateStatus(incidents[0].id, 'resolved')}
268
+ className="px-3 py-1.5 text-xs rounded bg-green-500 text-white"
269
+ >
270
+ Resolve First
271
+ </button>
272
+ )}
273
+ </div>
274
+ </div>
275
+ )
276
+ },
277
+ }
278
+
279
+ export const StatusPage: Story = {
280
+ render: () => (
281
+ <div className="w-[700px] p-6 rounded-xl border bg-card">
282
+ <div className="flex items-center justify-between mb-6">
283
+ <div>
284
+ <h2 className="text-xl font-bold">System Status</h2>
285
+ <p className="text-sm text-muted-foreground">Current and past incidents</p>
286
+ </div>
287
+ <div className="flex items-center gap-2">
288
+ <div className="w-2 h-2 rounded-full bg-yellow-500 animate-pulse" />
289
+ <span className="text-sm font-medium text-yellow-600">Partial Outage</span>
290
+ </div>
291
+ </div>
292
+
293
+ <WakaIncidentTimeline
294
+ incidents={sampleIncidents}
295
+ showFilters
296
+ showImpact
297
+ />
298
+ </div>
299
+ ),
300
+ }