diff options
| author | Mohamed Bassem <me@mbassem.com> | 2025-12-28 08:32:32 +0000 |
|---|---|---|
| committer | Mohamed Bassem <me@mbassem.com> | 2025-12-28 08:32:32 +0000 |
| commit | 173fb99aed957fd8b9b47455a1cb5b6cf4115c34 (patch) | |
| tree | dec7ca534312c2863e32c004140484916635a2bb /apps/web/components/ui/sonner.tsx | |
| parent | af3010abaa37f7db4144820469422bdbb432adfc (diff) | |
| download | karakeep-173fb99aed957fd8b9b47455a1cb5b6cf4115c34.tar.zst | |
refactor: migrate toasts to sonner
Diffstat (limited to 'apps/web/components/ui/sonner.tsx')
| -rw-r--r-- | apps/web/components/ui/sonner.tsx | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/apps/web/components/ui/sonner.tsx b/apps/web/components/ui/sonner.tsx new file mode 100644 index 00000000..d281f4ae --- /dev/null +++ b/apps/web/components/ui/sonner.tsx @@ -0,0 +1,71 @@ +"use client"; + +import { + CircleCheck, + Info, + LoaderCircle, + OctagonX, + TriangleAlert, +} from "lucide-react"; +import { useTheme } from "next-themes"; +import { Toaster as Sonner, toast } from "sonner"; + +type ToasterProps = React.ComponentProps<typeof Sonner>; + +const Toaster = ({ ...props }: ToasterProps) => { + const { theme = "system" } = useTheme(); + + return ( + <Sonner + theme={theme as ToasterProps["theme"]} + className="toaster group" + icons={{ + success: <CircleCheck className="h-4 w-4" />, + info: <Info className="h-4 w-4" />, + warning: <TriangleAlert className="h-4 w-4" />, + error: <OctagonX className="h-4 w-4" />, + loading: <LoaderCircle className="h-4 w-4 animate-spin" />, + }} + toastOptions={{ + classNames: { + toast: + "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg", + description: "group-[.toast]:text-muted-foreground", + actionButton: + "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground", + cancelButton: + "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground", + }, + }} + {...props} + /> + ); +}; + +/** + * Compat layer for migrating from old toaster to sonner + * @deprecated Use sonner's natie toast instead + */ +const legacyToast = ({ + title, + description, + variant, +}: { + title?: React.ReactNode; + description?: React.ReactNode; + variant?: "destructive" | "default"; +}) => { + let toastTitle = title; + let toastDescription: React.ReactNode | undefined = description; + if (!title) { + toastTitle = description; + toastDescription = undefined; + } + if (variant === "destructive") { + toast.error(toastTitle, { description: toastDescription }); + } else { + toast(toastTitle, { description: toastDescription }); + } +}; + +export { Toaster, legacyToast as toast }; |
