import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastTriggerButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          title: "Toast created",
          description: "This is a toast notification.",
        })
      }
    >
      Show toast
    </Button>
  );
}

export function ToastBasicDemo() {
  return (
    <Toasty>
      <ToastTriggerButton />
    </Toasty>
  );
}

安装

桶式导出

import { Toasty, useKumoToastManager } from "@cloudflare/kumo";

细粒度导入

import { Toasty, useKumoToastManager } from "@cloudflare/kumo/components/toast";

用法

toast 系统由两部分组成:用于触发 toast 的 Toasty provider 组件与 useKumoToastManager() hook。

import { Toasty, useKumoToastManager, Button } from "@cloudflare/kumo";

function ToastTrigger() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          title: "Success!",
          description: "Your changes have been saved.",
        })
      }
    >
      Save changes
    </Button>
  );
}

export default function App() {
  return (
    <Toasty>
      <ToastTrigger />
      {/* Rest of your app */}
    </Toasty>
  );
}

配置

用 Toasty provider 包裹你的应用(或其中一部分)。它会建立 toast 上下文并渲染 toast 视口。

// In your app root or layout
import { Toasty } from "@cloudflare/kumo";

export function Layout({ children }) {
  return <Toasty>{children}</Toasty>;
}

示例

标题与描述

同时包含标题与描述的完整 toast。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastTriggerButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          title: "Toast created",
          description: "This is a toast notification.",
        })
      }
    >
      Show toast
    </Button>
  );
}

export function ToastBasicDemo() {
  return (
    <Toasty>
      <ToastTriggerButton />
    </Toasty>
  );
}

仅标题

仅包含标题的简单 toast,适合简短消息。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastTitleOnlyButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          title: "Settings saved",
        })
      }
    >
      Title only
    </Button>
  );
}

export function ToastTitleOnlyDemo() {
  return (
    <Toasty>
      <ToastTitleOnlyButton />
    </Toasty>
  );
}

仅描述

仅包含描述的 toast,适合更详细的消息。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastDescriptionOnlyButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          description: "Your changes have been saved successfully.",
        })
      }
    >
      Description only
    </Button>
  );
}

export function ToastDescriptionOnlyDemo() {
  return (
    <Toasty>
      <ToastDescriptionOnlyButton />
    </Toasty>
  );
}

成功变体

确认或正面结果请使用成功变体。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

/** Success toast with green accent border and check icon. */
function ToastSuccessButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      variant="primary"
      onClick={() =>
        toastManager.add({
          title: "Deployed successfully",
          description: "Your Worker is now live.",
          variant: "success",
        })
      }
    >
      Deploy Worker
    </Button>
  );
}

export function ToastSuccessDemo() {
  return (
    <Toasty>
      <ToastSuccessButton />
    </Toasty>
  );
}

多个 Toast

多个 toast 会平滑堆叠并带有动画效果。将鼠标悬停在堆叠区域可展开它们。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastMultipleButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() => {
        toastManager.add({
          title: "First toast",
          description: "This is the first notification.",
        });
        setTimeout(() => {
          toastManager.add({
            title: "Second toast",
            description: "This is the second notification.",
          });
        }, 500);
        setTimeout(() => {
          toastManager.add({
            title: "Third toast",
            description: "This is the third notification.",
          });
        }, 1000);
      }}
    >
      Show multiple toasts
    </Button>
  );
}

export function ToastMultipleDemo() {
  return (
    <Toasty>
      <ToastMultipleButton />
    </Toasty>
  );
}

去重的 Toast

为重复通知设置稳定的 id,让屏幕上只保留一个 toast。 快速点击:每次触发都会更新当前 toast,而不是再堆叠一个副本。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastDeduplicatedButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          id: "deduplicated-toast",
          title: "Connection lost",
          description:
            "Click again: this toast bumps instead of stacking a copy.",
        })
      }
    >
      Show same toast
    </Button>
  );
}

/** Reuses a stable ID so repeated triggers bump one toast instead of adding copies. */
export function ToastDeduplicatedDemo() {
  return (
    <Toasty>
      <ToastDeduplicatedButton />
    </Toasty>
  );
}

函数式更新

可根据 toast 的当前状态将其就地更新。本示例在部署 toast 创建后把其变为成功状态。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastFunctionalUpdateButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() => {
        const id = toastManager.add({
          id: "functional-update",
          title: "Deploying Worker",
          description: "Uploading your changes.",
          variant: "info",
          data: { deployment: "in progress" },
        });

        setTimeout(() => {
          toastManager.update(id, (toast) => ({
            title: "Worker deployed",
            description: `Deployment was ${toast.data.deployment}.`,
            variant: "success",
          }));
        }, 1200);
      }}
    >
      Deploy Worker
    </Button>
  );
}

/** Demonstrates updating a toast from its current state. */
export function ToastFunctionalUpdateDemo() {
  return (
    <Toasty>
      <ToastFunctionalUpdateButton />
    </Toasty>
  );
}

错误变体

需要关注的严重问题请使用错误变体。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastErrorButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          title: "Deployment failed",
          description: "Unable to connect to the server.",
          variant: "error",
        })
      }
    >
      Show error toast
    </Button>
  );
}

export function ToastErrorDemo() {
  return (
    <Toasty>
      <ToastErrorButton />
    </Toasty>
  );
}

