|
| 1 | +'use client'; |
| 2 | + |
| 3 | +import { cn } from '@soybean-react-ui/variants'; |
| 4 | +import { useTheme } from 'next-themes'; |
| 5 | +import type { CSSProperties } from 'react'; |
| 6 | +import type { ToasterProps } from 'sonner'; |
| 7 | +import { Toaster as Sonner } from 'sonner'; |
| 8 | + |
| 9 | +const css = { |
| 10 | + '--border-radius': 'var(--radius - 2px)', |
| 11 | + '--error-text': 'hsl(var(--destructive))', |
| 12 | + '--info-text': 'hsl(var(--info))', |
| 13 | + '--normal-bg': 'hsl(var(--background))', |
| 14 | + '--normal-border': 'hsl(var(--border))', |
| 15 | + '--normal-text': 'hsl(var(--foreground))', |
| 16 | + '--success-text': 'hsl(var(--success))', |
| 17 | + '--warning-text': 'hsl(var(--warning))', |
| 18 | + pointerEvents: 'auto' |
| 19 | +}; |
| 20 | + |
| 21 | +const toastVariants = |
| 22 | + '!border-border !bg-card !text-card-foreground !shadow-[0_4px_6px_-1px_rgb(0_0_0_/_0.1),_0_2px_4px_-2px_rgb(0_0_0_/_0.1)] group !opacity-100'; |
| 23 | + |
| 24 | +const actionButton = |
| 25 | + '!inline-flex justify-center px-2 gap-1 leading-5 whitespace-nowrap focus-visible:shadow-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:pointer-events-none disabled:opacity-50 !bg-primary !text-primary-foreground '; |
| 26 | + |
| 27 | +const cancelButton = |
| 28 | + '!inline-flex justify-center px-2 gap-1 leading-5 whitespace-nowrap focus-visible:shadow-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:pointer-events-none disabled:opacity-50 !border !border-border !bg-background !text-foreground active:shadow-[0_4px_6px_-1px_rgb(0_0_0_/_0.1),_0_2px_4px_-2px_rgb(0_0_0_/_0.1)]'; |
| 29 | + |
| 30 | +const description = 'text-xs !text-muted-foreground'; |
| 31 | + |
| 32 | +const icon = |
| 33 | + 'group-data-[type=success]:text-success group-data-[type=info]:text-info group-data-[type=warning]:text-warning group-data-[type=error]:text-error'; |
| 34 | + |
| 35 | +const title = 'text-sm font-medium'; |
| 36 | + |
| 37 | +// eslint-disable-next-line complexity |
| 38 | +const Toaster = (props: ToasterProps) => { |
| 39 | + const { theme = 'system' } = useTheme(); |
| 40 | + |
| 41 | + const { expand = true, style = css as CSSProperties, toastOptions, ...rest } = props; |
| 42 | + |
| 43 | + return ( |
| 44 | + <Sonner |
| 45 | + expand={expand} |
| 46 | + style={style} |
| 47 | + theme={theme as ToasterProps['theme']} |
| 48 | + toastOptions={{ |
| 49 | + classNames: { |
| 50 | + actionButton: cn(actionButton, toastOptions?.classNames?.actionButton), |
| 51 | + cancelButton: cn(cancelButton, toastOptions?.classNames?.cancelButton), |
| 52 | + description: cn(description, toastOptions?.classNames?.description), |
| 53 | + icon: cn(icon, toastOptions?.classNames?.icon), |
| 54 | + title: cn(title, toastOptions?.classNames?.title), |
| 55 | + toast: cn(toastVariants, toastOptions?.classNames?.toast) |
| 56 | + } |
| 57 | + }} |
| 58 | + {...rest} |
| 59 | + /> |
| 60 | + ); |
| 61 | +}; |
| 62 | + |
| 63 | +export default Toaster; |
0 commit comments