@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,243 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
const alertVariants = cva(
|
|
7
|
+
"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: "bg-card text-card-foreground",
|
|
12
|
+
destructive:
|
|
13
|
+
"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: "default",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Alert - Display important messages and notifications to users
|
|
24
|
+
*
|
|
25
|
+
* A flexible alert component for displaying important messages, notifications, and status updates.
|
|
26
|
+
* Built with shadcn/ui design patterns and Tailwind CSS. Alerts are used to communicate
|
|
27
|
+
* critical information that requires user attention and potentially action.
|
|
28
|
+
*
|
|
29
|
+
* ## When to use
|
|
30
|
+
* - System-wide notifications and announcements
|
|
31
|
+
* - Form validation errors and success messages
|
|
32
|
+
* - Important warnings that need persistent visibility
|
|
33
|
+
* - Status updates that don't require immediate action
|
|
34
|
+
* - Progress indicators and completion messages
|
|
35
|
+
*
|
|
36
|
+
* ## Features
|
|
37
|
+
* - Two built-in variants: `default` and `destructive`
|
|
38
|
+
* - Automatic icon grid layout with proper spacing using CSS Grid
|
|
39
|
+
* - Semantic HTML with proper ARIA attributes (`role="alert"`)
|
|
40
|
+
* - Responsive design with consistent spacing
|
|
41
|
+
* - Dark mode support via CSS custom properties
|
|
42
|
+
* - Composition pattern with AlertTitle and AlertDescription
|
|
43
|
+
* - Support for custom styling through className prop
|
|
44
|
+
* - Icon-aware layout that adapts to presence of SVG icons
|
|
45
|
+
*
|
|
46
|
+
* ## Design Philosophy
|
|
47
|
+
* Follows the shadcn/ui principle of providing unstyled, accessible components that
|
|
48
|
+
* can be easily customized. The alert uses CSS Grid for intelligent layout that
|
|
49
|
+
* automatically adjusts based on whether an icon is present.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```tsx
|
|
53
|
+
* // Basic informational alert
|
|
54
|
+
* <Alert>
|
|
55
|
+
* <Info className="size-4" />
|
|
56
|
+
* <AlertTitle>Heads up!</AlertTitle>
|
|
57
|
+
* <AlertDescription>
|
|
58
|
+
* You can add components to your app using the cli.
|
|
59
|
+
* </AlertDescription>
|
|
60
|
+
* </Alert>
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* // Destructive error alert
|
|
66
|
+
* import { AlertCircle } from "lucide-react";
|
|
67
|
+
*
|
|
68
|
+
* <Alert variant="destructive">
|
|
69
|
+
* <AlertCircle className="size-4" />
|
|
70
|
+
* <AlertTitle>Error</AlertTitle>
|
|
71
|
+
* <AlertDescription>
|
|
72
|
+
* Your session has expired. Please log in again.
|
|
73
|
+
* </AlertDescription>
|
|
74
|
+
* </Alert>
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```tsx
|
|
79
|
+
* // Custom styled success alert
|
|
80
|
+
* <Alert className="border-green-200 bg-green-50 text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-200">
|
|
81
|
+
* <CheckCircle className="size-4" />
|
|
82
|
+
* <AlertTitle>Success</AlertTitle>
|
|
83
|
+
* <AlertDescription>
|
|
84
|
+
* Your changes have been saved successfully.
|
|
85
|
+
* </AlertDescription>
|
|
86
|
+
* </Alert>
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```tsx
|
|
91
|
+
* // Alert without icon
|
|
92
|
+
* <Alert>
|
|
93
|
+
* <AlertTitle>Simple Notice</AlertTitle>
|
|
94
|
+
* <AlertDescription>
|
|
95
|
+
* This alert doesn't use an icon.
|
|
96
|
+
* </AlertDescription>
|
|
97
|
+
* </Alert>
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```tsx
|
|
102
|
+
* // Alert with only description
|
|
103
|
+
* <Alert variant="destructive">
|
|
104
|
+
* <AlertCircle className="size-4" />
|
|
105
|
+
* <AlertDescription>
|
|
106
|
+
* Something went wrong. Please try again.
|
|
107
|
+
* </AlertDescription>
|
|
108
|
+
* </Alert>
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @param variant - Visual style variant determining colors and emphasis
|
|
112
|
+
* @param className - Additional CSS classes to merge with default styles
|
|
113
|
+
* @param children - Alert content including optional icon, title, and description
|
|
114
|
+
* @param props - Additional HTML div element props
|
|
115
|
+
*
|
|
116
|
+
* @accessibility
|
|
117
|
+
* - Uses `role="alert"` for immediate screen reader announcements
|
|
118
|
+
* - Supports keyboard navigation when containing interactive elements
|
|
119
|
+
* - WCAG AA color contrast compliance for all variants
|
|
120
|
+
* - Semantic HTML structure with proper heading hierarchy
|
|
121
|
+
* - Icon support with automatic grid layout and accessible sizing
|
|
122
|
+
* - Icons receive `text-current` color for proper contrast inheritance
|
|
123
|
+
*
|
|
124
|
+
* @see {@link AlertTitle} - Alert title component for headings
|
|
125
|
+
* @see {@link AlertDescription} - Alert description component for body text
|
|
126
|
+
* @see {@link https://ui.shadcn.com/docs/components/alert} - shadcn/ui Alert documentation
|
|
127
|
+
* @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/alert/} - ARIA alert pattern
|
|
128
|
+
* @since 1.0.0
|
|
129
|
+
*/
|
|
130
|
+
function Alert({
|
|
131
|
+
className,
|
|
132
|
+
variant,
|
|
133
|
+
...props
|
|
134
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
|
|
135
|
+
return (
|
|
136
|
+
<div
|
|
137
|
+
data-slot="alert"
|
|
138
|
+
role="alert"
|
|
139
|
+
className={cn(alertVariants({ variant }), className)}
|
|
140
|
+
{...props}
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* AlertTitle - The title/heading component for alerts
|
|
147
|
+
*
|
|
148
|
+
* Provides a prominent title or heading for the alert message. Automatically styled
|
|
149
|
+
* with medium font weight, line clamping, and proper grid positioning. Used to
|
|
150
|
+
* give context and immediate recognition of the alert's purpose.
|
|
151
|
+
*
|
|
152
|
+
* ## Features
|
|
153
|
+
* - Medium font weight for visual hierarchy
|
|
154
|
+
* - Single line with overflow handling (line-clamp-1)
|
|
155
|
+
* - Consistent minimum height for layout stability
|
|
156
|
+
* - Proper grid positioning (col-start-2) for icon layout
|
|
157
|
+
* - Tight character spacing (tracking-tight) for readability
|
|
158
|
+
*
|
|
159
|
+
* @component
|
|
160
|
+
* @example
|
|
161
|
+
* ```tsx
|
|
162
|
+
* <Alert>
|
|
163
|
+
* <Info className="size-4" />
|
|
164
|
+
* <AlertTitle>Payment Successful</AlertTitle>
|
|
165
|
+
* <AlertDescription>Your payment has been processed.</AlertDescription>
|
|
166
|
+
* </Alert>
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```tsx
|
|
171
|
+
* // Title-only alert (no description)
|
|
172
|
+
* <Alert variant="destructive">
|
|
173
|
+
* <AlertCircle className="size-4" />
|
|
174
|
+
* <AlertTitle>Connection Failed</AlertTitle>
|
|
175
|
+
* </Alert>
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* @param className - Additional CSS classes to apply
|
|
179
|
+
* @param children - Title text content
|
|
180
|
+
*
|
|
181
|
+
* @accessibility
|
|
182
|
+
* - Semantically associated with the alert container via DOM structure
|
|
183
|
+
* - Proper visual hierarchy with medium font weight
|
|
184
|
+
* - Readable character spacing and line height
|
|
185
|
+
* - Works with screen readers as part of alert announcement
|
|
186
|
+
*
|
|
187
|
+
* @see {@link Alert} - Parent alert container component
|
|
188
|
+
* @see {@link AlertDescription} - Companion description component
|
|
189
|
+
* @since 1.0.0
|
|
190
|
+
*/
|
|
191
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
192
|
+
return (
|
|
193
|
+
<div
|
|
194
|
+
data-slot="alert-title"
|
|
195
|
+
className={cn(
|
|
196
|
+
"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
|
|
197
|
+
className,
|
|
198
|
+
)}
|
|
199
|
+
{...props}
|
|
200
|
+
/>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* AlertDescription - Detailed description text for an alert
|
|
206
|
+
*
|
|
207
|
+
* Provides additional context or instructions related to the alert.
|
|
208
|
+
* Supports multiple paragraphs and rich text content.
|
|
209
|
+
*
|
|
210
|
+
* @component
|
|
211
|
+
* @example
|
|
212
|
+
* ```tsx
|
|
213
|
+
* <Alert>
|
|
214
|
+
* <AlertTitle>Note</AlertTitle>
|
|
215
|
+
* <AlertDescription>
|
|
216
|
+
* Your changes have been saved. You can continue editing or publish when ready.
|
|
217
|
+
* </AlertDescription>
|
|
218
|
+
* </Alert>
|
|
219
|
+
* ```
|
|
220
|
+
*
|
|
221
|
+
* @accessibility
|
|
222
|
+
* - Uses appropriate text color for readability
|
|
223
|
+
* - Supports paragraph spacing for long content
|
|
224
|
+
*
|
|
225
|
+
* @since 1.0.0
|
|
226
|
+
*/
|
|
227
|
+
function AlertDescription({
|
|
228
|
+
className,
|
|
229
|
+
...props
|
|
230
|
+
}: React.ComponentProps<"div">) {
|
|
231
|
+
return (
|
|
232
|
+
<div
|
|
233
|
+
data-slot="alert-description"
|
|
234
|
+
className={cn(
|
|
235
|
+
"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
|
|
236
|
+
className,
|
|
237
|
+
)}
|
|
238
|
+
{...props}
|
|
239
|
+
/>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export { Alert, AlertTitle, AlertDescription };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AspectRatio component for maintaining consistent width-to-height ratios
|
|
5
|
+
*
|
|
6
|
+
* A foundational layout component that preserves specific aspect ratios regardless
|
|
7
|
+
* of container size. Essential for responsive images, videos, and media content that
|
|
8
|
+
* needs consistent proportions across different screen sizes. Built on Radix UI
|
|
9
|
+
* primitives with zero JavaScript runtime overhead.
|
|
10
|
+
*
|
|
11
|
+
* This component creates a CSS-based aspect ratio container using the modern
|
|
12
|
+
* `aspect-ratio` property, ensuring content maintains its intended proportions
|
|
13
|
+
* without layout shifts or JavaScript calculations.
|
|
14
|
+
*
|
|
15
|
+
* @example Basic image with 16:9 aspect ratio
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <div className="w-[450px]">
|
|
18
|
+
* <AspectRatio ratio={16 / 9}>
|
|
19
|
+
* <img
|
|
20
|
+
* src="landscape.jpg"
|
|
21
|
+
* alt="Beautiful landscape"
|
|
22
|
+
* className="w-full h-full object-cover rounded-md"
|
|
23
|
+
* />
|
|
24
|
+
* </AspectRatio>
|
|
25
|
+
* </div>
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example Square avatar container (1:1 ratio)
|
|
29
|
+
* ```tsx
|
|
30
|
+
* <AspectRatio ratio={1}>
|
|
31
|
+
* <img
|
|
32
|
+
* src="avatar.jpg"
|
|
33
|
+
* alt="User profile"
|
|
34
|
+
* className="w-full h-full object-cover rounded-full"
|
|
35
|
+
* />
|
|
36
|
+
* </AspectRatio>
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @example Video player container
|
|
40
|
+
* ```tsx
|
|
41
|
+
* <div className="w-full max-w-2xl">
|
|
42
|
+
* <AspectRatio ratio={16 / 9}>
|
|
43
|
+
* <video
|
|
44
|
+
* src="video.mp4"
|
|
45
|
+
* controls
|
|
46
|
+
* className="w-full h-full object-cover rounded-lg"
|
|
47
|
+
* />
|
|
48
|
+
* </AspectRatio>
|
|
49
|
+
* </div>
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example Responsive image gallery with portrait orientation
|
|
53
|
+
* ```tsx
|
|
54
|
+
* <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
55
|
+
* {images.map((image) => (
|
|
56
|
+
* <AspectRatio key={image.id} ratio={3 / 4}>
|
|
57
|
+
* <img
|
|
58
|
+
* src={image.src}
|
|
59
|
+
* alt={image.alt}
|
|
60
|
+
* className="w-full h-full object-cover rounded-md"
|
|
61
|
+
* />
|
|
62
|
+
* </AspectRatio>
|
|
63
|
+
* ))}
|
|
64
|
+
* </div>
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @example Placeholder content for loading states
|
|
68
|
+
* ```tsx
|
|
69
|
+
* <AspectRatio ratio={16 / 9}>
|
|
70
|
+
* <div className="flex items-center justify-center bg-muted border-2 border-dashed border-muted-foreground/25 rounded-md">
|
|
71
|
+
* <div className="text-center text-muted-foreground">
|
|
72
|
+
* <ImageIcon className="h-12 w-12 mx-auto mb-2" />
|
|
73
|
+
* <p className="text-sm">Loading image...</p>
|
|
74
|
+
* </div>
|
|
75
|
+
* </div>
|
|
76
|
+
* </AspectRatio>
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @param ratio - The desired aspect ratio as width/height (e.g., 16/9, 4/3, 1)
|
|
80
|
+
* @param children - Content to be constrained within the aspect ratio
|
|
81
|
+
* @param className - Additional CSS classes for styling
|
|
82
|
+
*
|
|
83
|
+
* @accessibility
|
|
84
|
+
* - Inherits all accessibility features from Radix UI AspectRatio primitive
|
|
85
|
+
* - Preserves semantic meaning of child content
|
|
86
|
+
* - Does not interfere with screen reader navigation
|
|
87
|
+
* - Maintains keyboard navigation for interactive child elements
|
|
88
|
+
*
|
|
89
|
+
* @see {@link https://ui.shadcn.com/docs/components/aspect-ratio} shadcn/ui documentation
|
|
90
|
+
* @since 1.0.0
|
|
91
|
+
* @see {@link https://www.radix-ui.com/primitives/docs/components/aspect-ratio} Radix UI AspectRatio
|
|
92
|
+
*/
|
|
93
|
+
function AspectRatio({
|
|
94
|
+
...props
|
|
95
|
+
}: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {
|
|
96
|
+
return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { AspectRatio };
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Avatar - A flexible container for displaying user profile images with graceful fallback support
|
|
8
|
+
*
|
|
9
|
+
* The Avatar component is built on Radix UI's Avatar primitive and provides a robust solution
|
|
10
|
+
* for displaying user profile pictures throughout your application. It automatically handles
|
|
11
|
+
* image loading states and displays fallback content when images fail to load or are unavailable.
|
|
12
|
+
*
|
|
13
|
+
* This component follows the shadcn/ui design system principles and provides a consistent
|
|
14
|
+
* approach to user representation across all applications.
|
|
15
|
+
*
|
|
16
|
+
* ## Features
|
|
17
|
+
* - **Automatic loading states**: Seamlessly handles image loading and error states
|
|
18
|
+
* - **Graceful fallbacks**: Shows fallback content when images are unavailable
|
|
19
|
+
* - **Flexible sizing**: Easy customization through Tailwind CSS size utilities
|
|
20
|
+
* - **Shape variants**: Circular by default with support for rounded corners
|
|
21
|
+
* - **Accessibility first**: Built-in ARIA attributes and keyboard navigation
|
|
22
|
+
* - **Composable design**: Works with AvatarImage and AvatarFallback sub-components
|
|
23
|
+
*
|
|
24
|
+
* ## Common Use Cases
|
|
25
|
+
* - User profile displays in headers and navigation
|
|
26
|
+
* - Comment sections and author attribution
|
|
27
|
+
* - Team member listings and directories
|
|
28
|
+
* - Avatar groups with overlapping layouts
|
|
29
|
+
* - Organization logos and brand representation
|
|
30
|
+
* - Loading states and placeholder content
|
|
31
|
+
*
|
|
32
|
+
* ## Size Variants
|
|
33
|
+
* - `size-6` (24px) - Small avatars for dense layouts
|
|
34
|
+
* - `size-8` (32px) - Default size for most use cases
|
|
35
|
+
* - `size-10` (40px) - Medium avatars for lists
|
|
36
|
+
* - `size-12` (48px) - Large avatars for profiles
|
|
37
|
+
* - `size-16` (64px) - Extra large for main profile displays
|
|
38
|
+
*
|
|
39
|
+
* @example Basic avatar with image and fallback
|
|
40
|
+
* ```tsx
|
|
41
|
+
* <Avatar>
|
|
42
|
+
* <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
43
|
+
* <AvatarFallback>CN</AvatarFallback>
|
|
44
|
+
* </Avatar>
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @example Custom sizing
|
|
48
|
+
* ```tsx
|
|
49
|
+
* <Avatar className="size-12">
|
|
50
|
+
* <AvatarImage src="/profile.jpg" alt="John Doe" />
|
|
51
|
+
* <AvatarFallback>JD</AvatarFallback>
|
|
52
|
+
* </Avatar>
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example Avatar group with borders
|
|
56
|
+
* ```tsx
|
|
57
|
+
* <div className="flex -space-x-2">
|
|
58
|
+
* <Avatar className="border-2 border-background">
|
|
59
|
+
* <AvatarImage src="/user1.jpg" alt="User 1" />
|
|
60
|
+
* <AvatarFallback>U1</AvatarFallback>
|
|
61
|
+
* </Avatar>
|
|
62
|
+
* <Avatar className="border-2 border-background">
|
|
63
|
+
* <AvatarImage src="/user2.jpg" alt="User 2" />
|
|
64
|
+
* <AvatarFallback>U2</AvatarFallback>
|
|
65
|
+
* </Avatar>
|
|
66
|
+
* <Avatar className="border-2 border-background">
|
|
67
|
+
* <AvatarFallback>+3</AvatarFallback>
|
|
68
|
+
* </Avatar>
|
|
69
|
+
* </div>
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @example Square avatar for logos
|
|
73
|
+
* ```tsx
|
|
74
|
+
* <Avatar className="rounded-lg">
|
|
75
|
+
* <AvatarImage src="/company-logo.png" alt="Company" />
|
|
76
|
+
* <AvatarFallback>CO</AvatarFallback>
|
|
77
|
+
* </Avatar>
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @example With status indicator
|
|
81
|
+
* ```tsx
|
|
82
|
+
* <div className="relative">
|
|
83
|
+
* <Avatar>
|
|
84
|
+
* <AvatarImage src="/user.jpg" alt="Online user" />
|
|
85
|
+
* <AvatarFallback>OU</AvatarFallback>
|
|
86
|
+
* </Avatar>
|
|
87
|
+
* <div className="absolute bottom-0 right-0 size-3 bg-green-500 border-2 border-background rounded-full" />
|
|
88
|
+
* </div>
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @param className Additional CSS classes for styling. Common patterns include size utilities (size-6, size-8, size-10, size-12, size-16) and border radius overrides (rounded-lg, rounded-md, rounded-none)
|
|
92
|
+
* @param children Should contain AvatarImage and AvatarFallback components for proper functionality
|
|
93
|
+
*
|
|
94
|
+
* @accessibility
|
|
95
|
+
* - Automatically manages focus and ARIA attributes through Radix UI
|
|
96
|
+
* - Always provide descriptive alt text for AvatarImage components
|
|
97
|
+
* - Fallback content should be meaningful (user initials, not generic placeholders)
|
|
98
|
+
* - Ensure sufficient color contrast for fallback text (minimum 4.5:1 ratio)
|
|
99
|
+
* - Component supports keyboard navigation and screen reader announcements
|
|
100
|
+
* - Status indicators should include appropriate ARIA labels
|
|
101
|
+
*
|
|
102
|
+
* @see {@link AvatarImage} The image component for displaying avatar pictures
|
|
103
|
+
* @see {@link AvatarFallback} The fallback component for displaying initials or icons when images fail
|
|
104
|
+
* @see {@link https://ui.shadcn.com/docs/components/avatar} shadcn/ui Avatar Documentation
|
|
105
|
+
* @see {@link https://www.radix-ui.com/docs/primitives/components/avatar} Radix UI Avatar Primitive
|
|
106
|
+
* @since 1.0.0
|
|
107
|
+
*/
|
|
108
|
+
function Avatar({
|
|
109
|
+
className,
|
|
110
|
+
...props
|
|
111
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
|
|
112
|
+
return (
|
|
113
|
+
<AvatarPrimitive.Root
|
|
114
|
+
data-slot="avatar"
|
|
115
|
+
className={cn(
|
|
116
|
+
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
|
|
117
|
+
className,
|
|
118
|
+
)}
|
|
119
|
+
{...props}
|
|
120
|
+
/>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* AvatarImage - The image element component for displaying avatar pictures
|
|
126
|
+
*
|
|
127
|
+
* This component renders the actual avatar image and automatically handles loading states.
|
|
128
|
+
* It's built on Radix UI's Avatar.Image primitive which provides robust image loading
|
|
129
|
+
* behavior - when the image fails to load or is still loading, it remains hidden
|
|
130
|
+
* and the AvatarFallback will be displayed instead.
|
|
131
|
+
*
|
|
132
|
+
* ## Key Features
|
|
133
|
+
* - Automatic image loading state management
|
|
134
|
+
* - Graceful error handling for broken image URLs
|
|
135
|
+
* - Proper aspect ratio maintenance (square by default)
|
|
136
|
+
* - Inherits parent Avatar's size and border radius
|
|
137
|
+
* - Accessible image implementation
|
|
138
|
+
*
|
|
139
|
+
* @component
|
|
140
|
+
* @example
|
|
141
|
+
* ```tsx
|
|
142
|
+
* // Basic usage with remote image
|
|
143
|
+
* <Avatar>
|
|
144
|
+
* <AvatarImage
|
|
145
|
+
* src="https://github.com/username.png"
|
|
146
|
+
* alt="GitHub Profile Picture"
|
|
147
|
+
* />
|
|
148
|
+
* <AvatarFallback>GH</AvatarFallback>
|
|
149
|
+
* </Avatar>
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```tsx
|
|
154
|
+
* // Local image with descriptive alt text
|
|
155
|
+
* <Avatar>
|
|
156
|
+
* <AvatarImage
|
|
157
|
+
* src="/uploads/user-avatar.jpg"
|
|
158
|
+
* alt="John Doe's profile picture"
|
|
159
|
+
* />
|
|
160
|
+
* <AvatarFallback>JD</AvatarFallback>
|
|
161
|
+
* </Avatar>
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* @param src - The URL of the image to display. Can be relative or absolute URL
|
|
165
|
+
* @param alt - Descriptive alternative text for the image. Should describe the person or entity, not just "avatar" or "profile picture"
|
|
166
|
+
* @param className - Additional CSS classes to apply to the image element
|
|
167
|
+
* @param onLoadingStatusChange - Optional callback fired when the loading status changes
|
|
168
|
+
*
|
|
169
|
+
* @accessibility
|
|
170
|
+
* - Always provide descriptive alt text that identifies the person or entity
|
|
171
|
+
* - The image is automatically hidden from assistive technologies when loading or failed
|
|
172
|
+
* - Use meaningful descriptions like "John Doe's profile picture" rather than generic terms
|
|
173
|
+
* - The component handles ARIA attributes automatically via Radix UI
|
|
174
|
+
*
|
|
175
|
+
* @see {@link Avatar} - The parent container component
|
|
176
|
+
* @see {@link AvatarFallback} - The fallback component shown when image is unavailable
|
|
177
|
+
* @since 1.0.0
|
|
178
|
+
*/
|
|
179
|
+
function AvatarImage({
|
|
180
|
+
className,
|
|
181
|
+
...props
|
|
182
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
|
|
183
|
+
return (
|
|
184
|
+
<AvatarPrimitive.Image
|
|
185
|
+
data-slot="avatar-image"
|
|
186
|
+
className={cn("aspect-square size-full", className)}
|
|
187
|
+
{...props}
|
|
188
|
+
/>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* AvatarFallback - Fallback content displayed when the avatar image is unavailable
|
|
194
|
+
*
|
|
195
|
+
* This component renders alternative content when the AvatarImage is loading, fails to load,
|
|
196
|
+
* or is not provided. It's built on Radix UI's Avatar.Fallback primitive and provides a
|
|
197
|
+
* visually appealing placeholder that maintains the avatar's design consistency.
|
|
198
|
+
*
|
|
199
|
+
* ## Common Use Cases
|
|
200
|
+
* - User initials (most common pattern)
|
|
201
|
+
* - Generic user icons
|
|
202
|
+
* - Company/brand initials for organization avatars
|
|
203
|
+
* - Loading states with animations
|
|
204
|
+
* - Placeholder content for new users
|
|
205
|
+
*
|
|
206
|
+
* ## Design Considerations
|
|
207
|
+
* - Uses muted background color for subtle appearance
|
|
208
|
+
* - Automatically centers content both horizontally and vertically
|
|
209
|
+
* - Inherits size and border radius from parent Avatar
|
|
210
|
+
* - Should complement the overall design system
|
|
211
|
+
*
|
|
212
|
+
* @component
|
|
213
|
+
* @example
|
|
214
|
+
* ```tsx
|
|
215
|
+
* // User initials (recommended pattern)
|
|
216
|
+
* <Avatar>
|
|
217
|
+
* <AvatarImage src="/avatar.jpg" alt="John Doe" />
|
|
218
|
+
* <AvatarFallback>JD</AvatarFallback>
|
|
219
|
+
* </Avatar>
|
|
220
|
+
* ```
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```tsx
|
|
224
|
+
* // Icon fallback for unknown users
|
|
225
|
+
* import { User } from "lucide-react";
|
|
226
|
+
*
|
|
227
|
+
* <Avatar>
|
|
228
|
+
* <AvatarImage src="/unknown-user.jpg" alt="Anonymous User" />
|
|
229
|
+
* <AvatarFallback>
|
|
230
|
+
* <User className="size-4 text-muted-foreground" />
|
|
231
|
+
* </AvatarFallback>
|
|
232
|
+
* </Avatar>
|
|
233
|
+
* ```
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```tsx
|
|
237
|
+
* // Custom colored fallback
|
|
238
|
+
* <Avatar>
|
|
239
|
+
* <AvatarImage src="/user.jpg" alt="Jane Smith" />
|
|
240
|
+
* <AvatarFallback className="bg-blue-500 text-white">
|
|
241
|
+
* JS
|
|
242
|
+
* </AvatarFallback>
|
|
243
|
+
* </Avatar>
|
|
244
|
+
* ```
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```tsx
|
|
248
|
+
* // Loading state with animation
|
|
249
|
+
* <Avatar>
|
|
250
|
+
* <AvatarImage src="/loading-image.jpg" alt="Loading" />
|
|
251
|
+
* <AvatarFallback className="animate-pulse">
|
|
252
|
+
* <User className="size-4 text-muted-foreground" />
|
|
253
|
+
* </AvatarFallback>
|
|
254
|
+
* </Avatar>
|
|
255
|
+
* ```
|
|
256
|
+
*
|
|
257
|
+
* @param children - The fallback content to display. Common patterns include user initials (2-3 characters), icons, or loading indicators
|
|
258
|
+
* @param className - Additional CSS classes. Use for custom background colors, text styling, or animations
|
|
259
|
+
* @param delayMs - Optional delay in milliseconds before showing the fallback (Radix UI feature)
|
|
260
|
+
*
|
|
261
|
+
* @accessibility
|
|
262
|
+
* - Content should be meaningful and descriptive
|
|
263
|
+
* - Ensure sufficient color contrast between text and background (minimum 4.5:1 ratio)
|
|
264
|
+
* - Keep text concise - typically 1-3 characters for initials
|
|
265
|
+
* - Icons should have appropriate sizing relative to the avatar
|
|
266
|
+
* - The component is automatically accessible via Radix UI implementation
|
|
267
|
+
*
|
|
268
|
+
* @see {@link Avatar} - The parent container component
|
|
269
|
+
* @see {@link AvatarImage} - The image component that this component provides fallback for
|
|
270
|
+
* @since 1.0.0
|
|
271
|
+
*/
|
|
272
|
+
function AvatarFallback({
|
|
273
|
+
className,
|
|
274
|
+
...props
|
|
275
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
|
|
276
|
+
return (
|
|
277
|
+
<AvatarPrimitive.Fallback
|
|
278
|
+
data-slot="avatar-fallback"
|
|
279
|
+
className={cn(
|
|
280
|
+
"bg-muted flex size-full items-center justify-center rounded-full",
|
|
281
|
+
className,
|
|
282
|
+
)}
|
|
283
|
+
{...props}
|
|
284
|
+
/>
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export { Avatar, AvatarImage, AvatarFallback };
|