@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,224 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaAutocomplete, type AutocompleteOption } from './index'
3
+ import * as React from 'react'
4
+
5
+ const meta: Meta<typeof WakaAutocomplete> = {
6
+ title: 'Components/Forms/WakaAutocomplete',
7
+ component: WakaAutocomplete,
8
+ parameters: {
9
+ layout: 'centered',
10
+ docs: {
11
+ description: {
12
+ component: 'An autocomplete component with async search, multi-select, and creatable options.',
13
+ },
14
+ },
15
+ },
16
+ tags: ['autodocs'],
17
+ argTypes: {
18
+ multiple: {
19
+ control: 'boolean',
20
+ description: 'Enable multi-select mode',
21
+ },
22
+ creatable: {
23
+ control: 'boolean',
24
+ description: 'Allow creating new options',
25
+ },
26
+ disabled: {
27
+ control: 'boolean',
28
+ description: 'Disable the component',
29
+ },
30
+ },
31
+ }
32
+
33
+ export default meta
34
+ type Story = StoryObj<typeof WakaAutocomplete>
35
+
36
+ const fruits: AutocompleteOption[] = [
37
+ { value: 'apple', label: 'Apple' },
38
+ { value: 'banana', label: 'Banana' },
39
+ { value: 'cherry', label: 'Cherry' },
40
+ { value: 'date', label: 'Date' },
41
+ { value: 'elderberry', label: 'Elderberry' },
42
+ { value: 'fig', label: 'Fig' },
43
+ { value: 'grape', label: 'Grape' },
44
+ { value: 'honeydew', label: 'Honeydew' },
45
+ ]
46
+
47
+ const groupedOptions: AutocompleteOption[] = [
48
+ { value: 'apple', label: 'Apple', group: 'Fruits' },
49
+ { value: 'banana', label: 'Banana', group: 'Fruits' },
50
+ { value: 'cherry', label: 'Cherry', group: 'Fruits' },
51
+ { value: 'carrot', label: 'Carrot', group: 'Vegetables' },
52
+ { value: 'broccoli', label: 'Broccoli', group: 'Vegetables' },
53
+ { value: 'spinach', label: 'Spinach', group: 'Vegetables' },
54
+ ]
55
+
56
+ export const Default: Story = {
57
+ render: function AutocompleteDemo() {
58
+ const [value, setValue] = React.useState<string | string[] | null>(null)
59
+
60
+ return (
61
+ <div className="w-[300px]">
62
+ <WakaAutocomplete
63
+ options={fruits}
64
+ value={value as string | undefined}
65
+ onChange={setValue}
66
+ placeholder="Select a fruit..."
67
+ label="Favorite Fruit"
68
+ />
69
+ </div>
70
+ )
71
+ },
72
+ }
73
+
74
+ export const Multiple: Story = {
75
+ render: function MultipleDemo() {
76
+ const [value, setValue] = React.useState<string | string[] | null>([])
77
+
78
+ return (
79
+ <div className="w-[300px]">
80
+ <WakaAutocomplete
81
+ options={fruits}
82
+ value={value as string[]}
83
+ onChange={setValue}
84
+ multiple
85
+ placeholder="Select fruits..."
86
+ label="Favorite Fruits"
87
+ description="You can select multiple options"
88
+ />
89
+ </div>
90
+ )
91
+ },
92
+ }
93
+
94
+ export const Creatable: Story = {
95
+ render: function CreatableDemo() {
96
+ const [value, setValue] = React.useState<string | string[] | null>(null)
97
+
98
+ return (
99
+ <div className="w-[300px]">
100
+ <WakaAutocomplete
101
+ options={fruits}
102
+ value={value as string | undefined}
103
+ onChange={setValue}
104
+ creatable
105
+ placeholder="Select or create..."
106
+ label="Fruit"
107
+ description="Type to create a new option"
108
+ />
109
+ </div>
110
+ )
111
+ },
112
+ }
113
+
114
+ export const WithGroups: Story = {
115
+ render: function GroupedDemo() {
116
+ const [value, setValue] = React.useState<string | string[] | null>(null)
117
+
118
+ return (
119
+ <div className="w-[300px]">
120
+ <WakaAutocomplete
121
+ options={groupedOptions}
122
+ value={value as string | undefined}
123
+ onChange={setValue}
124
+ placeholder="Select an item..."
125
+ label="Food"
126
+ />
127
+ </div>
128
+ )
129
+ },
130
+ }
131
+
132
+ export const AsyncSearch: Story = {
133
+ render: function AsyncDemo() {
134
+ const [value, setValue] = React.useState<string | string[] | null>(null)
135
+
136
+ const searchFn = async (query: string): Promise<AutocompleteOption[]> => {
137
+ await new Promise((resolve) => setTimeout(resolve, 500))
138
+ return fruits.filter((f) =>
139
+ f.label.toLowerCase().includes(query.toLowerCase())
140
+ )
141
+ }
142
+
143
+ return (
144
+ <div className="w-[300px]">
145
+ <WakaAutocomplete
146
+ options={[]}
147
+ value={value as string | undefined}
148
+ onChange={setValue}
149
+ onSearch={searchFn}
150
+ placeholder="Search fruits..."
151
+ label="Async Search"
152
+ description="Type to search"
153
+ />
154
+ </div>
155
+ )
156
+ },
157
+ }
158
+
159
+ export const WithMaxSelections: Story = {
160
+ render: function MaxSelectionsDemo() {
161
+ const [value, setValue] = React.useState<string | string[] | null>([])
162
+
163
+ return (
164
+ <div className="w-[300px]">
165
+ <WakaAutocomplete
166
+ options={fruits}
167
+ value={value as string[]}
168
+ onChange={setValue}
169
+ multiple
170
+ maxSelections={3}
171
+ placeholder="Select up to 3 fruits..."
172
+ label="Limited Selection"
173
+ description="Maximum 3 selections allowed"
174
+ />
175
+ </div>
176
+ )
177
+ },
178
+ }
179
+
180
+ export const WithError: Story = {
181
+ render: function ErrorDemo() {
182
+ const [value, setValue] = React.useState<string | string[] | null>(null)
183
+
184
+ return (
185
+ <div className="w-[300px]">
186
+ <WakaAutocomplete
187
+ options={fruits}
188
+ value={value as string | undefined}
189
+ onChange={setValue}
190
+ placeholder="Select a fruit..."
191
+ label="Required Field"
192
+ error="This field is required"
193
+ />
194
+ </div>
195
+ )
196
+ },
197
+ }
198
+
199
+ export const Disabled: Story = {
200
+ render: () => (
201
+ <div className="w-[300px]">
202
+ <WakaAutocomplete
203
+ options={fruits}
204
+ value="apple"
205
+ disabled
206
+ placeholder="Select a fruit..."
207
+ label="Disabled"
208
+ />
209
+ </div>
210
+ ),
211
+ }
212
+
213
+ export const Loading: Story = {
214
+ render: () => (
215
+ <div className="w-[300px]">
216
+ <WakaAutocomplete
217
+ options={fruits}
218
+ loading
219
+ placeholder="Loading..."
220
+ label="Loading State"
221
+ />
222
+ </div>
223
+ ),
224
+ }
@@ -0,0 +1,269 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaBadgeShowcase } from './index'
3
+ import type { Badge } from './index'
4
+ import * as React from 'react'
5
+ import { Trophy, Star, Flame, Crown, Gem, Shield, Zap, Target, Heart, Award } from 'lucide-react'
6
+
7
+ const sampleBadges: Badge[] = [
8
+ { id: '1', name: 'First Steps', description: 'Complete the tutorial', icon: <Star className="h-6 w-6" />, rarity: 'common', unlockedAt: new Date() },
9
+ { id: '2', name: 'Champion', description: 'Win 10 games', icon: <Trophy className="h-6 w-6" />, rarity: 'rare', unlockedAt: new Date() },
10
+ { id: '3', name: 'Fire Starter', description: 'Get a 7-day streak', icon: <Flame className="h-6 w-6" />, rarity: 'rare', unlockedAt: new Date() },
11
+ { id: '4', name: 'Gem Collector', description: 'Collect 100 gems', icon: <Gem className="h-6 w-6" />, rarity: 'epic', unlockedAt: new Date() },
12
+ { id: '5', name: 'Guardian', description: 'Help 50 players', icon: <Shield className="h-6 w-6" />, rarity: 'epic', unlockedAt: new Date() },
13
+ { id: '6', name: 'Legend', description: 'Reach max level', icon: <Crown className="h-6 w-6" />, rarity: 'legendary', unlockedAt: new Date() },
14
+ { id: '7', name: 'Speed Demon', description: 'Complete speedrun', icon: <Zap className="h-6 w-6" />, rarity: 'legendary' },
15
+ { id: '8', name: 'Sharpshooter', description: '100% accuracy', icon: <Target className="h-6 w-6" />, rarity: 'epic' },
16
+ { id: '9', name: 'Beloved', description: 'Get 1000 likes', icon: <Heart className="h-6 w-6" />, rarity: 'rare' },
17
+ { id: '10', name: 'Elite', description: 'Top 1% player', icon: <Award className="h-6 w-6" />, rarity: 'legendary' },
18
+ ]
19
+
20
+ const meta: Meta<typeof WakaBadgeShowcase> = {
21
+ title: 'Components/Gamification/WakaBadgeShowcase',
22
+ component: WakaBadgeShowcase,
23
+ parameters: {
24
+ layout: 'centered',
25
+ docs: {
26
+ description: {
27
+ component: 'A badge showcase with grid/list/showcase modes, rarity tiers, and hover effects.',
28
+ },
29
+ },
30
+ },
31
+ tags: ['autodocs'],
32
+ argTypes: {
33
+ variant: {
34
+ control: 'select',
35
+ options: ['grid', 'list', 'showcase'],
36
+ description: 'Display variant',
37
+ },
38
+ size: {
39
+ control: 'select',
40
+ options: ['sm', 'md', 'lg'],
41
+ description: 'Size variant',
42
+ },
43
+ columns: {
44
+ control: { type: 'number', min: 2, max: 6 },
45
+ description: 'Number of columns (grid mode)',
46
+ },
47
+ showLocked: {
48
+ control: 'boolean',
49
+ description: 'Show locked badges',
50
+ },
51
+ animated: {
52
+ control: 'boolean',
53
+ description: 'Enable animations',
54
+ },
55
+ },
56
+ }
57
+
58
+ export default meta
59
+ type Story = StoryObj<typeof WakaBadgeShowcase>
60
+
61
+ export const Default: Story = {
62
+ args: {
63
+ badges: sampleBadges.slice(0, 6),
64
+ variant: 'grid',
65
+ size: 'md',
66
+ columns: 3,
67
+ showLocked: false,
68
+ animated: true,
69
+ },
70
+ render: (args) => (
71
+ <div className="w-[500px]">
72
+ <WakaBadgeShowcase {...args} />
73
+ </div>
74
+ ),
75
+ }
76
+
77
+ export const Variants: Story = {
78
+ render: () => (
79
+ <div className="space-y-8">
80
+ <div>
81
+ <p className="text-sm text-muted-foreground mb-2">Grid</p>
82
+ <div className="w-[400px]">
83
+ <WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} variant="grid" />
84
+ </div>
85
+ </div>
86
+ <div>
87
+ <p className="text-sm text-muted-foreground mb-2">List</p>
88
+ <div className="w-[350px]">
89
+ <WakaBadgeShowcase badges={sampleBadges.slice(0, 4)} variant="list" />
90
+ </div>
91
+ </div>
92
+ <div>
93
+ <p className="text-sm text-muted-foreground mb-2">Showcase</p>
94
+ <div className="w-[500px]">
95
+ <WakaBadgeShowcase badges={sampleBadges.slice(0, 5)} variant="showcase" />
96
+ </div>
97
+ </div>
98
+ </div>
99
+ ),
100
+ }
101
+
102
+ export const Sizes: Story = {
103
+ render: () => (
104
+ <div className="space-y-8">
105
+ <div>
106
+ <p className="text-sm text-muted-foreground mb-2">Small</p>
107
+ <div className="w-[300px]">
108
+ <WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} size="sm" columns={3} />
109
+ </div>
110
+ </div>
111
+ <div>
112
+ <p className="text-sm text-muted-foreground mb-2">Medium (Default)</p>
113
+ <div className="w-[400px]">
114
+ <WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} size="md" columns={3} />
115
+ </div>
116
+ </div>
117
+ <div>
118
+ <p className="text-sm text-muted-foreground mb-2">Large</p>
119
+ <div className="w-[500px]">
120
+ <WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} size="lg" columns={3} />
121
+ </div>
122
+ </div>
123
+ </div>
124
+ ),
125
+ }
126
+
127
+ export const RarityTiers: Story = {
128
+ render: () => {
129
+ const badgesByRarity = {
130
+ common: sampleBadges.filter((b) => b.rarity === 'common'),
131
+ rare: sampleBadges.filter((b) => b.rarity === 'rare'),
132
+ epic: sampleBadges.filter((b) => b.rarity === 'epic'),
133
+ legendary: sampleBadges.filter((b) => b.rarity === 'legendary'),
134
+ }
135
+
136
+ return (
137
+ <div className="w-[500px] space-y-6">
138
+ <div>
139
+ <div className="flex items-center gap-2 mb-2">
140
+ <div className="h-2 w-2 rounded-full bg-slate-400" />
141
+ <span className="text-sm font-medium text-slate-500">Common</span>
142
+ </div>
143
+ <WakaBadgeShowcase badges={badgesByRarity.common} columns={4} size="sm" />
144
+ </div>
145
+ <div>
146
+ <div className="flex items-center gap-2 mb-2">
147
+ <div className="h-2 w-2 rounded-full bg-blue-400" />
148
+ <span className="text-sm font-medium text-blue-500">Rare</span>
149
+ </div>
150
+ <WakaBadgeShowcase badges={badgesByRarity.rare} columns={4} size="sm" />
151
+ </div>
152
+ <div>
153
+ <div className="flex items-center gap-2 mb-2">
154
+ <div className="h-2 w-2 rounded-full bg-purple-400" />
155
+ <span className="text-sm font-medium text-purple-500">Epic</span>
156
+ </div>
157
+ <WakaBadgeShowcase badges={badgesByRarity.epic} columns={4} size="sm" />
158
+ </div>
159
+ <div>
160
+ <div className="flex items-center gap-2 mb-2">
161
+ <div className="h-2 w-2 rounded-full bg-amber-400" />
162
+ <span className="text-sm font-medium text-amber-500">Legendary</span>
163
+ </div>
164
+ <WakaBadgeShowcase badges={badgesByRarity.legendary} columns={4} size="sm" />
165
+ </div>
166
+ </div>
167
+ )
168
+ },
169
+ }
170
+
171
+ export const WithLockedBadges: Story = {
172
+ render: () => (
173
+ <div className="w-[500px]">
174
+ <WakaBadgeShowcase badges={sampleBadges} showLocked />
175
+ </div>
176
+ ),
177
+ }
178
+
179
+ export const Interactive: Story = {
180
+ render: () => {
181
+ const [selectedBadge, setSelectedBadge] = React.useState<Badge | null>(null)
182
+
183
+ return (
184
+ <div className="w-[500px] space-y-4">
185
+ <WakaBadgeShowcase
186
+ badges={sampleBadges.slice(0, 6)}
187
+ onBadgeClick={setSelectedBadge}
188
+ />
189
+
190
+ {selectedBadge && (
191
+ <div className="p-4 rounded-lg border bg-muted/30">
192
+ <div className="flex items-center gap-3">
193
+ <div className={`p-2 rounded-lg ${
194
+ selectedBadge.rarity === 'legendary' ? 'bg-amber-500/20 text-amber-500' :
195
+ selectedBadge.rarity === 'epic' ? 'bg-purple-500/20 text-purple-500' :
196
+ selectedBadge.rarity === 'rare' ? 'bg-blue-500/20 text-blue-500' :
197
+ 'bg-slate-500/20 text-slate-500'
198
+ }`}>
199
+ {selectedBadge.icon}
200
+ </div>
201
+ <div>
202
+ <h4 className="font-semibold">{selectedBadge.name}</h4>
203
+ <p className="text-sm text-muted-foreground">{selectedBadge.description}</p>
204
+ <p className="text-xs text-muted-foreground mt-1">
205
+ {selectedBadge.unlockedAt ? `Unlocked ${selectedBadge.unlockedAt.toLocaleDateString()}` : 'Not unlocked'}
206
+ </p>
207
+ </div>
208
+ </div>
209
+ </div>
210
+ )}
211
+ </div>
212
+ )
213
+ },
214
+ }
215
+
216
+ export const ProfileShowcase: Story = {
217
+ render: () => (
218
+ <div className="w-[450px] p-6 rounded-xl border bg-card">
219
+ <div className="flex items-center gap-4 mb-6">
220
+ <div className="w-16 h-16 rounded-full bg-gradient-to-br from-violet-500 to-purple-600" />
221
+ <div>
222
+ <h3 className="text-xl font-bold">ProGamer_42</h3>
223
+ <p className="text-sm text-muted-foreground">Level 42 • 1,847 XP</p>
224
+ </div>
225
+ </div>
226
+
227
+ <div className="mb-4">
228
+ <h4 className="text-sm font-medium text-muted-foreground mb-2">Featured Badges</h4>
229
+ <WakaBadgeShowcase
230
+ badges={sampleBadges.filter(b => b.unlockedAt).slice(0, 3)}
231
+ variant="showcase"
232
+ />
233
+ </div>
234
+
235
+ <div>
236
+ <div className="flex justify-between items-center mb-2">
237
+ <h4 className="text-sm font-medium text-muted-foreground">All Badges</h4>
238
+ <span className="text-xs text-muted-foreground">6/10</span>
239
+ </div>
240
+ <WakaBadgeShowcase badges={sampleBadges} showLocked columns={5} size="sm" />
241
+ </div>
242
+ </div>
243
+ ),
244
+ }
245
+
246
+ export const CompactWidget: Story = {
247
+ render: () => (
248
+ <div className="w-[280px] p-4 rounded-lg border">
249
+ <div className="flex justify-between items-center mb-3">
250
+ <h4 className="text-sm font-semibold">Recent Badges</h4>
251
+ <a href="#" className="text-xs text-primary hover:underline">View All</a>
252
+ </div>
253
+ <WakaBadgeShowcase
254
+ badges={sampleBadges.filter(b => b.unlockedAt).slice(0, 4)}
255
+ variant="grid"
256
+ columns={4}
257
+ size="sm"
258
+ />
259
+ </div>
260
+ ),
261
+ }
262
+
263
+ export const NoAnimation: Story = {
264
+ render: () => (
265
+ <div className="w-[500px]">
266
+ <WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} animated={false} />
267
+ </div>
268
+ ),
269
+ }