diff --git a/web/src/app/_components/toaster.tsx b/web/src/app/_components/toaster.tsx new file mode 100644 index 0000000..6f727b9 --- /dev/null +++ b/web/src/app/_components/toaster.tsx @@ -0,0 +1,33 @@ +// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates +// SPDX-License-Identifier: MIT + +"use client"; + +import { useTheme } from "next-themes"; +import { Toaster as Sonner } from "sonner"; + +type ToasterProps = React.ComponentProps; + +const Toaster = ({ ...props }: ToasterProps) => { + const { resolvedTheme = "dark" } = useTheme(); + return ( + + ); +}; + +export { Toaster }; diff --git a/web/src/app/_components/tooltip.tsx b/web/src/app/_components/tooltip.tsx index 9b537ce..e636f84 100644 --- a/web/src/app/_components/tooltip.tsx +++ b/web/src/app/_components/tooltip.tsx @@ -6,6 +6,7 @@ import { TooltipContent, TooltipTrigger, } from "~/components/ui/tooltip"; +import { cn } from "~/lib/utils"; export function Tooltip({ className, @@ -25,7 +26,11 @@ export function Tooltip({ return ( {children} - + {title} diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx index b51d16f..7405c4c 100644 --- a/web/src/app/layout.tsx +++ b/web/src/app/layout.tsx @@ -9,6 +9,8 @@ import { Geist } from "next/font/google"; import { ThemeProviderWrapper } from "~/app/_components/theme-provider-wrapper"; import { TooltipProvider } from "~/components/ui/tooltip"; +import { Toaster } from "./_components/toaster"; + export const metadata: Metadata = { title: "🦌 DeerFlow", description: @@ -30,6 +32,7 @@ export default function RootLayout({ {children} + ); diff --git a/web/src/core/store/store.ts b/web/src/core/store/store.ts index 13af2f0..eaaf483 100644 --- a/web/src/core/store/store.ts +++ b/web/src/core/store/store.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MIT import { nanoid } from "nanoid"; +import { toast } from "sonner"; import { create } from "zustand"; import { chatStream, generatePodcast } from "../api"; @@ -136,6 +137,7 @@ export async function sendMessage( } } } catch { + toast("An error occurred while generating the response. Please try again."); // Update message status. // TODO: const isAborted = (error as Error).name === "AbortError"; if (messageId != null) {