@neynar/ui 0.1.1
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/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/components/ui/accordion.d.ts +229 -0
- package/dist/components/ui/accordion.d.ts.map +1 -0
- package/dist/components/ui/alert-dialog.d.ts +247 -0
- package/dist/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/components/ui/alert.d.ts +187 -0
- package/dist/components/ui/alert.d.ts.map +1 -0
- package/dist/components/ui/aspect-ratio.d.ts +94 -0
- package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
- package/dist/components/ui/avatar.d.ts +244 -0
- package/dist/components/ui/avatar.d.ts.map +1 -0
- package/dist/components/ui/badge.d.ts +163 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +281 -0
- package/dist/components/ui/breadcrumb.d.ts.map +1 -0
- package/dist/components/ui/button.d.ts +129 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/calendar.d.ts +169 -0
- package/dist/components/ui/calendar.d.ts.map +1 -0
- package/dist/components/ui/card.d.ts +365 -0
- package/dist/components/ui/card.d.ts.map +1 -0
- package/dist/components/ui/carousel.d.ts +369 -0
- package/dist/components/ui/carousel.d.ts.map +1 -0
- package/dist/components/ui/chart.d.ts +442 -0
- package/dist/components/ui/chart.d.ts.map +1 -0
- package/dist/components/ui/checkbox.d.ts +88 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -0
- package/dist/components/ui/collapsible.d.ts +182 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/combobox.d.ts +270 -0
- package/dist/components/ui/combobox.d.ts.map +1 -0
- package/dist/components/ui/command.d.ts +355 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/container.d.ts +102 -0
- package/dist/components/ui/container.d.ts.map +1 -0
- package/dist/components/ui/context-menu.d.ts +339 -0
- package/dist/components/ui/context-menu.d.ts.map +1 -0
- package/dist/components/ui/date-picker.d.ts +145 -0
- package/dist/components/ui/date-picker.d.ts.map +1 -0
- package/dist/components/ui/dialog.d.ts +322 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/drawer.d.ts +154 -0
- package/dist/components/ui/drawer.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +349 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/empty-state.d.ts +133 -0
- package/dist/components/ui/empty-state.d.ts.map +1 -0
- package/dist/components/ui/hover-card.d.ts +109 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -0
- package/dist/components/ui/input.d.ts +89 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/label.d.ts +93 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/menubar.d.ts +306 -0
- package/dist/components/ui/menubar.d.ts.map +1 -0
- package/dist/components/ui/navigation-menu.d.ts +318 -0
- package/dist/components/ui/navigation-menu.d.ts.map +1 -0
- package/dist/components/ui/pagination.d.ts +343 -0
- package/dist/components/ui/pagination.d.ts.map +1 -0
- package/dist/components/ui/popover.d.ts +178 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/progress.d.ts +64 -0
- package/dist/components/ui/progress.d.ts.map +1 -0
- package/dist/components/ui/radio-group.d.ts +144 -0
- package/dist/components/ui/radio-group.d.ts.map +1 -0
- package/dist/components/ui/resizable.d.ts +164 -0
- package/dist/components/ui/resizable.d.ts.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +82 -0
- package/dist/components/ui/scroll-area.d.ts.map +1 -0
- package/dist/components/ui/select.d.ts +316 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/separator.d.ts +80 -0
- package/dist/components/ui/separator.d.ts.map +1 -0
- package/dist/components/ui/sheet.d.ts +346 -0
- package/dist/components/ui/sheet.d.ts.map +1 -0
- package/dist/components/ui/sidebar.d.ts +1561 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -0
- package/dist/components/ui/skeleton.d.ts +66 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/slider.d.ts +95 -0
- package/dist/components/ui/slider.d.ts.map +1 -0
- package/dist/components/ui/sonner.d.ts +101 -0
- package/dist/components/ui/sonner.d.ts.map +1 -0
- package/dist/components/ui/stack.d.ts +192 -0
- package/dist/components/ui/stack.d.ts.map +1 -0
- package/dist/components/ui/stories/accordion.stories.d.ts +71 -0
- package/dist/components/ui/stories/accordion.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/alert-dialog.stories.d.ts +39 -0
- package/dist/components/ui/stories/alert-dialog.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/alert.stories.d.ts +48 -0
- package/dist/components/ui/stories/alert.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/aspect-ratio.stories.d.ts +53 -0
- package/dist/components/ui/stories/aspect-ratio.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/avatar.stories.d.ts +49 -0
- package/dist/components/ui/stories/avatar.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/badge.stories.d.ts +64 -0
- package/dist/components/ui/stories/badge.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/breadcrumb.stories.d.ts +27 -0
- package/dist/components/ui/stories/breadcrumb.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/button.stories.d.ts +92 -0
- package/dist/components/ui/stories/button.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/calendar.stories.d.ts +94 -0
- package/dist/components/ui/stories/calendar.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/card.stories.d.ts +29 -0
- package/dist/components/ui/stories/card.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/carousel.stories.d.ts +42 -0
- package/dist/components/ui/stories/carousel.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/chart.stories.d.ts +51 -0
- package/dist/components/ui/stories/chart.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/checkbox.stories.d.ts +72 -0
- package/dist/components/ui/stories/checkbox.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/cn.stories.d.ts +19 -0
- package/dist/components/ui/stories/cn.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/collapsible.stories.d.ts +51 -0
- package/dist/components/ui/stories/collapsible.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/colors.stories.d.ts +31 -0
- package/dist/components/ui/stories/colors.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/combobox.stories.d.ts +89 -0
- package/dist/components/ui/stories/combobox.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/command.stories.d.ts +69 -0
- package/dist/components/ui/stories/command.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/container.stories.d.ts +42 -0
- package/dist/components/ui/stories/container.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/context-menu.stories.d.ts +32 -0
- package/dist/components/ui/stories/context-menu.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/date-picker.stories.d.ts +67 -0
- package/dist/components/ui/stories/date-picker.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/dialog.stories.d.ts +48 -0
- package/dist/components/ui/stories/dialog.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/drawer.stories.d.ts +33 -0
- package/dist/components/ui/stories/drawer.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/dropdown-menu.stories.d.ts +31 -0
- package/dist/components/ui/stories/dropdown-menu.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/empty-state.stories.d.ts +74 -0
- package/dist/components/ui/stories/empty-state.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/hover-card.stories.d.ts +35 -0
- package/dist/components/ui/stories/hover-card.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/input.stories.d.ts +69 -0
- package/dist/components/ui/stories/input.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/label.stories.d.ts +47 -0
- package/dist/components/ui/stories/label.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/menubar.stories.d.ts +39 -0
- package/dist/components/ui/stories/menubar.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/navigation-menu.stories.d.ts +44 -0
- package/dist/components/ui/stories/navigation-menu.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/pagination.stories.d.ts +33 -0
- package/dist/components/ui/stories/pagination.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/popover.stories.d.ts +36 -0
- package/dist/components/ui/stories/popover.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/progress.stories.d.ts +38 -0
- package/dist/components/ui/stories/progress.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/radio-group.stories.d.ts +76 -0
- package/dist/components/ui/stories/radio-group.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/resizable.stories.d.ts +49 -0
- package/dist/components/ui/stories/resizable.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/scroll-area.stories.d.ts +35 -0
- package/dist/components/ui/stories/scroll-area.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/select.stories.d.ts +51 -0
- package/dist/components/ui/stories/select.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/separator.stories.d.ts +58 -0
- package/dist/components/ui/stories/separator.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/sheet.stories.d.ts +43 -0
- package/dist/components/ui/stories/sheet.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/sidebar.stories.d.ts +60 -0
- package/dist/components/ui/stories/sidebar.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/skeleton.stories.d.ts +42 -0
- package/dist/components/ui/stories/skeleton.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/slider.stories.d.ts +99 -0
- package/dist/components/ui/stories/slider.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/sonner.stories.d.ts +9 -0
- package/dist/components/ui/stories/sonner.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/stack.stories.d.ts +39 -0
- package/dist/components/ui/stories/stack.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/switch.stories.d.ts +71 -0
- package/dist/components/ui/stories/switch.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/table.stories.d.ts +40 -0
- package/dist/components/ui/stories/table.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/tabs.stories.d.ts +62 -0
- package/dist/components/ui/stories/tabs.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/text-field.stories.d.ts +78 -0
- package/dist/components/ui/stories/text-field.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/textarea.stories.d.ts +57 -0
- package/dist/components/ui/stories/textarea.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/theme-toggle.stories.d.ts +71 -0
- package/dist/components/ui/stories/theme-toggle.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/theme.stories.d.ts +51 -0
- package/dist/components/ui/stories/theme.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/toggle-group.stories.d.ts +71 -0
- package/dist/components/ui/stories/toggle-group.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/toggle.stories.d.ts +78 -0
- package/dist/components/ui/stories/toggle.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/tooltip.stories.d.ts +37 -0
- package/dist/components/ui/stories/tooltip.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/typography.stories.d.ts +137 -0
- package/dist/components/ui/stories/typography.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/use-mobile.stories.d.ts +20 -0
- package/dist/components/ui/stories/use-mobile.stories.d.ts.map +1 -0
- package/dist/components/ui/stories/use-theme.stories.d.ts +23 -0
- package/dist/components/ui/stories/use-theme.stories.d.ts.map +1 -0
- package/dist/components/ui/switch.d.ts +84 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/components/ui/table.d.ts +321 -0
- package/dist/components/ui/table.d.ts.map +1 -0
- package/dist/components/ui/tabs.d.ts +260 -0
- package/dist/components/ui/tabs.d.ts.map +1 -0
- package/dist/components/ui/text-field.d.ts +157 -0
- package/dist/components/ui/text-field.d.ts.map +1 -0
- package/dist/components/ui/textarea.d.ts +84 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/theme-toggle.d.ts +105 -0
- package/dist/components/ui/theme-toggle.d.ts.map +1 -0
- package/dist/components/ui/theme.d.ts +110 -0
- package/dist/components/ui/theme.d.ts.map +1 -0
- package/dist/components/ui/toggle-group.d.ts +133 -0
- package/dist/components/ui/toggle-group.d.ts.map +1 -0
- package/dist/components/ui/toggle.d.ts +84 -0
- package/dist/components/ui/toggle.d.ts.map +1 -0
- package/dist/components/ui/tooltip.d.ts +202 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/typography.d.ts +287 -0
- package/dist/components/ui/typography.d.ts.map +1 -0
- package/dist/hooks/use-mobile.d.ts +74 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -0
- package/dist/hooks/use-theme.d.ts +142 -0
- package/dist/hooks/use-theme.d.ts.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27498 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/utils.d.ts +43 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/docs/llm/colors.md +273 -0
- package/docs/llm/components/buttons.md +68 -0
- package/docs/llm/components/cards.md +53 -0
- package/docs/llm/components/display.md +134 -0
- package/docs/llm/components/feedback.md +96 -0
- package/docs/llm/components/forms.md +90 -0
- package/docs/llm/components/layout.md +59 -0
- package/docs/llm/components/menus.md +70 -0
- package/docs/llm/components/navigation.md +80 -0
- package/docs/llm/components/overlays.md +83 -0
- package/docs/llm/components/tables.md +73 -0
- package/docs/llm/components/typography.md +199 -0
- package/docs/llm/components/utilities.md +114 -0
- package/docs/llm/guide.md +165 -0
- package/llms.txt +122 -0
- package/package.json +104 -0
- package/src/components/ui/accordion.tsx +285 -0
- package/src/components/ui/alert-dialog.tsx +387 -0
- package/src/components/ui/alert.tsx +243 -0
- package/src/components/ui/aspect-ratio.tsx +99 -0
- package/src/components/ui/avatar.tsx +288 -0
- package/src/components/ui/badge.tsx +205 -0
- package/src/components/ui/breadcrumb.tsx +378 -0
- package/src/components/ui/button.tsx +195 -0
- package/src/components/ui/calendar.tsx +371 -0
- package/src/components/ui/card.tsx +447 -0
- package/src/components/ui/carousel.tsx +624 -0
- package/src/components/ui/chart.tsx +802 -0
- package/src/components/ui/checkbox.tsx +113 -0
- package/src/components/ui/collapsible.tsx +207 -0
- package/src/components/ui/combobox.tsx +373 -0
- package/src/components/ui/command.tsx +518 -0
- package/src/components/ui/container.tsx +114 -0
- package/src/components/ui/context-menu.tsx +563 -0
- package/src/components/ui/date-picker.tsx +213 -0
- package/src/components/ui/dialog.tsx +447 -0
- package/src/components/ui/drawer.tsx +273 -0
- package/src/components/ui/dropdown-menu.tsx +578 -0
- package/src/components/ui/empty-state.tsx +145 -0
- package/src/components/ui/hover-card.tsx +144 -0
- package/src/components/ui/input.tsx +106 -0
- package/src/components/ui/label.tsx +110 -0
- package/src/components/ui/menubar.tsx +553 -0
- package/src/components/ui/navigation-menu.tsx +471 -0
- package/src/components/ui/pagination.tsx +456 -0
- package/src/components/ui/popover.tsx +216 -0
- package/src/components/ui/progress.tsx +88 -0
- package/src/components/ui/radio-group.tsx +183 -0
- package/src/components/ui/resizable.tsx +209 -0
- package/src/components/ui/scroll-area.tsx +132 -0
- package/src/components/ui/select.tsx +485 -0
- package/src/components/ui/separator.tsx +101 -0
- package/src/components/ui/sheet.tsx +495 -0
- package/src/components/ui/sidebar.tsx +2211 -0
- package/src/components/ui/skeleton.tsx +76 -0
- package/src/components/ui/slider.tsx +147 -0
- package/src/components/ui/sonner.tsx +120 -0
- package/src/components/ui/stack.tsx +180 -0
- package/src/components/ui/stories/accordion.stories.tsx +429 -0
- package/src/components/ui/stories/alert-dialog.stories.tsx +519 -0
- package/src/components/ui/stories/alert.stories.tsx +228 -0
- package/src/components/ui/stories/aspect-ratio.stories.tsx +200 -0
- package/src/components/ui/stories/avatar.stories.tsx +317 -0
- package/src/components/ui/stories/badge.stories.tsx +260 -0
- package/src/components/ui/stories/breadcrumb.stories.tsx +482 -0
- package/src/components/ui/stories/button.stories.tsx +266 -0
- package/src/components/ui/stories/calendar.stories.tsx +375 -0
- package/src/components/ui/stories/card.stories.tsx +308 -0
- package/src/components/ui/stories/carousel.stories.tsx +328 -0
- package/src/components/ui/stories/chart.stories.tsx +430 -0
- package/src/components/ui/stories/checkbox.stories.tsx +297 -0
- package/src/components/ui/stories/cn.stories.tsx +433 -0
- package/src/components/ui/stories/collapsible.stories.tsx +256 -0
- package/src/components/ui/stories/colors.stories.tsx +502 -0
- package/src/components/ui/stories/combobox.stories.tsx +301 -0
- package/src/components/ui/stories/command.stories.tsx +632 -0
- package/src/components/ui/stories/container.stories.tsx +250 -0
- package/src/components/ui/stories/context-menu.stories.tsx +446 -0
- package/src/components/ui/stories/date-picker.stories.tsx +378 -0
- package/src/components/ui/stories/dialog.stories.tsx +535 -0
- package/src/components/ui/stories/drawer.stories.tsx +364 -0
- package/src/components/ui/stories/dropdown-menu.stories.tsx +374 -0
- package/src/components/ui/stories/empty-state.stories.tsx +244 -0
- package/src/components/ui/stories/hover-card.stories.tsx +355 -0
- package/src/components/ui/stories/input.stories.tsx +289 -0
- package/src/components/ui/stories/label.stories.tsx +294 -0
- package/src/components/ui/stories/menubar.stories.tsx +764 -0
- package/src/components/ui/stories/navigation-menu.stories.tsx +539 -0
- package/src/components/ui/stories/pagination.stories.tsx +604 -0
- package/src/components/ui/stories/popover.stories.tsx +392 -0
- package/src/components/ui/stories/progress.stories.tsx +218 -0
- package/src/components/ui/stories/radio-group.stories.tsx +400 -0
- package/src/components/ui/stories/resizable.stories.tsx +417 -0
- package/src/components/ui/stories/scroll-area.stories.tsx +180 -0
- package/src/components/ui/stories/select.stories.tsx +389 -0
- package/src/components/ui/stories/separator.stories.tsx +192 -0
- package/src/components/ui/stories/sheet.stories.tsx +468 -0
- package/src/components/ui/stories/sidebar.stories.tsx +731 -0
- package/src/components/ui/stories/skeleton.stories.tsx +216 -0
- package/src/components/ui/stories/slider.stories.tsx +321 -0
- package/src/components/ui/stories/sonner.stories.tsx +373 -0
- package/src/components/ui/stories/stack.stories.tsx +222 -0
- package/src/components/ui/stories/switch.stories.tsx +202 -0
- package/src/components/ui/stories/table.stories.tsx +541 -0
- package/src/components/ui/stories/tabs.stories.tsx +544 -0
- package/src/components/ui/stories/text-field.stories.tsx +280 -0
- package/src/components/ui/stories/textarea.stories.tsx +245 -0
- package/src/components/ui/stories/theme-toggle.stories.tsx +275 -0
- package/src/components/ui/stories/theme.stories.tsx +412 -0
- package/src/components/ui/stories/toggle-group.stories.tsx +337 -0
- package/src/components/ui/stories/toggle.stories.tsx +325 -0
- package/src/components/ui/stories/tooltip.stories.tsx +444 -0
- package/src/components/ui/stories/typography.stories.tsx +1586 -0
- package/src/components/ui/stories/use-mobile.stories.tsx +420 -0
- package/src/components/ui/stories/use-theme.stories.tsx +531 -0
- package/src/components/ui/switch.tsx +106 -0
- package/src/components/ui/table.tsx +424 -0
- package/src/components/ui/tabs.tsx +316 -0
- package/src/components/ui/text-field.tsx +206 -0
- package/src/components/ui/textarea.tsx +98 -0
- package/src/components/ui/theme-toggle.tsx +185 -0
- package/src/components/ui/theme.tsx +148 -0
- package/src/components/ui/toggle-group.tsx +196 -0
- package/src/components/ui/toggle.tsx +115 -0
- package/src/components/ui/tooltip.tsx +253 -0
- package/src/components/ui/typography.tsx +468 -0
- package/src/hooks/use-mobile.ts +91 -0
- package/src/hooks/use-theme.ts +319 -0
- package/src/index.ts +77 -0
- package/src/lib/utils.ts +57 -0
- package/src/styles/globals.css +160 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { format } from "date-fns";
|
|
3
|
+
import { CalendarIcon } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
import { Button } from "./button";
|
|
7
|
+
import { Calendar } from "./calendar";
|
|
8
|
+
import { Popover, PopoverContent, PopoverTrigger } from "./popover";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Properties for the DatePicker component
|
|
12
|
+
*
|
|
13
|
+
* @type DatePickerProps
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
*/
|
|
16
|
+
type DatePickerProps = {
|
|
17
|
+
/**
|
|
18
|
+
* The currently selected date value. When undefined, no date is selected.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const [selectedDate, setSelectedDate] = useState<Date>();
|
|
23
|
+
* <DatePicker date={selectedDate} onDateChange={setSelectedDate} />
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
date?: Date;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Callback function invoked when the user selects or clears a date.
|
|
30
|
+
* Receives the selected date or undefined when cleared.
|
|
31
|
+
*
|
|
32
|
+
* @param date - The newly selected date or undefined if cleared
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* <DatePicker onDateChange={(date) => console.log('Selected:', date)} />
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
onDateChange?: (date: Date | undefined) => void;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Placeholder text displayed in the trigger button when no date is selected.
|
|
43
|
+
* Provides context about what kind of date selection is expected.
|
|
44
|
+
*
|
|
45
|
+
* @default "Pick a date"
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```tsx
|
|
49
|
+
* <DatePicker placeholder="Select your birthday" />
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
placeholder?: string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* When true, disables the date picker preventing user interaction.
|
|
56
|
+
* The trigger button will appear disabled and the popover cannot be opened.
|
|
57
|
+
*
|
|
58
|
+
* @default false
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* <DatePicker disabled={true} placeholder="Date locked" />
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
disabled?: boolean;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Additional CSS classes to apply to the trigger button.
|
|
69
|
+
* Useful for customizing width, spacing, or other styling.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```tsx
|
|
73
|
+
* <DatePicker className="w-full" /> // Full width
|
|
74
|
+
* <DatePicker className="w-[300px]" /> // Fixed width
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
className?: string;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A comprehensive date selection component that combines an accessible button trigger
|
|
82
|
+
* with a full-featured calendar popover for intuitive date picking.
|
|
83
|
+
*
|
|
84
|
+
* Built on shadcn/ui design principles, this component provides a polished interface
|
|
85
|
+
* for date selection with proper accessibility, keyboard navigation, and visual feedback.
|
|
86
|
+
* The selected date is displayed using date-fns formatting for consistent presentation.
|
|
87
|
+
*
|
|
88
|
+
* @component
|
|
89
|
+
* @example
|
|
90
|
+
* ```tsx
|
|
91
|
+
* // Basic controlled date picker
|
|
92
|
+
* const [date, setDate] = useState<Date>();
|
|
93
|
+
*
|
|
94
|
+
* <DatePicker
|
|
95
|
+
* date={date}
|
|
96
|
+
* onDateChange={setDate}
|
|
97
|
+
* placeholder="Select date"
|
|
98
|
+
* />
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```tsx
|
|
103
|
+
* // Date picker for forms with validation
|
|
104
|
+
* const [birthDate, setBirthDate] = useState<Date>();
|
|
105
|
+
*
|
|
106
|
+
* <DatePicker
|
|
107
|
+
* date={birthDate}
|
|
108
|
+
* onDateChange={setBirthDate}
|
|
109
|
+
* placeholder="Select birth date"
|
|
110
|
+
* className="w-[280px]"
|
|
111
|
+
* disabled={isSubmitting}
|
|
112
|
+
* />
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```tsx
|
|
117
|
+
* // Date range start/end picker
|
|
118
|
+
* <div className="flex gap-2 items-center">
|
|
119
|
+
* <DatePicker
|
|
120
|
+
* date={startDate}
|
|
121
|
+
* onDateChange={setStartDate}
|
|
122
|
+
* placeholder="Start date"
|
|
123
|
+
* className="w-[180px]"
|
|
124
|
+
* />
|
|
125
|
+
* <span>to</span>
|
|
126
|
+
* <DatePicker
|
|
127
|
+
* date={endDate}
|
|
128
|
+
* onDateChange={setEndDate}
|
|
129
|
+
* placeholder="End date"
|
|
130
|
+
* className="w-[180px]"
|
|
131
|
+
* />
|
|
132
|
+
* </div>
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* @accessibility
|
|
136
|
+
* - **Keyboard Navigation**: Full keyboard support with Tab, Enter, Escape, and arrow keys
|
|
137
|
+
* - **Screen Reader Support**: Proper ARIA labels and live announcements for date changes
|
|
138
|
+
* - **Focus Management**: Focus returns to trigger button when popover closes
|
|
139
|
+
* - **Visual Indicators**: Clear visual states for disabled, selected, and focused elements
|
|
140
|
+
* - **Date Formatting**: Consistent date presentation using localized formatting
|
|
141
|
+
*
|
|
142
|
+
* @features
|
|
143
|
+
* - Single date selection with visual confirmation
|
|
144
|
+
* - Popover-based calendar that doesn't interfere with page layout
|
|
145
|
+
* - Automatic popover positioning and collision detection
|
|
146
|
+
* - Internal state management with optional external control
|
|
147
|
+
* - Customizable trigger button styling and width
|
|
148
|
+
* - Date formatting using date-fns for internationalization support
|
|
149
|
+
*
|
|
150
|
+
* @see {@link https://ui.shadcn.com/docs/components/date-picker} shadcn/ui Date Picker patterns
|
|
151
|
+
* @see {@link Calendar} - The underlying calendar component
|
|
152
|
+
* @see {@link Popover} - The popover container component
|
|
153
|
+
* @see {@link Button} - The trigger button component
|
|
154
|
+
*
|
|
155
|
+
* @since 1.0.0
|
|
156
|
+
*/
|
|
157
|
+
function DatePicker({
|
|
158
|
+
date,
|
|
159
|
+
onDateChange,
|
|
160
|
+
placeholder = "Pick a date",
|
|
161
|
+
disabled = false,
|
|
162
|
+
className,
|
|
163
|
+
}: DatePickerProps) {
|
|
164
|
+
// Internal state for uncontrolled usage and popover open/close
|
|
165
|
+
const [internalDate, setInternalDate] = React.useState<Date | undefined>(
|
|
166
|
+
date,
|
|
167
|
+
);
|
|
168
|
+
const [open, setOpen] = React.useState(false);
|
|
169
|
+
|
|
170
|
+
// Sync internal state when controlled date prop changes
|
|
171
|
+
React.useEffect(() => {
|
|
172
|
+
setInternalDate(date);
|
|
173
|
+
}, [date]);
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Handles date selection from the calendar.
|
|
177
|
+
* Updates internal state, calls the onChange callback, and closes the popover.
|
|
178
|
+
*/
|
|
179
|
+
const handleDateSelect = (selectedDate: Date | undefined) => {
|
|
180
|
+
setInternalDate(selectedDate);
|
|
181
|
+
onDateChange?.(selectedDate);
|
|
182
|
+
setOpen(false);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
187
|
+
<PopoverTrigger asChild>
|
|
188
|
+
<Button
|
|
189
|
+
variant="outline"
|
|
190
|
+
className={cn(
|
|
191
|
+
"w-[240px] justify-start text-left font-normal",
|
|
192
|
+
!internalDate && "text-muted-foreground",
|
|
193
|
+
className,
|
|
194
|
+
)}
|
|
195
|
+
disabled={disabled}
|
|
196
|
+
>
|
|
197
|
+
<CalendarIcon className="mr-2 h-4 w-4" />
|
|
198
|
+
{internalDate ? format(internalDate, "PPP") : placeholder}
|
|
199
|
+
</Button>
|
|
200
|
+
</PopoverTrigger>
|
|
201
|
+
<PopoverContent className="w-auto p-0" align="start">
|
|
202
|
+
<Calendar
|
|
203
|
+
mode="single"
|
|
204
|
+
selected={internalDate}
|
|
205
|
+
onSelect={handleDateSelect}
|
|
206
|
+
initialFocus
|
|
207
|
+
/>
|
|
208
|
+
</PopoverContent>
|
|
209
|
+
</Popover>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export { DatePicker };
|
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
3
|
+
import { XIcon } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Dialog - A modal dialog component for important content or actions
|
|
9
|
+
*
|
|
10
|
+
* A modal window overlay component built on Radix UI Dialog primitives that interrupts
|
|
11
|
+
* the user's workflow to capture their attention for important interactions. Dialogs render
|
|
12
|
+
* content in a layer above the main application with proper focus management and accessibility.
|
|
13
|
+
*
|
|
14
|
+
* Use dialogs for critical interactions, confirmations, forms, or detailed information that
|
|
15
|
+
* requires user focus and prevents interaction with the background content.
|
|
16
|
+
*
|
|
17
|
+
* @component
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* // Basic confirmation dialog
|
|
21
|
+
* <Dialog>
|
|
22
|
+
* <DialogTrigger asChild>
|
|
23
|
+
* <Button>Open Dialog</Button>
|
|
24
|
+
* </DialogTrigger>
|
|
25
|
+
* <DialogContent>
|
|
26
|
+
* <DialogHeader>
|
|
27
|
+
* <DialogTitle>Are you sure?</DialogTitle>
|
|
28
|
+
* <DialogDescription>
|
|
29
|
+
* This action cannot be undone.
|
|
30
|
+
* </DialogDescription>
|
|
31
|
+
* </DialogHeader>
|
|
32
|
+
* <DialogFooter>
|
|
33
|
+
* <Button variant="outline">Cancel</Button>
|
|
34
|
+
* <Button>Continue</Button>
|
|
35
|
+
* </DialogFooter>
|
|
36
|
+
* </DialogContent>
|
|
37
|
+
* </Dialog>
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```tsx
|
|
42
|
+
* // Controlled dialog with form handling
|
|
43
|
+
* const [open, setOpen] = useState(false);
|
|
44
|
+
*
|
|
45
|
+
* <Dialog open={open} onOpenChange={setOpen}>
|
|
46
|
+
* <DialogTrigger asChild>
|
|
47
|
+
* <Button>Edit Profile</Button>
|
|
48
|
+
* </DialogTrigger>
|
|
49
|
+
* <DialogContent className="sm:max-w-[425px]">
|
|
50
|
+
* <DialogHeader>
|
|
51
|
+
* <DialogTitle>Edit profile</DialogTitle>
|
|
52
|
+
* <DialogDescription>
|
|
53
|
+
* Make changes to your profile here. Click save when you're done.
|
|
54
|
+
* </DialogDescription>
|
|
55
|
+
* </DialogHeader>
|
|
56
|
+
* <form onSubmit={handleSubmit}>
|
|
57
|
+
* <div className="grid gap-4 py-4">
|
|
58
|
+
* <Input label="Name" defaultValue="John Doe" />
|
|
59
|
+
* <Input label="Username" defaultValue="@johndoe" />
|
|
60
|
+
* </div>
|
|
61
|
+
* <DialogFooter>
|
|
62
|
+
* <Button type="submit">Save changes</Button>
|
|
63
|
+
* </DialogFooter>
|
|
64
|
+
* </form>
|
|
65
|
+
* </DialogContent>
|
|
66
|
+
* </Dialog>
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```tsx
|
|
71
|
+
* // Custom close behavior
|
|
72
|
+
* <Dialog>
|
|
73
|
+
* <DialogTrigger asChild>
|
|
74
|
+
* <Button>Share Link</Button>
|
|
75
|
+
* </DialogTrigger>
|
|
76
|
+
* <DialogContent showCloseButton={false}>
|
|
77
|
+
* <DialogHeader>
|
|
78
|
+
* <DialogTitle>Share this link</DialogTitle>
|
|
79
|
+
* </DialogHeader>
|
|
80
|
+
* <div className="flex items-center space-x-2">
|
|
81
|
+
* <Input value="https://example.com" readOnly />
|
|
82
|
+
* <Button size="sm"><Copy className="h-4 w-4" /></Button>
|
|
83
|
+
* </div>
|
|
84
|
+
* <DialogFooter>
|
|
85
|
+
* <DialogClose asChild>
|
|
86
|
+
* <Button variant="secondary">Done</Button>
|
|
87
|
+
* </DialogClose>
|
|
88
|
+
* </DialogFooter>
|
|
89
|
+
* </DialogContent>
|
|
90
|
+
* </Dialog>
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @accessibility
|
|
94
|
+
* - Focus trapped within dialog when open using Radix UI focus management
|
|
95
|
+
* - Escape key closes the dialog (can be disabled with `modal={false}`)
|
|
96
|
+
* - Background scroll locked when dialog is open
|
|
97
|
+
* - Proper ARIA attributes including aria-labelledby and aria-describedby
|
|
98
|
+
* - Screen reader announcements when dialog opens/closes
|
|
99
|
+
* - Focus returns to trigger element when dialog closes
|
|
100
|
+
* - Background content becomes inert (non-interactive)
|
|
101
|
+
* - Keyboard navigation between focusable elements
|
|
102
|
+
*
|
|
103
|
+
* @param open - Controlled open state of the dialog
|
|
104
|
+
* @param onOpenChange - Callback fired when open state changes
|
|
105
|
+
* @param modal - Whether dialog is modal (default: true). Non-modal allows background interaction
|
|
106
|
+
* @param defaultOpen - Default open state for uncontrolled usage
|
|
107
|
+
*
|
|
108
|
+
* @see {@link https://ui.shadcn.com/docs/components/dialog} - shadcn/ui Dialog documentation
|
|
109
|
+
* @see {@link https://www.radix-ui.com/primitives/docs/components/dialog} - Radix UI Dialog primitives
|
|
110
|
+
* @see {@link AlertDialog} - For confirmation dialogs with specific alert semantics
|
|
111
|
+
* @see {@link Sheet} - For side panel overlays
|
|
112
|
+
* @see {@link Drawer} - For mobile-friendly bottom overlays
|
|
113
|
+
* @since 1.0.0
|
|
114
|
+
*/
|
|
115
|
+
function Dialog({
|
|
116
|
+
...props
|
|
117
|
+
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
118
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* DialogTrigger - The element that opens the dialog when clicked
|
|
123
|
+
*
|
|
124
|
+
* Typically wraps a button or other interactive element. Use asChild
|
|
125
|
+
* prop to render as the child element instead of a button.
|
|
126
|
+
*
|
|
127
|
+
* @component
|
|
128
|
+
* @example
|
|
129
|
+
* ```tsx
|
|
130
|
+
* <DialogTrigger asChild>
|
|
131
|
+
* <Button>Open Dialog</Button>
|
|
132
|
+
* </DialogTrigger>
|
|
133
|
+
* ```
|
|
134
|
+
* @since 1.0.0
|
|
135
|
+
*/
|
|
136
|
+
function DialogTrigger({
|
|
137
|
+
...props
|
|
138
|
+
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
139
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* DialogPortal - Portal container for dialog content
|
|
144
|
+
*
|
|
145
|
+
* Renders dialog content in a React portal at the end of the document body.
|
|
146
|
+
* This ensures proper stacking context and prevents z-index issues.
|
|
147
|
+
*
|
|
148
|
+
* @component
|
|
149
|
+
* @since 1.0.0
|
|
150
|
+
*/
|
|
151
|
+
function DialogPortal({
|
|
152
|
+
...props
|
|
153
|
+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
154
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* DialogClose - A close button that dismisses the dialog
|
|
159
|
+
*
|
|
160
|
+
* Can be placed anywhere within DialogContent to provide a close action.
|
|
161
|
+
* Typically used for custom close buttons in addition to the default X button.
|
|
162
|
+
*
|
|
163
|
+
* @component
|
|
164
|
+
* @example
|
|
165
|
+
* ```tsx
|
|
166
|
+
* <DialogClose asChild>
|
|
167
|
+
* <Button variant="outline">Cancel</Button>
|
|
168
|
+
* </DialogClose>
|
|
169
|
+
* ```
|
|
170
|
+
* @since 1.0.0
|
|
171
|
+
*/
|
|
172
|
+
function DialogClose({
|
|
173
|
+
...props
|
|
174
|
+
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
175
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* DialogOverlay - The backdrop overlay behind the dialog
|
|
180
|
+
*
|
|
181
|
+
* Provides a semi-transparent background that covers the main content.
|
|
182
|
+
* Clicking the overlay will close the dialog by default.
|
|
183
|
+
*
|
|
184
|
+
* @component
|
|
185
|
+
* @accessibility
|
|
186
|
+
* - Prevents interaction with background content
|
|
187
|
+
* - Can be clicked to dismiss dialog (configurable)
|
|
188
|
+
* @since 1.0.0
|
|
189
|
+
*/
|
|
190
|
+
function DialogOverlay({
|
|
191
|
+
className,
|
|
192
|
+
...props
|
|
193
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
194
|
+
return (
|
|
195
|
+
<DialogPrimitive.Overlay
|
|
196
|
+
data-slot="dialog-overlay"
|
|
197
|
+
className={cn(
|
|
198
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
|
199
|
+
className,
|
|
200
|
+
)}
|
|
201
|
+
{...props}
|
|
202
|
+
/>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* DialogContent - The main content container for the dialog
|
|
208
|
+
*
|
|
209
|
+
* The primary container for dialog content that automatically includes the overlay and portal.
|
|
210
|
+
* Provides the visual dialog box with animations, positioning, and focus management.
|
|
211
|
+
* Includes a close button (X) by default which can be hidden using the showCloseButton prop.
|
|
212
|
+
*
|
|
213
|
+
* @component
|
|
214
|
+
* @example
|
|
215
|
+
* ```tsx
|
|
216
|
+
* // Standard content with header and footer
|
|
217
|
+
* <DialogContent>
|
|
218
|
+
* <DialogHeader>
|
|
219
|
+
* <DialogTitle>Dialog Title</DialogTitle>
|
|
220
|
+
* <DialogDescription>
|
|
221
|
+
* Detailed description of the dialog's purpose
|
|
222
|
+
* </DialogDescription>
|
|
223
|
+
* </DialogHeader>
|
|
224
|
+
* <div className="py-4">
|
|
225
|
+
* Main dialog content goes here
|
|
226
|
+
* </div>
|
|
227
|
+
* <DialogFooter>
|
|
228
|
+
* <Button variant="outline">Cancel</Button>
|
|
229
|
+
* <Button>Confirm</Button>
|
|
230
|
+
* </DialogFooter>
|
|
231
|
+
* </DialogContent>
|
|
232
|
+
* ```
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```tsx
|
|
236
|
+
* // Custom sizing and scrollable content
|
|
237
|
+
* <DialogContent className="sm:max-w-[425px] max-h-[80vh] overflow-y-auto">
|
|
238
|
+
* <DialogHeader>
|
|
239
|
+
* <DialogTitle>Long Content</DialogTitle>
|
|
240
|
+
* </DialogHeader>
|
|
241
|
+
* <div className="space-y-4">
|
|
242
|
+
* // Long scrollable content
|
|
243
|
+
* </div>
|
|
244
|
+
* </DialogContent>
|
|
245
|
+
* ```
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```tsx
|
|
249
|
+
* // Without default close button
|
|
250
|
+
* <DialogContent showCloseButton={false}>
|
|
251
|
+
* <DialogHeader>
|
|
252
|
+
* <DialogTitle>Custom Close</DialogTitle>
|
|
253
|
+
* </DialogHeader>
|
|
254
|
+
* <div>Content without X button</div>
|
|
255
|
+
* <DialogFooter>
|
|
256
|
+
* <DialogClose asChild>
|
|
257
|
+
* <Button>Close</Button>
|
|
258
|
+
* </DialogClose>
|
|
259
|
+
* </DialogFooter>
|
|
260
|
+
* </DialogContent>
|
|
261
|
+
* ```
|
|
262
|
+
*
|
|
263
|
+
* @accessibility
|
|
264
|
+
* - Automatically focuses first focusable element on open
|
|
265
|
+
* - Traps focus within the dialog using Radix UI focus management
|
|
266
|
+
* - Includes accessible close button with screen reader text ("Close")
|
|
267
|
+
* - Proper ARIA labeling automatically applied via DialogTitle and DialogDescription
|
|
268
|
+
* - ESC key support for closing (when modal={true})
|
|
269
|
+
* - Click outside to close (when modal={true})
|
|
270
|
+
*
|
|
271
|
+
* @param className - Additional CSS classes to apply to the content container
|
|
272
|
+
* @param children - Dialog content including header, body, and footer elements
|
|
273
|
+
* @param showCloseButton - Whether to show the X close button in top-right corner (default: true)
|
|
274
|
+
* @param ...props - All other props from Radix UI Dialog.Content including positioning and animation props
|
|
275
|
+
*
|
|
276
|
+
* @since 1.0.0
|
|
277
|
+
*/
|
|
278
|
+
function DialogContent({
|
|
279
|
+
className,
|
|
280
|
+
children,
|
|
281
|
+
showCloseButton = true,
|
|
282
|
+
...props
|
|
283
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
284
|
+
showCloseButton?: boolean;
|
|
285
|
+
}) {
|
|
286
|
+
return (
|
|
287
|
+
<DialogPortal data-slot="dialog-portal">
|
|
288
|
+
<DialogOverlay />
|
|
289
|
+
<DialogPrimitive.Content
|
|
290
|
+
data-slot="dialog-content"
|
|
291
|
+
className={cn(
|
|
292
|
+
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
|
293
|
+
className,
|
|
294
|
+
)}
|
|
295
|
+
{...props}
|
|
296
|
+
>
|
|
297
|
+
{children}
|
|
298
|
+
{showCloseButton && (
|
|
299
|
+
<DialogPrimitive.Close
|
|
300
|
+
data-slot="dialog-close"
|
|
301
|
+
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
|
302
|
+
>
|
|
303
|
+
<XIcon />
|
|
304
|
+
<span className="sr-only">Close</span>
|
|
305
|
+
</DialogPrimitive.Close>
|
|
306
|
+
)}
|
|
307
|
+
</DialogPrimitive.Content>
|
|
308
|
+
</DialogPortal>
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* DialogHeader - Container for dialog title and description
|
|
314
|
+
*
|
|
315
|
+
* Groups the dialog's title and description at the top of the dialog content.
|
|
316
|
+
* Provides consistent spacing and alignment for header elements.
|
|
317
|
+
*
|
|
318
|
+
* @component
|
|
319
|
+
* @example
|
|
320
|
+
* ```tsx
|
|
321
|
+
* <DialogHeader>
|
|
322
|
+
* <DialogTitle>Edit profile</DialogTitle>
|
|
323
|
+
* <DialogDescription>
|
|
324
|
+
* Make changes to your profile here. Click save when you're done.
|
|
325
|
+
* </DialogDescription>
|
|
326
|
+
* </DialogHeader>
|
|
327
|
+
* ```
|
|
328
|
+
* @since 1.0.0
|
|
329
|
+
*/
|
|
330
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
331
|
+
return (
|
|
332
|
+
<div
|
|
333
|
+
data-slot="dialog-header"
|
|
334
|
+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
335
|
+
{...props}
|
|
336
|
+
/>
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* DialogFooter - Container for dialog action buttons
|
|
342
|
+
*
|
|
343
|
+
* Typically contains action buttons like Save, Cancel, or Submit.
|
|
344
|
+
* Automatically handles responsive layout with proper button alignment.
|
|
345
|
+
*
|
|
346
|
+
* @component
|
|
347
|
+
* @example
|
|
348
|
+
* ```tsx
|
|
349
|
+
* <DialogFooter>
|
|
350
|
+
* <Button variant="outline">Cancel</Button>
|
|
351
|
+
* <Button type="submit">Save changes</Button>
|
|
352
|
+
* </DialogFooter>
|
|
353
|
+
* ```
|
|
354
|
+
*
|
|
355
|
+
* @accessibility
|
|
356
|
+
* - Buttons are arranged in logical order for keyboard navigation
|
|
357
|
+
* - Mobile-responsive layout
|
|
358
|
+
* @since 1.0.0
|
|
359
|
+
*/
|
|
360
|
+
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
361
|
+
return (
|
|
362
|
+
<div
|
|
363
|
+
data-slot="dialog-footer"
|
|
364
|
+
className={cn(
|
|
365
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
366
|
+
className,
|
|
367
|
+
)}
|
|
368
|
+
{...props}
|
|
369
|
+
/>
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* DialogTitle - The main heading of the dialog
|
|
375
|
+
*
|
|
376
|
+
* Provides the accessible name for the dialog. Should clearly describe
|
|
377
|
+
* the dialog's purpose or the action being performed.
|
|
378
|
+
*
|
|
379
|
+
* @component
|
|
380
|
+
* @example
|
|
381
|
+
* ```tsx
|
|
382
|
+
* <DialogTitle>Delete Account</DialogTitle>
|
|
383
|
+
* ```
|
|
384
|
+
*
|
|
385
|
+
* @accessibility
|
|
386
|
+
* - Automatically sets aria-labelledby on the dialog
|
|
387
|
+
* - Should be descriptive and concise
|
|
388
|
+
* @since 1.0.0
|
|
389
|
+
*/
|
|
390
|
+
function DialogTitle({
|
|
391
|
+
className,
|
|
392
|
+
...props
|
|
393
|
+
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
394
|
+
return (
|
|
395
|
+
<DialogPrimitive.Title
|
|
396
|
+
data-slot="dialog-title"
|
|
397
|
+
className={cn("text-lg leading-none font-semibold", className)}
|
|
398
|
+
{...props}
|
|
399
|
+
/>
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* DialogDescription - Supplementary description for the dialog
|
|
405
|
+
*
|
|
406
|
+
* Provides additional context or instructions for the dialog content.
|
|
407
|
+
* Helps users understand what action they're about to take.
|
|
408
|
+
*
|
|
409
|
+
* @component
|
|
410
|
+
* @example
|
|
411
|
+
* ```tsx
|
|
412
|
+
* <DialogDescription>
|
|
413
|
+
* This action cannot be undone. This will permanently delete your
|
|
414
|
+
* account and remove your data from our servers.
|
|
415
|
+
* </DialogDescription>
|
|
416
|
+
* ```
|
|
417
|
+
*
|
|
418
|
+
* @accessibility
|
|
419
|
+
* - Automatically sets aria-describedby on the dialog
|
|
420
|
+
* - Important for screen reader users to understand context
|
|
421
|
+
* @since 1.0.0
|
|
422
|
+
*/
|
|
423
|
+
function DialogDescription({
|
|
424
|
+
className,
|
|
425
|
+
...props
|
|
426
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
427
|
+
return (
|
|
428
|
+
<DialogPrimitive.Description
|
|
429
|
+
data-slot="dialog-description"
|
|
430
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
431
|
+
{...props}
|
|
432
|
+
/>
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export {
|
|
437
|
+
Dialog,
|
|
438
|
+
DialogClose,
|
|
439
|
+
DialogContent,
|
|
440
|
+
DialogDescription,
|
|
441
|
+
DialogFooter,
|
|
442
|
+
DialogHeader,
|
|
443
|
+
DialogOverlay,
|
|
444
|
+
DialogPortal,
|
|
445
|
+
DialogTitle,
|
|
446
|
+
DialogTrigger,
|
|
447
|
+
};
|