@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,93 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from './index'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Accordion> = {
|
|
5
|
+
title: 'Components/Accordion',
|
|
6
|
+
component: Accordion,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component: 'A vertically stacked set of interactive headings that reveal or hide associated content.',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
tags: ['autodocs'],
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default meta
|
|
19
|
+
type Story = StoryObj<typeof Accordion>
|
|
20
|
+
|
|
21
|
+
export const Default: Story = {
|
|
22
|
+
args: {
|
|
23
|
+
type: 'single',
|
|
24
|
+
collapsible: true,
|
|
25
|
+
className: 'w-[400px]',
|
|
26
|
+
},
|
|
27
|
+
render: (args) => (
|
|
28
|
+
<Accordion {...args}>
|
|
29
|
+
<AccordionItem value="item-1">
|
|
30
|
+
<AccordionTrigger>Is it accessible?</AccordionTrigger>
|
|
31
|
+
<AccordionContent>
|
|
32
|
+
Yes. It adheres to the WAI-ARIA design pattern.
|
|
33
|
+
</AccordionContent>
|
|
34
|
+
</AccordionItem>
|
|
35
|
+
<AccordionItem value="item-2">
|
|
36
|
+
<AccordionTrigger>Is it styled?</AccordionTrigger>
|
|
37
|
+
<AccordionContent>
|
|
38
|
+
Yes. It comes with default styles that match the other components.
|
|
39
|
+
</AccordionContent>
|
|
40
|
+
</AccordionItem>
|
|
41
|
+
<AccordionItem value="item-3">
|
|
42
|
+
<AccordionTrigger>Is it animated?</AccordionTrigger>
|
|
43
|
+
<AccordionContent>
|
|
44
|
+
Yes. It's animated by default, but you can disable it if you prefer.
|
|
45
|
+
</AccordionContent>
|
|
46
|
+
</AccordionItem>
|
|
47
|
+
</Accordion>
|
|
48
|
+
),
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const Multiple: Story = {
|
|
52
|
+
render: () => (
|
|
53
|
+
<Accordion type="multiple" className="w-[400px]">
|
|
54
|
+
<AccordionItem value="item-1">
|
|
55
|
+
<AccordionTrigger>Can I open multiple items?</AccordionTrigger>
|
|
56
|
+
<AccordionContent>
|
|
57
|
+
Yes. Set type="multiple" to allow multiple items to be open at once.
|
|
58
|
+
</AccordionContent>
|
|
59
|
+
</AccordionItem>
|
|
60
|
+
<AccordionItem value="item-2">
|
|
61
|
+
<AccordionTrigger>How does it work?</AccordionTrigger>
|
|
62
|
+
<AccordionContent>
|
|
63
|
+
Each item can be toggled independently when using the multiple type.
|
|
64
|
+
</AccordionContent>
|
|
65
|
+
</AccordionItem>
|
|
66
|
+
<AccordionItem value="item-3">
|
|
67
|
+
<AccordionTrigger>What about accessibility?</AccordionTrigger>
|
|
68
|
+
<AccordionContent>
|
|
69
|
+
Full keyboard navigation and screen reader support is included.
|
|
70
|
+
</AccordionContent>
|
|
71
|
+
</AccordionItem>
|
|
72
|
+
</Accordion>
|
|
73
|
+
),
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const DefaultOpen: Story = {
|
|
77
|
+
render: () => (
|
|
78
|
+
<Accordion type="single" defaultValue="item-1" className="w-[400px]">
|
|
79
|
+
<AccordionItem value="item-1">
|
|
80
|
+
<AccordionTrigger>This item is open by default</AccordionTrigger>
|
|
81
|
+
<AccordionContent>
|
|
82
|
+
Use the defaultValue prop to set which item should be open initially.
|
|
83
|
+
</AccordionContent>
|
|
84
|
+
</AccordionItem>
|
|
85
|
+
<AccordionItem value="item-2">
|
|
86
|
+
<AccordionTrigger>This item is closed</AccordionTrigger>
|
|
87
|
+
<AccordionContent>
|
|
88
|
+
Click to expand this content.
|
|
89
|
+
</AccordionContent>
|
|
90
|
+
</AccordionItem>
|
|
91
|
+
</Accordion>
|
|
92
|
+
),
|
|
93
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { Alert, AlertTitle, AlertDescription } from './index'
|
|
3
|
+
import { AlertCircle, Terminal, Info, CheckCircle2 } from 'lucide-react'
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Alert> = {
|
|
6
|
+
title: 'Components/Alert',
|
|
7
|
+
component: Alert,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'centered',
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component: 'Displays a callout for user attention with optional title, description, and icon.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
tags: ['autodocs'],
|
|
17
|
+
argTypes: {
|
|
18
|
+
variant: {
|
|
19
|
+
control: 'select',
|
|
20
|
+
options: ['default', 'destructive'],
|
|
21
|
+
description: 'The visual style of the alert',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default meta
|
|
27
|
+
type Story = StoryObj<typeof Alert>
|
|
28
|
+
|
|
29
|
+
export const Default: Story = {
|
|
30
|
+
args: {
|
|
31
|
+
variant: 'default',
|
|
32
|
+
},
|
|
33
|
+
render: (args) => (
|
|
34
|
+
<Alert {...args} className="w-[400px]">
|
|
35
|
+
<Terminal className="h-4 w-4" />
|
|
36
|
+
<AlertTitle>Heads up!</AlertTitle>
|
|
37
|
+
<AlertDescription>
|
|
38
|
+
You can add components to your app using the cli.
|
|
39
|
+
</AlertDescription>
|
|
40
|
+
</Alert>
|
|
41
|
+
),
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const Destructive: Story = {
|
|
45
|
+
render: () => (
|
|
46
|
+
<Alert variant="destructive" className="w-[400px]">
|
|
47
|
+
<AlertCircle className="h-4 w-4" />
|
|
48
|
+
<AlertTitle>Error</AlertTitle>
|
|
49
|
+
<AlertDescription>
|
|
50
|
+
Your session has expired. Please log in again.
|
|
51
|
+
</AlertDescription>
|
|
52
|
+
</Alert>
|
|
53
|
+
),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const Variants: Story = {
|
|
57
|
+
render: () => (
|
|
58
|
+
<div className="flex flex-col gap-4 w-[400px]">
|
|
59
|
+
<Alert>
|
|
60
|
+
<Info className="h-4 w-4" />
|
|
61
|
+
<AlertTitle>Information</AlertTitle>
|
|
62
|
+
<AlertDescription>
|
|
63
|
+
This is a default alert with some useful information.
|
|
64
|
+
</AlertDescription>
|
|
65
|
+
</Alert>
|
|
66
|
+
<Alert variant="destructive">
|
|
67
|
+
<AlertCircle className="h-4 w-4" />
|
|
68
|
+
<AlertTitle>Error</AlertTitle>
|
|
69
|
+
<AlertDescription>
|
|
70
|
+
Something went wrong. Please try again later.
|
|
71
|
+
</AlertDescription>
|
|
72
|
+
</Alert>
|
|
73
|
+
</div>
|
|
74
|
+
),
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const WithoutIcon: Story = {
|
|
78
|
+
render: () => (
|
|
79
|
+
<Alert className="w-[400px]">
|
|
80
|
+
<AlertTitle>Note</AlertTitle>
|
|
81
|
+
<AlertDescription>
|
|
82
|
+
Alerts can be displayed without an icon if needed.
|
|
83
|
+
</AlertDescription>
|
|
84
|
+
</Alert>
|
|
85
|
+
),
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export const TitleOnly: Story = {
|
|
89
|
+
render: () => (
|
|
90
|
+
<Alert className="w-[400px]">
|
|
91
|
+
<CheckCircle2 className="h-4 w-4" />
|
|
92
|
+
<AlertTitle>Successfully saved!</AlertTitle>
|
|
93
|
+
</Alert>
|
|
94
|
+
),
|
|
95
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import {
|
|
3
|
+
AlertDialog,
|
|
4
|
+
AlertDialogAction,
|
|
5
|
+
AlertDialogCancel,
|
|
6
|
+
AlertDialogContent,
|
|
7
|
+
AlertDialogDescription,
|
|
8
|
+
AlertDialogFooter,
|
|
9
|
+
AlertDialogHeader,
|
|
10
|
+
AlertDialogTitle,
|
|
11
|
+
AlertDialogTrigger,
|
|
12
|
+
} from './index'
|
|
13
|
+
import { Button } from '../button'
|
|
14
|
+
|
|
15
|
+
const meta: Meta<typeof AlertDialog> = {
|
|
16
|
+
title: 'Components/AlertDialog',
|
|
17
|
+
component: AlertDialog,
|
|
18
|
+
parameters: {
|
|
19
|
+
layout: 'centered',
|
|
20
|
+
docs: {
|
|
21
|
+
description: {
|
|
22
|
+
component: 'A modal dialog that interrupts the user with important content and expects a response.',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
tags: ['autodocs'],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default meta
|
|
30
|
+
type Story = StoryObj<typeof AlertDialog>
|
|
31
|
+
|
|
32
|
+
export const Default: Story = {
|
|
33
|
+
args: {},
|
|
34
|
+
render: (args) => (
|
|
35
|
+
<AlertDialog {...args}>
|
|
36
|
+
<AlertDialogTrigger asChild>
|
|
37
|
+
<Button variant="outline">Delete Account</Button>
|
|
38
|
+
</AlertDialogTrigger>
|
|
39
|
+
<AlertDialogContent>
|
|
40
|
+
<AlertDialogHeader>
|
|
41
|
+
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
|
42
|
+
<AlertDialogDescription>
|
|
43
|
+
This action cannot be undone. This will permanently delete your
|
|
44
|
+
account and remove your data from our servers.
|
|
45
|
+
</AlertDialogDescription>
|
|
46
|
+
</AlertDialogHeader>
|
|
47
|
+
<AlertDialogFooter>
|
|
48
|
+
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
49
|
+
<AlertDialogAction>Continue</AlertDialogAction>
|
|
50
|
+
</AlertDialogFooter>
|
|
51
|
+
</AlertDialogContent>
|
|
52
|
+
</AlertDialog>
|
|
53
|
+
),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const Destructive: Story = {
|
|
57
|
+
render: () => (
|
|
58
|
+
<AlertDialog>
|
|
59
|
+
<AlertDialogTrigger asChild>
|
|
60
|
+
<Button variant="destructive">Delete</Button>
|
|
61
|
+
</AlertDialogTrigger>
|
|
62
|
+
<AlertDialogContent>
|
|
63
|
+
<AlertDialogHeader>
|
|
64
|
+
<AlertDialogTitle>Delete this item?</AlertDialogTitle>
|
|
65
|
+
<AlertDialogDescription>
|
|
66
|
+
This will permanently delete this item. This action cannot be undone.
|
|
67
|
+
</AlertDialogDescription>
|
|
68
|
+
</AlertDialogHeader>
|
|
69
|
+
<AlertDialogFooter>
|
|
70
|
+
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
71
|
+
<AlertDialogAction className="bg-destructive text-destructive-foreground hover:bg-destructive/90">
|
|
72
|
+
Delete
|
|
73
|
+
</AlertDialogAction>
|
|
74
|
+
</AlertDialogFooter>
|
|
75
|
+
</AlertDialogContent>
|
|
76
|
+
</AlertDialog>
|
|
77
|
+
),
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const LogoutConfirmation: Story = {
|
|
81
|
+
render: () => (
|
|
82
|
+
<AlertDialog>
|
|
83
|
+
<AlertDialogTrigger asChild>
|
|
84
|
+
<Button variant="ghost">Log out</Button>
|
|
85
|
+
</AlertDialogTrigger>
|
|
86
|
+
<AlertDialogContent>
|
|
87
|
+
<AlertDialogHeader>
|
|
88
|
+
<AlertDialogTitle>Log out of your account?</AlertDialogTitle>
|
|
89
|
+
<AlertDialogDescription>
|
|
90
|
+
You will be logged out of your account on this device. You can log
|
|
91
|
+
back in at any time.
|
|
92
|
+
</AlertDialogDescription>
|
|
93
|
+
</AlertDialogHeader>
|
|
94
|
+
<AlertDialogFooter>
|
|
95
|
+
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
96
|
+
<AlertDialogAction>Log out</AlertDialogAction>
|
|
97
|
+
</AlertDialogFooter>
|
|
98
|
+
</AlertDialogContent>
|
|
99
|
+
</AlertDialog>
|
|
100
|
+
),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const SaveChanges: Story = {
|
|
104
|
+
render: () => (
|
|
105
|
+
<AlertDialog>
|
|
106
|
+
<AlertDialogTrigger asChild>
|
|
107
|
+
<Button variant="outline">Discard Changes</Button>
|
|
108
|
+
</AlertDialogTrigger>
|
|
109
|
+
<AlertDialogContent>
|
|
110
|
+
<AlertDialogHeader>
|
|
111
|
+
<AlertDialogTitle>Unsaved changes</AlertDialogTitle>
|
|
112
|
+
<AlertDialogDescription>
|
|
113
|
+
You have unsaved changes. Are you sure you want to leave? Your
|
|
114
|
+
changes will be lost.
|
|
115
|
+
</AlertDialogDescription>
|
|
116
|
+
</AlertDialogHeader>
|
|
117
|
+
<AlertDialogFooter>
|
|
118
|
+
<AlertDialogCancel>Keep editing</AlertDialogCancel>
|
|
119
|
+
<AlertDialogAction className="bg-destructive text-destructive-foreground hover:bg-destructive/90">
|
|
120
|
+
Discard
|
|
121
|
+
</AlertDialogAction>
|
|
122
|
+
</AlertDialogFooter>
|
|
123
|
+
</AlertDialogContent>
|
|
124
|
+
</AlertDialog>
|
|
125
|
+
),
|
|
126
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { AspectRatio } from './index'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof AspectRatio> = {
|
|
5
|
+
title: 'Components/AspectRatio',
|
|
6
|
+
component: AspectRatio,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component: 'Displays content within a desired ratio.',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
tags: ['autodocs'],
|
|
16
|
+
argTypes: {
|
|
17
|
+
ratio: {
|
|
18
|
+
control: 'number',
|
|
19
|
+
description: 'The desired aspect ratio',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default meta
|
|
25
|
+
type Story = StoryObj<typeof AspectRatio>
|
|
26
|
+
|
|
27
|
+
export const Default: Story = {
|
|
28
|
+
args: {
|
|
29
|
+
ratio: 16 / 9,
|
|
30
|
+
className: 'bg-muted rounded-md overflow-hidden',
|
|
31
|
+
},
|
|
32
|
+
render: (args) => (
|
|
33
|
+
<div className="w-[450px]">
|
|
34
|
+
<AspectRatio {...args}>
|
|
35
|
+
<img
|
|
36
|
+
src="https://images.unsplash.com/photo-1588345921523-c2dcdb7f1dcd?w=800&dpr=2&q=80"
|
|
37
|
+
alt="Photo by Drew Beamer"
|
|
38
|
+
className="h-full w-full object-cover"
|
|
39
|
+
/>
|
|
40
|
+
</AspectRatio>
|
|
41
|
+
</div>
|
|
42
|
+
),
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const Square: Story = {
|
|
46
|
+
render: () => (
|
|
47
|
+
<div className="w-[300px]">
|
|
48
|
+
<AspectRatio ratio={1} className="bg-muted rounded-md overflow-hidden">
|
|
49
|
+
<img
|
|
50
|
+
src="https://images.unsplash.com/photo-1588345921523-c2dcdb7f1dcd?w=800&dpr=2&q=80"
|
|
51
|
+
alt="Photo by Drew Beamer"
|
|
52
|
+
className="h-full w-full object-cover"
|
|
53
|
+
/>
|
|
54
|
+
</AspectRatio>
|
|
55
|
+
</div>
|
|
56
|
+
),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const Portrait: Story = {
|
|
60
|
+
render: () => (
|
|
61
|
+
<div className="w-[250px]">
|
|
62
|
+
<AspectRatio ratio={3 / 4} className="bg-muted rounded-md overflow-hidden">
|
|
63
|
+
<img
|
|
64
|
+
src="https://images.unsplash.com/photo-1588345921523-c2dcdb7f1dcd?w=800&dpr=2&q=80"
|
|
65
|
+
alt="Photo by Drew Beamer"
|
|
66
|
+
className="h-full w-full object-cover"
|
|
67
|
+
/>
|
|
68
|
+
</AspectRatio>
|
|
69
|
+
</div>
|
|
70
|
+
),
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const Ratios: Story = {
|
|
74
|
+
render: () => (
|
|
75
|
+
<div className="flex gap-4 flex-wrap">
|
|
76
|
+
<div className="w-[200px]">
|
|
77
|
+
<p className="text-sm text-muted-foreground mb-2">16:9</p>
|
|
78
|
+
<AspectRatio ratio={16 / 9} className="bg-muted rounded-md flex items-center justify-center">
|
|
79
|
+
<span className="text-muted-foreground text-sm">16:9</span>
|
|
80
|
+
</AspectRatio>
|
|
81
|
+
</div>
|
|
82
|
+
<div className="w-[200px]">
|
|
83
|
+
<p className="text-sm text-muted-foreground mb-2">4:3</p>
|
|
84
|
+
<AspectRatio ratio={4 / 3} className="bg-muted rounded-md flex items-center justify-center">
|
|
85
|
+
<span className="text-muted-foreground text-sm">4:3</span>
|
|
86
|
+
</AspectRatio>
|
|
87
|
+
</div>
|
|
88
|
+
<div className="w-[200px]">
|
|
89
|
+
<p className="text-sm text-muted-foreground mb-2">1:1</p>
|
|
90
|
+
<AspectRatio ratio={1} className="bg-muted rounded-md flex items-center justify-center">
|
|
91
|
+
<span className="text-muted-foreground text-sm">1:1</span>
|
|
92
|
+
</AspectRatio>
|
|
93
|
+
</div>
|
|
94
|
+
<div className="w-[200px]">
|
|
95
|
+
<p className="text-sm text-muted-foreground mb-2">21:9</p>
|
|
96
|
+
<AspectRatio ratio={21 / 9} className="bg-muted rounded-md flex items-center justify-center">
|
|
97
|
+
<span className="text-muted-foreground text-sm">21:9</span>
|
|
98
|
+
</AspectRatio>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
),
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const WithVideo: Story = {
|
|
105
|
+
render: () => (
|
|
106
|
+
<div className="w-[500px]">
|
|
107
|
+
<AspectRatio ratio={16 / 9} className="bg-black rounded-md overflow-hidden">
|
|
108
|
+
<iframe
|
|
109
|
+
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
|
|
110
|
+
title="Video"
|
|
111
|
+
className="h-full w-full"
|
|
112
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
113
|
+
allowFullScreen
|
|
114
|
+
/>
|
|
115
|
+
</AspectRatio>
|
|
116
|
+
</div>
|
|
117
|
+
),
|
|
118
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { Avatar, AvatarImage, AvatarFallback } from './index'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Avatar> = {
|
|
5
|
+
title: 'Components/Avatar',
|
|
6
|
+
component: Avatar,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component: 'An image element with a fallback for representing the user.',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
tags: ['autodocs'],
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default meta
|
|
19
|
+
type Story = StoryObj<typeof Avatar>
|
|
20
|
+
|
|
21
|
+
export const Default: Story = {
|
|
22
|
+
args: {},
|
|
23
|
+
render: (args) => (
|
|
24
|
+
<Avatar {...args}>
|
|
25
|
+
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
26
|
+
<AvatarFallback>CN</AvatarFallback>
|
|
27
|
+
</Avatar>
|
|
28
|
+
),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const WithFallback: Story = {
|
|
32
|
+
render: () => (
|
|
33
|
+
<Avatar>
|
|
34
|
+
<AvatarImage src="/broken-image.jpg" alt="@user" />
|
|
35
|
+
<AvatarFallback>JD</AvatarFallback>
|
|
36
|
+
</Avatar>
|
|
37
|
+
),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const Sizes: Story = {
|
|
41
|
+
render: () => (
|
|
42
|
+
<div className="flex items-center gap-4">
|
|
43
|
+
<Avatar className="h-6 w-6">
|
|
44
|
+
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
45
|
+
<AvatarFallback className="text-xs">CN</AvatarFallback>
|
|
46
|
+
</Avatar>
|
|
47
|
+
<Avatar className="h-8 w-8">
|
|
48
|
+
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
49
|
+
<AvatarFallback className="text-xs">CN</AvatarFallback>
|
|
50
|
+
</Avatar>
|
|
51
|
+
<Avatar>
|
|
52
|
+
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
53
|
+
<AvatarFallback>CN</AvatarFallback>
|
|
54
|
+
</Avatar>
|
|
55
|
+
<Avatar className="h-14 w-14">
|
|
56
|
+
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
57
|
+
<AvatarFallback>CN</AvatarFallback>
|
|
58
|
+
</Avatar>
|
|
59
|
+
<Avatar className="h-20 w-20">
|
|
60
|
+
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
61
|
+
<AvatarFallback className="text-xl">CN</AvatarFallback>
|
|
62
|
+
</Avatar>
|
|
63
|
+
</div>
|
|
64
|
+
),
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const Group: Story = {
|
|
68
|
+
render: () => (
|
|
69
|
+
<div className="flex -space-x-4">
|
|
70
|
+
<Avatar className="border-2 border-background">
|
|
71
|
+
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
72
|
+
<AvatarFallback>CN</AvatarFallback>
|
|
73
|
+
</Avatar>
|
|
74
|
+
<Avatar className="border-2 border-background">
|
|
75
|
+
<AvatarFallback>AB</AvatarFallback>
|
|
76
|
+
</Avatar>
|
|
77
|
+
<Avatar className="border-2 border-background">
|
|
78
|
+
<AvatarFallback>CD</AvatarFallback>
|
|
79
|
+
</Avatar>
|
|
80
|
+
<Avatar className="border-2 border-background">
|
|
81
|
+
<AvatarFallback>+3</AvatarFallback>
|
|
82
|
+
</Avatar>
|
|
83
|
+
</div>
|
|
84
|
+
),
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const FallbackColors: Story = {
|
|
88
|
+
render: () => (
|
|
89
|
+
<div className="flex items-center gap-4">
|
|
90
|
+
<Avatar>
|
|
91
|
+
<AvatarFallback className="bg-primary text-primary-foreground">AB</AvatarFallback>
|
|
92
|
+
</Avatar>
|
|
93
|
+
<Avatar>
|
|
94
|
+
<AvatarFallback className="bg-destructive text-destructive-foreground">CD</AvatarFallback>
|
|
95
|
+
</Avatar>
|
|
96
|
+
<Avatar>
|
|
97
|
+
<AvatarFallback className="bg-secondary text-secondary-foreground">EF</AvatarFallback>
|
|
98
|
+
</Avatar>
|
|
99
|
+
<Avatar>
|
|
100
|
+
<AvatarFallback className="bg-accent text-accent-foreground">GH</AvatarFallback>
|
|
101
|
+
</Avatar>
|
|
102
|
+
</div>
|
|
103
|
+
),
|
|
104
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { fn } from 'storybook/test'
|
|
2
3
|
import { Button } from './index'
|
|
3
4
|
import { Mail, Loader2, ChevronRight } from 'lucide-react'
|
|
4
5
|
|
|
@@ -14,6 +15,9 @@ const meta: Meta<typeof Button> = {
|
|
|
14
15
|
},
|
|
15
16
|
},
|
|
16
17
|
tags: ['autodocs'],
|
|
18
|
+
args: {
|
|
19
|
+
onClick: fn(),
|
|
20
|
+
},
|
|
17
21
|
argTypes: {
|
|
18
22
|
variant: {
|
|
19
23
|
control: 'select',
|
|
@@ -33,19 +37,25 @@ const meta: Meta<typeof Button> = {
|
|
|
33
37
|
control: 'boolean',
|
|
34
38
|
description: 'Whether to render as a child component (for composition)',
|
|
35
39
|
},
|
|
40
|
+
children: {
|
|
41
|
+
control: 'text',
|
|
42
|
+
description: 'Button content',
|
|
43
|
+
},
|
|
36
44
|
},
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
export default meta
|
|
40
48
|
type Story = StoryObj<typeof Button>
|
|
41
49
|
|
|
42
|
-
// Default button
|
|
50
|
+
// Default button with working controls
|
|
43
51
|
export const Default: Story = {
|
|
44
52
|
args: {
|
|
45
53
|
children: 'Button',
|
|
46
54
|
variant: 'default',
|
|
47
55
|
size: 'default',
|
|
56
|
+
disabled: false,
|
|
48
57
|
},
|
|
58
|
+
render: (args) => <Button {...args} />,
|
|
49
59
|
}
|
|
50
60
|
|
|
51
61
|
// All variants
|
|
@@ -108,6 +118,7 @@ export const Disabled: Story = {
|
|
|
108
118
|
children: 'Disabled',
|
|
109
119
|
disabled: true,
|
|
110
120
|
},
|
|
121
|
+
render: (args) => <Button {...args} />,
|
|
111
122
|
}
|
|
112
123
|
|
|
113
124
|
// As link
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { Calendar } from './index'
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { DateRange } from 'react-day-picker'
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Calendar> = {
|
|
7
|
+
title: 'Components/Calendar',
|
|
8
|
+
component: Calendar,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
docs: {
|
|
12
|
+
description: {
|
|
13
|
+
component: 'A date picker component with single and range selection support.',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
tags: ['autodocs'],
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default meta
|
|
21
|
+
type Story = StoryObj<typeof Calendar>
|
|
22
|
+
|
|
23
|
+
export const Default: Story = {
|
|
24
|
+
render: function CalendarDemo() {
|
|
25
|
+
const [date, setDate] = React.useState<Date | undefined>(new Date())
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Calendar
|
|
29
|
+
mode="single"
|
|
30
|
+
selected={date}
|
|
31
|
+
onSelect={setDate}
|
|
32
|
+
/>
|
|
33
|
+
)
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const WithRange: Story = {
|
|
38
|
+
render: function CalendarRangeDemo() {
|
|
39
|
+
const [range, setRange] = React.useState<DateRange | undefined>({
|
|
40
|
+
from: new Date(),
|
|
41
|
+
to: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Calendar
|
|
46
|
+
mode="range"
|
|
47
|
+
selected={range}
|
|
48
|
+
onSelect={setRange}
|
|
49
|
+
numberOfMonths={2}
|
|
50
|
+
/>
|
|
51
|
+
)
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const MultipleMonths: Story = {
|
|
56
|
+
render: function CalendarMultipleDemo() {
|
|
57
|
+
const [date, setDate] = React.useState<Date | undefined>(new Date())
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<Calendar
|
|
61
|
+
mode="single"
|
|
62
|
+
selected={date}
|
|
63
|
+
onSelect={setDate}
|
|
64
|
+
numberOfMonths={2}
|
|
65
|
+
/>
|
|
66
|
+
)
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const DisabledDates: Story = {
|
|
71
|
+
render: function CalendarDisabledDemo() {
|
|
72
|
+
const [date, setDate] = React.useState<Date | undefined>(new Date())
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<Calendar
|
|
76
|
+
mode="single"
|
|
77
|
+
selected={date}
|
|
78
|
+
onSelect={setDate}
|
|
79
|
+
disabled={(date) => date < new Date() || date.getDay() === 0 || date.getDay() === 6}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const WithFooter: Story = {
|
|
86
|
+
render: function CalendarFooterDemo() {
|
|
87
|
+
const [date, setDate] = React.useState<Date | undefined>()
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div className="space-y-4">
|
|
91
|
+
<Calendar
|
|
92
|
+
mode="single"
|
|
93
|
+
selected={date}
|
|
94
|
+
onSelect={setDate}
|
|
95
|
+
/>
|
|
96
|
+
<p className="text-sm text-muted-foreground text-center">
|
|
97
|
+
{date ? `Selected: ${date.toLocaleDateString()}` : 'Pick a date'}
|
|
98
|
+
</p>
|
|
99
|
+
</div>
|
|
100
|
+
)
|
|
101
|
+
},
|
|
102
|
+
}
|