11import * as React from 'react'
2- import * as Toast from '@radix-ui/react-toast'
2+ import { Toaster , toast } from 'sonner'
3+ import { useTheme } from '~/components/ThemeProvider'
34
45type ToastOptions = {
56 durationMs ?: number
67}
78
8- type ToastItem = {
9- id : string
10- content : React . ReactNode
11- durationMs : number
12- }
13-
149type ToastContextValue = {
1510 notify : ( content : React . ReactNode , options ?: ToastOptions ) => string
1611}
@@ -30,46 +25,39 @@ export function ToastProvider({
3025} : {
3126 children : React . ReactNode
3227} ) : React . ReactElement {
33- const [ toasts , setToasts ] = React . useState < ToastItem [ ] > ( [ ] )
28+ const { resolvedTheme } = useTheme ( )
3429
3530 const notify = React . useCallback (
3631 ( content : React . ReactNode , options ?: ToastOptions ) => {
37- const id = Math . random ( ) . toString ( 36 ) . slice ( 2 )
38- const durationMs = options ?. durationMs ?? 2500
39- setToasts ( ( prev ) => [ ...prev , { id, content, durationMs } ] )
40- return id
32+ const id = toast ( content , { duration : options ?. durationMs ?? 2500 } )
33+ return String ( id )
4134 } ,
4235 [ ] ,
4336 )
4437
45- const removeToast = React . useCallback ( ( id : string ) => {
46- setToasts ( ( prev ) => prev . filter ( ( t ) => t . id !== id ) )
47- } , [ ] )
48-
4938 const contextValue = React . useMemo < ToastContextValue > (
5039 ( ) => ( { notify } ) ,
5140 [ notify ] ,
5241 )
5342
5443 return (
5544 < ToastContext . Provider value = { contextValue } >
56- < Toast . Provider swipeDirection = "right" >
57- { children }
58- { toasts . map ( ( t ) => (
59- < Toast . Root
60- key = { t . id }
61- defaultOpen
62- duration = { t . durationMs }
63- onOpenChange = { ( open ) => {
64- if ( ! open ) removeToast ( t . id )
65- } }
66- className = "relative z-[60] rounded-md border border-gray-200 bg-white px-3 py-2 text-sm text-gray-900 shadow-lg outline-none dark:border-gray-700 dark:bg-gray-800 dark:text-gray-50"
67- >
68- < div className = "flex items-start gap-2" > { t . content } </ div >
69- </ Toast . Root >
70- ) ) }
71- < Toast . Viewport className = "fixed bottom-4 right-4 z-[60] flex max-h-screen w-96 flex-col gap-2 p-0 outline-none" />
72- </ Toast . Provider >
45+ { children }
46+ < Toaster
47+ theme = { resolvedTheme }
48+ position = "bottom-right"
49+ swipeDirections = { [ 'right' ] }
50+ offset = { 16 }
51+ gap = { 8 }
52+ toastOptions = { {
53+ unstyled : true ,
54+ classNames : {
55+ toast :
56+ 'relative w-96 rounded-md border border-gray-200 bg-white px-3 py-2 text-sm text-gray-900 shadow-lg outline-none dark:border-gray-700 dark:bg-gray-800 dark:text-gray-50' ,
57+ content : 'flex items-start gap-2' ,
58+ } ,
59+ } }
60+ />
7361 </ ToastContext . Provider >
7462 )
7563}
0 commit comments