警告变体

需要警示的消息请使用警告变体。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastWarningButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          title: "Rate limit warning",
          description: "You're approaching your API quota.",
          variant: "warning",
        })
      }
    >
      Show warning toast
    </Button>
  );
}

export function ToastWarningDemo() {
  return (
    <Toasty>
      <ToastWarningButton />
    </Toasty>
  );
}

信息变体

中性信息类消息请使用信息变体。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

/** Info toast with blue accent border and info icon. */
function ToastInfoButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          title: "New version available",
          description: "Kumo v4.2 includes performance improvements.",
          variant: "info",
        })
      }
    >
      Show info toast
    </Button>
  );
}

export function ToastInfoDemo() {
  return (
    <Toasty>
      <ToastInfoButton />
    </Toasty>
  );
}

自定义内容

使用 content 属性可渲染完全自定义的 toast 内容。

import { Button, Toasty, useKumoToastManager, Link } from "@cloudflare/kumo";
import { CheckCircleIcon } from "@phosphor-icons/react/dist/ssr";

function ToastCustomContentButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          content: (
            <div>
              <div className="flex items-center gap-2">
                <CheckCircleIcon />
                <Link href="/">my-first-worker</Link> created!
              </div>
            </div>
          ),
        })
      }
    >
      Show custom content
    </Button>
  );
}

export function ToastCustomContentDemo() {
  return (
    <Toasty>
      <ToastCustomContentButton />
    </Toasty>
  );
}

操作按钮

为 toast 添加操作按钮,以便用户交互。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastActionsButton() {
  const toastManager = useKumoToastManager();

  return (
    <Button
      onClick={() =>
        toastManager.add({
          title: "Need help?",
          description: "Get assistance with your deployment.",
          actions: [
            {
              children: "Support",
              variant: "secondary",
              onClick: () => console.log("Support clicked"),
            },
            {
              children: "Ask AI",
              variant: "primary",
              onClick: () => console.log("Ask AI clicked"),
            },
          ],
        })
      }
    >
      Show with actions
    </Button>
  );
}

export function ToastActionsDemo() {
  return (
    <Toasty>
      <ToastActionsButton />
    </Toasty>
  );
}

Promise

使用 promise 方法可自动展示加载、成功和错误状态。

import { Button, Toasty, useKumoToastManager } from "@cloudflare/kumo";

function ToastPromiseButton() {
  const toastManager = useKumoToastManager();

  const simulateDeployment = () => {
    return new Promise<{ name: string }>((resolve, reject) => {
      setTimeout(() => {
        if (Math.random() > 0.3) {
          resolve({ name: "my-worker" });
        } else {
          reject(new Error("Network error"));
        }
      }, 2000);
    });
  };

  return (
    <Button
      onClick={() =>
        toastManager.promise(simulateDeployment(), {
          loading: {
            title: "Deploying...",
            description: "Please wait while we deploy your Worker.",
          },
          success: (data) => ({
            title: "Deployed!",
            description: `Worker "${data.name}" is now live.`,
          }),
          error: (err) => ({
            title: "Deployment failed",
            description: err.message,
            variant: "error",
          }),
        })
      }
    >
      Deploy with promise
    </Button>
  );
}

export function ToastPromiseDemo() {
  return (
    <Toasty>
      <ToastPromiseButton />
    </Toasty>
  );
}

API 参考

Toasty

包裹应用并管理 toast 系统的 provider 组件。

PropTypeDefaultDescription
variant"default" | "success" | "error" | "warning" | "info""default"-
children*React.ReactNode-

应用程序内容。Toast 通过 portal 渲染在该内容上方。

containerPortalContainer-

传送门的容器元素。使用此属性可在 Shadow DOM 或自定义容器中渲染提示消息。覆盖 KumoPortalProvider 上下文。

toastManagerReturnType<typeof createKumoToastManager>-

可选的由 createKumoToastManager() 创建的 toast 管理器。提供后,允许 React 树外部的代码(定时器、模块加载回调、查询缓存监听器)通过同一去重感知的管理器派发 toast,该管理器与树内部 useKumoToastManager() 返回的管理器相同。转发到底层 @base-ui/react/toast 的 Toast.Provider 的 toastManager 属性——有关上游原语,请参阅 https://base-ui.com/react/components/toast。

useKumoToastManager()

返回用于创建 toast 的 toast 管理器 hook。

const toastManager = useKumoToastManager();

// Add a toast
toastManager.add(options);

// Update from the current toast state
toastManager.update(toastId, (toast) => ({
  description: `Updated after ${toast.timeout ?? 5000}ms`,
}));

// Promise-based toast
toastManager.promise(asyncFn(), {
  loading: options,
  success: (data) => options,
  error: (err) => options,
});

Toast 选项

传递给 toastManager.add() 及 promise 处理函数的选项。

属性类型默认值说明
titlestring—醒目展示的 toast 标题。
descriptionstring—显示在标题下方的次要文本。
variant

“default” | “success” | “error” | “warning” | “info"

"default”toast 的视觉样式。
contentReactNode—

在 toast 内部渲染的自定义内容,会覆盖 title 与 description。

actionsButtonProps[]—以操作按钮形式渲染的按钮属性数组。
timeoutnumber5000

toast 自动消失前的毫秒数。