'use client';
import {
UNSTABLE_ToastRegion as ToastRegion,
UNSTABLE_Toast as Toast,
UNSTABLE_ToastQueue as ToastQueue,
UNSTABLE_ToastContent as ToastContent,
ToastProps,
Text
} from 'react-aria-components';
import {Button} from '@/registry/react-aria/ui/Button';
import {X} from 'lucide-react';
import './Toast.css';
import {flushSync} from 'react-dom';
// Define the type for your toast content. This interface defines the properties of your toast content, affecting what you
// pass to the queue calls as arguments.
interface MyToastContent {
title: string;
description?: string;
}
// This is a global toast queue, to be imported and called where ever you want to queue a toast via queue.add().
export const queue = new ToastQueue<MyToastContent>({
// Wrap state updates in a CSS view transition.
wrapUpdate(fn) {
if ('startViewTransition' in document) {
document.startViewTransition(() => {
flushSync(fn);
});
} else {
fn();
}
}
});
export function MyToastRegion() {
return (
// The ToastRegion should be rendered at the root of your app.
(<ToastRegion queue={queue}>
{({toast}) => (
<MyToast toast={toast} style={{viewTransitionName: toast.key}}>
<ToastContent>
<Text slot="title">{toast.content.title}</Text>
{toast.content.description && (
<Text slot="description">{toast.content.description}</Text>
)}
</ToastContent>
<Button slot="close" aria-label="Close" variant="quiet">
<X size={16} />
</Button>
</MyToast>
)}
</ToastRegion>)
);
}
export function MyToast(props: ToastProps<MyToastContent>) {
return <Toast {...props} />;
}