| ... | @@ -11,9 +11,15 @@ import { | ... | @@ -11,9 +11,15 @@ import { |
| 11 | | 11 | |
| 12 | import { cn } from "~/lib/utils"; | 12 | import { cn } from "~/lib/utils"; |
| 13 | import { buttonVariants } from "~/components/ui/button"; | 13 | import { buttonVariants } from "~/components/ui/button"; |
| | 14 | import { useStore } from "~/store"; |
| 14 | | 15 | |
| 15 | const toastManager = Toast.createToastManager(); | 16 | type ThreadToastData = { |
| 16 | const anchoredToastManager = Toast.createToastManager(); | 17 | threadId?: string | null; |
| | 18 | tooltipStyle?: boolean; |
| | 19 | }; |
| | 20 | |
| | 21 | const toastManager = Toast.createToastManager<ThreadToastData>(); |
| | 22 | const anchoredToastManager = Toast.createToastManager<ThreadToastData>(); |
| 17 | | 23 | |
| 18 | const TOAST_ICONS = { | 24 | const TOAST_ICONS = { |
| 19 | error: CircleAlertIcon, | 25 | error: CircleAlertIcon, |
| ... | @@ -35,6 +41,15 @@ interface ToastProviderProps extends Toast.Provider.Props { | ... | @@ -35,6 +41,15 @@ interface ToastProviderProps extends Toast.Provider.Props { |
| 35 | position?: ToastPosition; | 41 | position?: ToastPosition; |
| 36 | } | 42 | } |
| 37 | | 43 | |
| | 44 | function shouldRenderForActiveThread( |
| | 45 | data: ThreadToastData | undefined, |
| | 46 | activeThreadId: string | null, |
| | 47 | ): boolean { |
| | 48 | const toastThreadId = data?.threadId; |
| | 49 | if (!toastThreadId) return true; |
| | 50 | return toastThreadId === activeThreadId; |
| | 51 | } |
| | 52 | |
| 38 | function ToastProvider({ children, position = "top-right", ...props }: ToastProviderProps) { | 53 | function ToastProvider({ children, position = "top-right", ...props }: ToastProviderProps) { |
| 39 | return ( | 54 | return ( |
| 40 | <Toast.Provider toastManager={toastManager} {...props}> | 55 | <Toast.Provider toastManager={toastManager} {...props}> |
| ... | @@ -45,7 +60,9 @@ function ToastProvider({ children, position = "top-right", ...props }: ToastProv | ... | @@ -45,7 +60,9 @@ function ToastProvider({ children, position = "top-right", ...props }: ToastProv |
| 45 | } | 60 | } |
| 46 | | 61 | |
| 47 | function Toasts({ position = "top-right" }: { position: ToastPosition }) { | 62 | function Toasts({ position = "top-right" }: { position: ToastPosition }) { |
| 48 | const { toasts } = Toast.useToastManager(); | 63 | const { state } = useStore(); |
| | 64 | const { toasts } = Toast.useToastManager<ThreadToastData>(); |
| | 65 | const activeThreadId = state.activeThreadId; |
| 49 | const isTop = position.startsWith("top"); | 66 | const isTop = position.startsWith("top"); |
| 50 | | 67 | |
| 51 | return ( | 68 | return ( |
| ... | @@ -64,91 +81,96 @@ function Toasts({ position = "top-right" }: { position: ToastPosition }) { | ... | @@ -64,91 +81,96 @@ function Toasts({ position = "top-right" }: { position: ToastPosition }) { |
| 64 | data-position={position} | 81 | data-position={position} |
| 65 | data-slot="toast-viewport" | 82 | data-slot="toast-viewport" |
| 66 | > | 83 | > |
| 67 | {toasts.map((toast) => { | 84 | {toasts |
| 68 | const Icon = toast.type ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS] : null; | 85 | .filter((toast) => shouldRenderForActiveThread(toast.data, activeThreadId)) |
| 69 | | 86 | .map((toast) => { |
| 70 | return ( | 87 | const Icon = toast.type ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS] : null; |
| 71 | <Toast.Root | | |
| 72 | className={cn( | | |
| 73 | "absolute z-[calc(9999-var(--toast-index))] h-(--toast-calc-height) w-full select-none rounded-lg border bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 [transition:transform_.5s_cubic-bezier(.22,1,.36,1),opacity_.5s,height_.15s] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", | | |
| 74 | // Base positioning using data-position | | |
| 75 | "data-[position*=right]:right-0 data-[position*=right]:left-auto", | | |
| 76 | "data-[position*=left]:right-auto data-[position*=left]:left-0", | | |
| 77 | "data-[position*=center]:right-0 data-[position*=center]:left-0", | | |
| 78 | "data-[position*=top]:top-0 data-[position*=top]:bottom-auto data-[position*=top]:origin-top", | | |
| 79 | "data-[position*=bottom]:top-auto data-[position*=bottom]:bottom-0 data-[position*=bottom]:origin-bottom", | | |
| 80 | // Gap fill for hover | | |
| 81 | "after:absolute after:left-0 after:h-[calc(var(--toast-gap)+1px)] after:w-full", | | |
| 82 | "data-[position*=top]:after:top-full", | | |
| 83 | "data-[position*=bottom]:after:bottom-full", | | |
| 84 | // Define some variables | | |
| 85 | "[--toast-calc-height:var(--toast-frontmost-height,var(--toast-height))] [--toast-gap:--spacing(3)] [--toast-peek:--spacing(3)] [--toast-scale:calc(max(0,1-(var(--toast-index)*.1)))] [--toast-shrink:calc(1-var(--toast-scale))]", | | |
| 86 | // Define offset-y variable | | |
| 87 | "data-[position*=top]:[--toast-calc-offset-y:calc(var(--toast-offset-y)+var(--toast-index)*var(--toast-gap)+var(--toast-swipe-movement-y))]", | | |
| 88 | "data-[position*=bottom]:[--toast-calc-offset-y:calc(var(--toast-offset-y)*-1+var(--toast-index)*var(--toast-gap)*-1+var(--toast-swipe-movement-y))]", | | |
| 89 | // Default state transform | | |
| 90 | "data-[position*=top]:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--toast-peek))+(var(--toast-shrink)*var(--toast-calc-height))))_scale(var(--toast-scale))]", | | |
| 91 | "data-[position*=bottom]:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--toast-peek))-(var(--toast-shrink)*var(--toast-calc-height))))_scale(var(--toast-scale))]", | | |
| 92 | // Limited state | | |
| 93 | "data-limited:opacity-0", | | |
| 94 | // Expanded state | | |
| 95 | "data-expanded:h-(--toast-height)", | | |
| 96 | "data-position:data-expanded:transform-[translateX(var(--toast-swipe-movement-x))_translateY(var(--toast-calc-offset-y))]", | | |
| 97 | // Starting and ending animations | | |
| 98 | "data-[position*=top]:data-starting-style:transform-[translateY(calc(-100%-var(--toast-inset)))]", | | |
| 99 | "data-[position*=bottom]:data-starting-style:transform-[translateY(calc(100%+var(--toast-inset)))]", | | |
| 100 | "data-ending-style:opacity-0", | | |
| 101 | // Ending animations (direction-aware) | | |
| 102 | "data-ending-style:not-data-limited:not-data-swipe-direction:transform-[translateY(calc(100%+var(--toast-inset)))]", | | |
| 103 | "data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-100%-var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]", | | |
| 104 | "data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+100%+var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]", | | |
| 105 | "data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-100%-var(--toast-inset)))]", | | |
| 106 | "data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+100%+var(--toast-inset)))]", | | |
| 107 | // Ending animations (expanded) | | |
| 108 | "data-expanded:data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-100%-var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]", | | |
| 109 | "data-expanded:data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+100%+var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]", | | |
| 110 | "data-expanded:data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-100%-var(--toast-inset)))]", | | |
| 111 | "data-expanded:data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+100%+var(--toast-inset)))]", | | |
| 112 | )} | | |
| 113 | data-position={position} | | |
| 114 | key={toast.id} | | |
| 115 | swipeDirection={ | | |
| 116 | position.includes("center") | | |
| 117 | ? [isTop ? "up" : "down"] | | |
| 118 | : position.includes("left") | | |
| 119 | ? ["left", isTop ? "up" : "down"] | | |
| 120 | : ["right", isTop ? "up" : "down"] | | |
| 121 | } | | |
| 122 | toast={toast} | | |
| 123 | > | | |
| 124 | <Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm transition-opacity duration-250 data-behind:not-data-expanded:pointer-events-none data-behind:opacity-0 data-expanded:opacity-100"> | | |
| 125 | <div className="flex gap-2"> | | |
| 126 | {Icon && ( | | |
| 127 | <div | | |
| 128 | className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0" | | |
| 129 | data-slot="toast-icon" | | |
| 130 | > | | |
| 131 | <Icon className="in-data-[type=loading]:animate-spin in-data-[type=error]:text-destructive in-data-[type=info]:text-info in-data-[type=success]:text-success in-data-[type=warning]:text-warning in-data-[type=loading]:opacity-80" /> | | |
| 132 | </div> | | |
| 133 | )} | | |
| 134 | | 88 | |
| 135 | <div className="flex flex-col gap-0.5"> | 89 | return ( |
| 136 | <Toast.Title className="font-medium" data-slot="toast-title" /> | 90 | <Toast.Root |
| 137 | <Toast.Description | 91 | className={cn( |
| 138 | className="text-muted-foreground" | 92 | "absolute z-[calc(9999-var(--toast-index))] h-(--toast-calc-height) w-full select-none rounded-lg border bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 [transition:transform_.5s_cubic-bezier(.22,1,.36,1),opacity_.5s,height_.15s] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", |
| 139 | data-slot="toast-description" | 93 | // Base positioning using data-position |
| 140 | /> | 94 | "data-[position*=right]:right-0 data-[position*=right]:left-auto", |
| 141 | </div> | 95 | "data-[position*=left]:right-auto data-[position*=left]:left-0", |
| 142 | </div> | 96 | "data-[position*=center]:right-0 data-[position*=center]:left-0", |
| 143 | {toast.actionProps && ( | 97 | "data-[position*=top]:top-0 data-[position*=top]:bottom-auto data-[position*=top]:origin-top", |
| 144 | <Toast.Action className={buttonVariants({ size: "xs" })} data-slot="toast-action"> | 98 | "data-[position*=bottom]:top-auto data-[position*=bottom]:bottom-0 data-[position*=bottom]:origin-bottom", |
| 145 | {toast.actionProps.children} | 99 | // Gap fill for hover |
| 146 | </Toast.Action> | 100 | "after:absolute after:left-0 after:h-[calc(var(--toast-gap)+1px)] after:w-full", |
| | 101 | "data-[position*=top]:after:top-full", |
| | 102 | "data-[position*=bottom]:after:bottom-full", |
| | 103 | // Define some variables |
| | 104 | "[--toast-calc-height:var(--toast-frontmost-height,var(--toast-height))] [--toast-gap:--spacing(3)] [--toast-peek:--spacing(3)] [--toast-scale:calc(max(0,1-(var(--toast-index)*.1)))] [--toast-shrink:calc(1-var(--toast-scale))]", |
| | 105 | // Define offset-y variable |
| | 106 | "data-[position*=top]:[--toast-calc-offset-y:calc(var(--toast-offset-y)+var(--toast-index)*var(--toast-gap)+var(--toast-swipe-movement-y))]", |
| | 107 | "data-[position*=bottom]:[--toast-calc-offset-y:calc(var(--toast-offset-y)*-1+var(--toast-index)*var(--toast-gap)*-1+var(--toast-swipe-movement-y))]", |
| | 108 | // Default state transform |
| | 109 | "data-[position*=top]:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--toast-peek))+(var(--toast-shrink)*var(--toast-calc-height))))_scale(var(--toast-scale))]", |
| | 110 | "data-[position*=bottom]:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--toast-peek))-(var(--toast-shrink)*var(--toast-calc-height))))_scale(var(--toast-scale))]", |
| | 111 | // Limited state |
| | 112 | "data-limited:opacity-0", |
| | 113 | // Expanded state |
| | 114 | "data-expanded:h-(--toast-height)", |
| | 115 | "data-position:data-expanded:transform-[translateX(var(--toast-swipe-movement-x))_translateY(var(--toast-calc-offset-y))]", |
| | 116 | // Starting and ending animations |
| | 117 | "data-[position*=top]:data-starting-style:transform-[translateY(calc(-100%-var(--toast-inset)))]", |
| | 118 | "data-[position*=bottom]:data-starting-style:transform-[translateY(calc(100%+var(--toast-inset)))]", |
| | 119 | "data-ending-style:opacity-0", |
| | 120 | // Ending animations (direction-aware) |
| | 121 | "data-ending-style:not-data-limited:not-data-swipe-direction:transform-[translateY(calc(100%+var(--toast-inset)))]", |
| | 122 | "data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-100%-var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]", |
| | 123 | "data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+100%+var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]", |
| | 124 | "data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-100%-var(--toast-inset)))]", |
| | 125 | "data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+100%+var(--toast-inset)))]", |
| | 126 | // Ending animations (expanded) |
| | 127 | "data-expanded:data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-100%-var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]", |
| | 128 | "data-expanded:data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+100%+var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]", |
| | 129 | "data-expanded:data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-100%-var(--toast-inset)))]", |
| | 130 | "data-expanded:data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+100%+var(--toast-inset)))]", |
| 147 | )} | 131 | )} |
| 148 | </Toast.Content> | 132 | data-position={position} |
| 149 | </Toast.Root> | 133 | key={toast.id} |
| 150 | ); | 134 | swipeDirection={ |
| 151 | })} | 135 | position.includes("center") |
| | 136 | ? [isTop ? "up" : "down"] |
| | 137 | : position.includes("left") |
| | 138 | ? ["left", isTop ? "up" : "down"] |
| | 139 | : ["right", isTop ? "up" : "down"] |
| | 140 | } |
| | 141 | toast={toast} |
| | 142 | > |
| | 143 | <Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm transition-opacity duration-250 data-behind:not-data-expanded:pointer-events-none data-behind:opacity-0 data-expanded:opacity-100"> |
| | 144 | <div className="flex gap-2"> |
| | 145 | {Icon && ( |
| | 146 | <div |
| | 147 | className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0" |
| | 148 | data-slot="toast-icon" |
| | 149 | > |
| | 150 | <Icon className="in-data-[type=loading]:animate-spin in-data-[type=error]:text-destructive in-data-[type=info]:text-info in-data-[type=success]:text-success in-data-[type=warning]:text-warning in-data-[type=loading]:opacity-80" /> |
| | 151 | </div> |
| | 152 | )} |
| | 153 | |
| | 154 | <div className="flex flex-col gap-0.5"> |
| | 155 | <Toast.Title className="font-medium" data-slot="toast-title" /> |
| | 156 | <Toast.Description |
| | 157 | className="text-muted-foreground" |
| | 158 | data-slot="toast-description" |
| | 159 | /> |
| | 160 | </div> |
| | 161 | </div> |
| | 162 | {toast.actionProps && ( |
| | 163 | <Toast.Action |
| | 164 | className={buttonVariants({ size: "xs" })} |
| | 165 | data-slot="toast-action" |
| | 166 | > |
| | 167 | {toast.actionProps.children} |
| | 168 | </Toast.Action> |
| | 169 | )} |
| | 170 | </Toast.Content> |
| | 171 | </Toast.Root> |
| | 172 | ); |
| | 173 | })} |
| 152 | </Toast.Viewport> | 174 | </Toast.Viewport> |
| 153 | </Toast.Portal> | 175 | </Toast.Portal> |
| 154 | ); | 176 | ); |
| ... | @@ -164,76 +186,80 @@ function AnchoredToastProvider({ children, ...props }: Toast.Provider.Props) { | ... | @@ -164,76 +186,80 @@ function AnchoredToastProvider({ children, ...props }: Toast.Provider.Props) { |
| 164 | } | 186 | } |
| 165 | | 187 | |
| 166 | function AnchoredToasts() { | 188 | function AnchoredToasts() { |
| 167 | const { toasts } = Toast.useToastManager(); | 189 | const { state } = useStore(); |
| | 190 | const { toasts } = Toast.useToastManager<ThreadToastData>(); |
| | 191 | const activeThreadId = state.activeThreadId; |
| 168 | | 192 | |
| 169 | return ( | 193 | return ( |
| 170 | <Toast.Portal data-slot="toast-portal-anchored"> | 194 | <Toast.Portal data-slot="toast-portal-anchored"> |
| 171 | <Toast.Viewport className="outline-none" data-slot="toast-viewport-anchored"> | 195 | <Toast.Viewport className="outline-none" data-slot="toast-viewport-anchored"> |
| 172 | {toasts.map((toast) => { | 196 | {toasts |
| 173 | const Icon = toast.type ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS] : null; | 197 | .filter((toast) => shouldRenderForActiveThread(toast.data, activeThreadId)) |
| 174 | const tooltipStyle = (toast.data as { tooltipStyle?: boolean })?.tooltipStyle ?? false; | 198 | .map((toast) => { |
| 175 | const positionerProps = toast.positionerProps; | 199 | const Icon = toast.type ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS] : null; |
| 176 | | 200 | const tooltipStyle = toast.data?.tooltipStyle ?? false; |
| 177 | if (!positionerProps?.anchor) { | 201 | const positionerProps = toast.positionerProps; |
| 178 | return null; | 202 | |
| 179 | } | 203 | if (!positionerProps?.anchor) { |
| 180 | | 204 | return null; |
| 181 | return ( | 205 | } |
| 182 | <Toast.Positioner | 206 | |
| 183 | className="z-50 max-w-[min(--spacing(64),var(--available-width))]" | 207 | return ( |
| 184 | data-slot="toast-positioner" | 208 | <Toast.Positioner |
| 185 | key={toast.id} | 209 | className="z-50 max-w-[min(--spacing(64),var(--available-width))]" |
| 186 | sideOffset={positionerProps.sideOffset ?? 4} | 210 | data-slot="toast-positioner" |
| 187 | toast={toast} | 211 | key={toast.id} |
| 188 | > | 212 | sideOffset={positionerProps.sideOffset ?? 4} |
| 189 | <Toast.Root | | |
| 190 | className={cn( | | |
| 191 | "relative text-balance border bg-popover not-dark:bg-clip-padding text-popover-foreground text-xs transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/4%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", | | |
| 192 | tooltipStyle | | |
| 193 | ? "rounded-md shadow-md/5 before:rounded-[calc(var(--radius-md)-1px)]" | | |
| 194 | : "rounded-lg shadow-lg/5 before:rounded-[calc(var(--radius-lg)-1px)]", | | |
| 195 | )} | | |
| 196 | data-slot="toast-popup" | | |
| 197 | toast={toast} | 213 | toast={toast} |
| 198 | > | 214 | > |
| 199 | {tooltipStyle ? ( | 215 | <Toast.Root |
| 200 | <Toast.Content className="pointer-events-auto px-2 py-1"> | 216 | className={cn( |
| 201 | <Toast.Title data-slot="toast-title" /> | 217 | "relative text-balance border bg-popover not-dark:bg-clip-padding text-popover-foreground text-xs transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/4%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", |
| 202 | </Toast.Content> | 218 | tooltipStyle |
| 203 | ) : ( | 219 | ? "rounded-md shadow-md/5 before:rounded-[calc(var(--radius-md)-1px)]" |
| 204 | <Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm"> | 220 | : "rounded-lg shadow-lg/5 before:rounded-[calc(var(--radius-lg)-1px)]", |
| 205 | <div className="flex gap-2"> | 221 | )} |
| 206 | {Icon && ( | 222 | data-slot="toast-popup" |
| 207 | <div | 223 | toast={toast} |
| 208 | className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0" | 224 | > |
| 209 | data-slot="toast-icon" | 225 | {tooltipStyle ? ( |
| 210 | > | 226 | <Toast.Content className="pointer-events-auto px-2 py-1"> |
| 211 | <Icon className="in-data-[type=loading]:animate-spin in-data-[type=error]:text-destructive in-data-[type=info]:text-info in-data-[type=success]:text-success in-data-[type=warning]:text-warning in-data-[type=loading]:opacity-80" /> | 227 | <Toast.Title data-slot="toast-title" /> |
| 212 | </div> | 228 | </Toast.Content> |
| 213 | )} | 229 | ) : ( |
| | 230 | <Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm"> |
| | 231 | <div className="flex gap-2"> |
| | 232 | {Icon && ( |
| | 233 | <div |
| | 234 | className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0" |
| | 235 | data-slot="toast-icon" |
| | 236 | > |
| | 237 | <Icon className="in-data-[type=loading]:animate-spin in-data-[type=error]:text-destructive in-data-[type=info]:text-info in-data-[type=success]:text-success in-data-[type=warning]:text-warning in-data-[type=loading]:opacity-80" /> |
| | 238 | </div> |
| | 239 | )} |
| 214 | | 240 | |
| 215 | <div className="flex flex-col gap-0.5"> | 241 | <div className="flex flex-col gap-0.5"> |
| 216 | <Toast.Title className="font-medium" data-slot="toast-title" /> | 242 | <Toast.Title className="font-medium" data-slot="toast-title" /> |
| 217 | <Toast.Description | 243 | <Toast.Description |
| 218 | className="text-muted-foreground" | 244 | className="text-muted-foreground" |
| 219 | data-slot="toast-description" | 245 | data-slot="toast-description" |
| 220 | /> | 246 | /> |
| | 247 | </div> |
| 221 | </div> | 248 | </div> |
| 222 | </div> | 249 | {toast.actionProps && ( |
| 223 | {toast.actionProps && ( | 250 | <Toast.Action |
| 224 | <Toast.Action | 251 | className={buttonVariants({ size: "xs" })} |
| 225 | className={buttonVariants({ size: "xs" })} | 252 | data-slot="toast-action" |
| 226 | data-slot="toast-action" | 253 | > |
| 227 | > | 254 | {toast.actionProps.children} |
| 228 | {toast.actionProps.children} | 255 | </Toast.Action> |
| 229 | </Toast.Action> | 256 | )} |
| 230 | )} | 257 | </Toast.Content> |
| 231 | </Toast.Content> | 258 | )} |
| 232 | )} | 259 | </Toast.Root> |
| 233 | </Toast.Root> | 260 | </Toast.Positioner> |
| 234 | </Toast.Positioner> | 261 | ); |
| 235 | ); | 262 | })} |
| 236 | })} | | |
| 237 | </Toast.Viewport> | 263 | </Toast.Viewport> |
| 238 | </Toast.Portal> | 264 | </Toast.Portal> |
| 239 | ); | 265 | ); |