@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.
- package/dist/blocks/dashboard/index.d.ts +4 -1
- package/dist/blocks/empty-states/index.d.ts +4 -1
- package/dist/blocks/error-pages/index.d.ts +4 -1
- package/dist/blocks/index.d.ts +1 -1
- package/dist/blocks/landing/index.d.ts +4 -1
- package/dist/blocks/pricing/index.d.ts +5 -1
- package/dist/blocks/sidebar/index.d.ts +5 -1
- package/dist/index.cjs.js +130 -130
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +7905 -7856
- package/dist/stories/Button.d.ts +14 -0
- package/dist/stories/Button.stories.d.ts +8 -0
- package/dist/stories/Header.d.ts +11 -0
- package/dist/stories/Header.stories.d.ts +6 -0
- package/dist/stories/Page.d.ts +2 -0
- package/dist/stories/Page.stories.d.ts +6 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/link.d.ts +23 -0
- package/package.json +11 -3
- package/src/blocks/activity-timeline/ActivityTimeline.stories.tsx +460 -0
- package/src/blocks/apm-overview/APMOverview.stories.tsx +435 -0
- package/src/blocks/auth-2fa/Auth2FA.stories.tsx +308 -0
- package/src/blocks/calendar-view/CalendarView.stories.tsx +398 -0
- package/src/blocks/chat/Chat.stories.tsx +466 -0
- package/src/blocks/chat-interface/ChatInterface.stories.tsx +412 -0
- package/src/blocks/checkout-flow/CheckoutFlow.stories.tsx +408 -0
- package/src/blocks/cicd-builder/CICDBuilder.stories.tsx +499 -0
- package/src/blocks/cloud-cost-dashboard/CloudCostDashboard.stories.tsx +356 -0
- package/src/blocks/container-orchestrator/ContainerOrchestrator.stories.tsx +461 -0
- package/src/blocks/dashboard/Dashboard.stories.tsx +559 -0
- package/src/blocks/dashboard/index.tsx +68 -27
- package/src/blocks/dashboard-kpi/DashboardKPI.stories.tsx +422 -0
- package/src/blocks/database-admin/DatabaseAdmin.stories.tsx +393 -0
- package/src/blocks/deployment-dashboard/DeploymentDashboard.stories.tsx +457 -0
- package/src/blocks/empty-states/EmptyStates.stories.tsx +467 -0
- package/src/blocks/empty-states/index.tsx +26 -8
- package/src/blocks/error-pages/ErrorPages.stories.tsx +401 -0
- package/src/blocks/error-pages/index.tsx +26 -8
- package/src/blocks/faq/FAQ.stories.tsx +416 -0
- package/src/blocks/file-manager/FileManager.stories.tsx +413 -0
- package/src/blocks/footer/Footer.stories.tsx +328 -0
- package/src/blocks/gitops-sync-status/GitOpsSyncStatus.stories.tsx +529 -0
- package/src/blocks/header/WakaHeader.stories.tsx +455 -0
- package/src/blocks/headtab/Headtab.stories.tsx +369 -0
- package/src/blocks/i18n-editor/I18nEditor.stories.tsx +451 -0
- package/src/blocks/incident-manager/IncidentManager.stories.tsx +464 -0
- package/src/blocks/index.ts +1 -1
- package/src/blocks/infrastructure-map/InfrastructureMap.stories.tsx +533 -0
- package/src/blocks/kanban-board/KanbanBoard.stories.tsx +494 -0
- package/src/blocks/landing/WakaLanding.stories.tsx +449 -0
- package/src/blocks/landing/index.tsx +125 -66
- package/src/blocks/language-selector/LanguageSelector.stories.tsx +345 -0
- package/src/blocks/layout/Layout.stories.tsx +373 -0
- package/src/blocks/login/Login.stories.tsx +443 -0
- package/src/blocks/on-call-schedule/OnCallSchedule.stories.tsx +381 -0
- package/src/blocks/player-profile/PlayerProfile.stories.tsx +316 -0
- package/src/blocks/pricing/WakaPricing.stories.tsx +530 -0
- package/src/blocks/pricing/index.tsx +38 -4
- package/src/blocks/profile/Profile.stories.tsx +371 -0
- package/src/blocks/release-notes/ReleaseNotes.stories.tsx +431 -0
- package/src/blocks/settings/Settings.stories.tsx +520 -0
- package/src/blocks/sidebar/WakaSidebar.stories.tsx +513 -0
- package/src/blocks/sidebar/index.tsx +49 -20
- package/src/blocks/theme-creator-block/ThemeCreatorBlock.stories.tsx +370 -0
- package/src/blocks/user-management/UserManagement.stories.tsx +411 -0
- package/src/blocks/wizard/Wizard.stories.tsx +683 -0
- package/src/components/accordion/Accordion.stories.tsx +93 -0
- package/src/components/alert/Alert.stories.tsx +95 -0
- package/src/components/alert-dialog/AlertDialog.stories.tsx +126 -0
- package/src/components/aspect-ratio/AspectRatio.stories.tsx +118 -0
- package/src/components/avatar/Avatar.stories.tsx +104 -0
- package/src/components/button/Button.stories.tsx +12 -1
- package/src/components/calendar/Calendar.stories.tsx +102 -0
- package/src/components/card/Card.stories.tsx +125 -0
- package/src/components/checkbox/Checkbox.stories.tsx +100 -0
- package/src/components/code/Code.stories.tsx +402 -0
- package/src/components/collapsible/Collapsible.stories.tsx +123 -0
- package/src/components/command/Command.stories.tsx +207 -0
- package/src/components/context-menu/ContextMenu.stories.tsx +220 -0
- package/src/components/dialog/Dialog.stories.tsx +157 -0
- package/src/components/dropdown-menu/DropdownMenu.stories.tsx +225 -0
- package/src/components/form/Form.stories.tsx +413 -0
- package/src/components/hover-card/HoverCard.stories.tsx +148 -0
- package/src/components/input-otp/InputOTP.stories.tsx +255 -0
- package/src/components/label/Label.stories.tsx +68 -0
- package/src/components/menubar/Menubar.stories.tsx +278 -0
- package/src/components/navigation-menu/NavigationMenu.stories.tsx +202 -0
- package/src/components/popover/Popover.stories.tsx +199 -0
- package/src/components/progress/Progress.stories.tsx +104 -0
- package/src/components/radio-group/RadioGroup.stories.tsx +138 -0
- package/src/components/scroll-area/ScrollArea.stories.tsx +153 -0
- package/src/components/select/Select.stories.tsx +146 -0
- package/src/components/separator/Separator.stories.tsx +117 -0
- package/src/components/sheet/Sheet.stories.tsx +195 -0
- package/src/components/skeleton/Skeleton.stories.tsx +114 -0
- package/src/components/slider/Slider.stories.tsx +157 -0
- package/src/components/switch/Switch.stories.tsx +114 -0
- package/src/components/table/Table.stories.tsx +153 -0
- package/src/components/tabs/Tabs.stories.tsx +155 -0
- package/src/components/textarea/Textarea.stories.tsx +116 -0
- package/src/components/toast/Toast.stories.tsx +160 -0
- package/src/components/toggle/Toggle.stories.tsx +125 -0
- package/src/components/tooltip/Tooltip.stories.tsx +133 -0
- package/src/components/typography/Typography.stories.tsx +207 -0
- package/src/components/waka-3d-pie-chart/Waka3DPieChart.stories.tsx +308 -0
- package/src/components/waka-achievement-unlock/WakaAchievementUnlock.stories.tsx +353 -0
- package/src/components/waka-artifact-list/WakaArtifactList.stories.tsx +258 -0
- package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +224 -0
- package/src/components/waka-badge-showcase/WakaBadgeShowcase.stories.tsx +269 -0
- package/src/components/waka-barcode/WakaBarcode.stories.tsx +227 -0
- package/src/components/waka-bottom-sheet/WakaBottomSheet.stories.tsx +408 -0
- package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +237 -0
- package/src/components/waka-build-matrix/WakaBuildMatrix.stories.tsx +328 -0
- package/src/components/waka-carousel/WakaCarousel.stories.tsx +296 -0
- package/src/components/waka-charts/WakaCharts.stories.tsx +519 -0
- package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +200 -0
- package/src/components/waka-combobox/WakaCombobox.stories.tsx +250 -0
- package/src/components/waka-container-list/WakaContainerList.stories.tsx +315 -0
- package/src/components/waka-contribution-graph/WakaContributionGraph.stories.tsx +354 -0
- package/src/components/waka-cost-breakdown/WakaCostBreakdown.stories.tsx +348 -0
- package/src/components/waka-daily-reward/WakaDailyReward.stories.tsx +365 -0
- package/src/components/waka-database-card/WakaDatabaseCard.stories.tsx +306 -0
- package/src/components/waka-date-range-picker/WakaDateRangePicker.stories.tsx +339 -0
- package/src/components/waka-datetime-picker/WakaDateTimePicker.stories.tsx +317 -0
- package/src/components/waka-deployment-lane/WakaDeploymentLane.stories.tsx +292 -0
- package/src/components/waka-dock/WakaDock.stories.tsx +332 -0
- package/src/components/waka-drawer/WakaDrawer.stories.tsx +437 -0
- package/src/components/waka-env-var-editor/WakaEnvVarEditor.stories.tsx +263 -0
- package/src/components/waka-error-shake/WakaErrorShake.stories.tsx +410 -0
- package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +239 -0
- package/src/components/waka-flow-diagram/WakaFlowDiagram.stories.tsx +365 -0
- package/src/components/waka-funnel-chart/WakaFunnelChart.stories.tsx +281 -0
- package/src/components/waka-glow-card/WakaGlowCard.stories.tsx +274 -0
- package/src/components/waka-haptic-button/WakaHapticButton.stories.tsx +349 -0
- package/src/components/waka-health-pulse/WakaHealthPulse.stories.tsx +293 -0
- package/src/components/waka-heatmap/WakaHeatmap.stories.tsx +376 -0
- package/src/components/waka-image/WakaImage.stories.tsx +255 -0
- package/src/components/waka-incident-timeline/WakaIncidentTimeline.stories.tsx +300 -0
- package/src/components/waka-kanban/WakaKanban.stories.tsx +399 -0
- package/src/components/waka-kubernetes-overview/WakaKubernetesOverview.stories.tsx +281 -0
- package/src/components/waka-leaderboard/WakaLeaderboard.stories.tsx +300 -0
- package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +313 -0
- package/src/components/waka-loading-orbit/WakaLoadingOrbit.stories.tsx +413 -0
- package/src/components/waka-log-viewer/WakaLogViewer.stories.tsx +312 -0
- package/src/components/waka-loot-box/WakaLootBox.stories.tsx +374 -0
- package/src/components/waka-metric-sparkline/WakaMetricSparkline.stories.tsx +312 -0
- package/src/components/waka-migration-list/WakaMigrationList.stories.tsx +289 -0
- package/src/components/waka-modal/WakaModal.stories.tsx +434 -0
- package/src/components/waka-morph-button/WakaMorphButton.stories.tsx +405 -0
- package/src/components/waka-network-topology/WakaNetworkTopology.stories.tsx +364 -0
- package/src/components/waka-notifications/WakaNotifications.stories.tsx +290 -0
- package/src/components/waka-number-input/WakaNumberInput.stories.tsx +282 -0
- package/src/components/waka-pagination/WakaPagination.stories.tsx +328 -0
- package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +318 -0
- package/src/components/waka-pipeline-view/WakaPipelineView.stories.tsx +386 -0
- package/src/components/waka-player-card/WakaPlayerCard.stories.tsx +333 -0
- package/src/components/waka-pod-card/WakaPodCard.stories.tsx +435 -0
- package/src/components/waka-qrcode/WakaQRCode.stories.tsx +232 -0
- package/src/components/waka-query-explain/WakaQueryExplain.stories.tsx +407 -0
- package/src/components/waka-quest-card/WakaQuestCard.stories.tsx +394 -0
- package/src/components/waka-quota-bar/WakaQuotaBar.stories.tsx +435 -0
- package/src/components/waka-radar-score/WakaRadarScore.stories.tsx +372 -0
- package/src/components/waka-resource-gauge/WakaResourceGauge.stories.tsx +366 -0
- package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +238 -0
- package/src/components/waka-sankey-diagram/WakaSankeyDiagram.stories.tsx +389 -0
- package/src/components/waka-scratch-card/WakaScratchCard.stories.tsx +388 -0
- package/src/components/waka-secret-card/WakaSecretCard.stories.tsx +314 -0
- package/src/components/waka-segmented-control/WakaSegmentedControl.stories.tsx +309 -0
- package/src/components/waka-server-rack/WakaServerRack.stories.tsx +382 -0
- package/src/components/waka-service-graph/WakaServiceGraph.stories.tsx +262 -0
- package/src/components/waka-skeleton-wave/WakaSkeletonWave.stories.tsx +321 -0
- package/src/components/waka-skill-tree/WakaSkillTree.stories.tsx +308 -0
- package/src/components/waka-spin-wheel/WakaSpinWheel.stories.tsx +368 -0
- package/src/components/waka-spinner/WakaSpinner.stories.tsx +156 -0
- package/src/components/waka-stat/WakaStat.stories.tsx +334 -0
- package/src/components/waka-status-matrix/WakaStatusMatrix.stories.tsx +331 -0
- package/src/components/waka-stepper/WakaStepper.stories.tsx +468 -0
- package/src/components/waka-streak-counter/WakaStreakCounter.stories.tsx +235 -0
- package/src/components/waka-success-explosion/WakaSuccessExplosion.stories.tsx +389 -0
- package/src/components/waka-tabs-morph/WakaTabsMorph.stories.tsx +471 -0
- package/src/components/waka-terminal-output/WakaTerminalOutput.stories.tsx +351 -0
- package/src/components/waka-test-report/WakaTestReport.stories.tsx +322 -0
- package/src/components/waka-tilt-card/WakaTiltCard.stories.tsx +300 -0
- package/src/components/waka-time-picker/WakaTimePicker.stories.tsx +227 -0
- package/src/components/waka-timeline/WakaTimeline.stories.tsx +383 -0
- package/src/components/waka-tournament-bracket/WakaTournamentBracket.stories.tsx +375 -0
- package/src/components/waka-trace-viewer/WakaTraceViewer.stories.tsx +445 -0
- package/src/components/waka-tree/WakaTree.stories.tsx +359 -0
- package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +378 -0
- package/src/components/waka-typewriter/WakaTypewriter.stories.tsx +366 -0
- package/src/components/waka-versus-card/WakaVersusCard.stories.tsx +530 -0
- package/src/components/waka-video/WakaVideo.stories.tsx +203 -0
- package/src/components/waka-virtual-list/WakaVirtualList.stories.tsx +273 -0
- 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
|
+
}
|