logo
导航

Toast 通知组件

Toast 通知组件用于显示临时的反馈消息,支持多种类型(成功、错误、警告、信息)和自动消失功能。与 DashboardLayout 深度集成,提供全局通知能力。

特性

  • 🎯 四种类型 - 支持 success、error、warning、info 四种消息类型
  • 简单 API - 通过全局函数 showToast() 快速调用
  • 🔄 自动管理 - 自动显示、定时消失和内存清理
  • 🎨 优雅动画 - 平滑的滑入滑出动画效果
  • 📱 响应式设计 - 适配不同屏幕尺寸
  • 可访问性 - 支持屏幕阅读器和 ARIA 标准
  • 🔧 批量管理 - 支持同时显示多个通知和批量清除

基础用法

通过不同的标签页展示 Toast 的各种使用场景:

重要提示

在实际应用中,请确保将 <ToastContainer /> 放置在应用的根组件或布局组件中,这样 Toast 通知才能在任何页面正常工作。

展示四种不同类型的 Toast 通知:info、success、warning、error

表单保存

文件上传

系统通知

              ---
/**
 * @component ToastTypes
 * @description Toast 类型示例 - 展示不同类型的通知消息
 */

import { ToastContainer } from '@coffic/cosy-ui';
---

<div class="cosy:space-y-4">
  <div class="cosy:grid cosy:grid-cols-1 sm:cosy:grid-cols-2 cosy:gap-4">
    <button
      class="cosy:btn cosy:btn-info cosy:btn-block"
      onclick="showToast({ message: '系统信息:数据同步已完成', type: 'info' })">
      信息 (Info)
    </button>

    <button
      class="cosy:btn cosy:btn-success cosy:btn-block"
      onclick="showToast({ message: '成功:文件上传完成!', type: 'success' })">
      成功 (Success)
    </button>

    <button
      class="cosy:btn cosy:btn-warning cosy:btn-block"
      onclick="showToast({ message: '警告:磁盘空间不足', type: 'warning' })">
      警告 (Warning)
    </button>

    <button
      class="cosy:btn cosy:btn-error cosy:btn-block"
      onclick="showToast({ message: '错误:网络连接失败', type: 'error' })">
      错误 (Error)
    </button>
  </div>
</div>

<!-- Toast 容器 - 每个标签页独立 -->
<ToastContainer />

            

演示如何自定义 Toast 的显示时长,从快速提示到持久显示

表单保存

文件上传

系统通知

              ---
/**
 * @component ToastDuration
 * @description Toast 持续时间示例 - 展示不同持续时间的通知
 */

import { ToastContainer } from '@coffic/cosy-ui';
---

<div class="cosy:space-y-4">
  <div class="cosy:grid cosy:grid-cols-1 sm:cosy:grid-cols-2 cosy:gap-4">
    <button
      class="cosy:btn cosy:btn-outline cosy:btn-block"
      onclick="showToast({ message: '快速提示(1秒)', type: 'info', duration: 1000 })">
      短暂显示 (1s)
    </button>

    <button
      class="cosy:btn cosy:btn-outline cosy:btn-block"
      onclick="showToast({ message: '标准提示(3秒)', type: 'success', duration: 3000 })">
      标准显示 (3s)
    </button>

    <button
      class="cosy:btn cosy:btn-outline cosy:btn-block"
      onclick="showToast({ message: '重要提示(5秒)', type: 'warning', duration: 5000 })">
      长时间显示 (5s)
    </button>

    <button
      class="cosy:btn cosy:btn-outline cosy:btn-block"
      onclick="showToast({ message: '需要手动关闭的通知', type: 'error', duration: 0 })">
      持久显示 (手动关闭)
    </button>
  </div>
</div>

<!-- Toast 容器 - 每个标签页独立 -->
<ToastContainer />

            

展示手动控制 Toast 的各种操作:显示、关闭、批量管理

表单保存

文件上传

系统通知

              ---
/**
 * @component ToastControl
 * @description Toast 控制示例 - 展示手动控制通知的功能
 */

import { ToastContainer } from '@coffic/cosy-ui';
---

<div class="cosy:space-y-4">
  <div class="cosy:space-y-3">
    <div class="cosy:flex cosy:gap-3">
      <button
        class="cosy:btn cosy:btn-primary cosy:flex-1"
        onclick="window.currentToastId = showToast({ message: '可控制的通知消息', type: 'info', duration: 0 })">
        显示可控制通知
      </button>

      <button
        class="cosy:btn cosy:btn-ghost"
        onclick="if (window.currentToastId) { closeToast(window.currentToastId); window.currentToastId = null; }">
        关闭
      </button>
    </div>

    <div class="cosy:flex cosy:gap-3">
      <button
        class="cosy:btn cosy:btn-secondary cosy:flex-1"
        onclick="
          showToast({ message: '通知 1', type: 'info' });
          showToast({ message: '通知 2', type: 'success' });
          showToast({ message: '通知 3', type: 'warning' });
        ">
        显示多个通知
      </button>

      <button class="cosy:btn cosy:btn-ghost" onclick="clearAllToasts()">
        清除全部
      </button>
    </div>

    <div class="cosy:divider cosy:my-2"></div>

    <button
      class="cosy:btn cosy:btn-neutral cosy:btn-block"
      onclick="
        const id = showToast({ message: '这条通知将在 2 秒后自动关闭', type: 'warning', duration: 0 });
        setTimeout(() => closeToast(id), 2000);
      ">
      延时自动关闭示例
    </button>
  </div>
</div>

<!-- Toast 容器 - 每个标签页独立 -->
<ToastContainer />

            

模拟真实应用场景:表单保存、文件上传、系统通知等

表单保存

文件上传

系统通知

              ---
/**
 * @component ToastRealWorld
 * @description Toast 实际应用场景示例 - 模拟真实的使用场景
 */

import { ToastContainer } from '@coffic/cosy-ui';
---

<div class="cosy:space-y-4">
  <div class="cosy:space-y-3">
    <!-- 表单保存场景 -->
    <div class="cosy:card cosy:bg-base-100 cosy:shadow">
      <div class="cosy:card-body cosy:py-4">
        <h4 class="cosy:card-title cosy:text-base">表单保存</h4>
        <div class="cosy:flex cosy:gap-2">
          <button
            class="cosy:btn cosy:btn-success cosy:btn-sm"
            onclick="
              showToast({ message: '用户信息保存成功!', type: 'success' });
            ">
            保存成功
          </button>
          <button
            class="cosy:btn cosy:btn-error cosy:btn-sm"
            onclick="
              showToast({ message: '保存失败:请检查必填字段', type: 'error', duration: 5000 });
            ">
            保存失败
          </button>
        </div>
      </div>
    </div>

    <!-- 文件上传场景 -->
    <div class="cosy:card cosy:bg-base-100 cosy:shadow">
      <div class="cosy:card-body cosy:py-4">
        <h4 class="cosy:card-title cosy:text-base">文件上传</h4>
        <div class="cosy:flex cosy:gap-2">
          <button
            class="cosy:btn cosy:btn-primary cosy:btn-sm"
            onclick="
              const uploadId = showToast({ 
                message: '正在上传文件...', 
                type: 'info', 
                duration: 0 
              });
              setTimeout(() => {
                closeToast(uploadId);
                showToast({ message: '文件上传完成!', type: 'success' });
              }, 3000);
            ">
            开始上传
          </button>
          <button
            class="cosy:btn cosy:btn-warning cosy:btn-sm"
            onclick="
              showToast({ 
                message: '文件大小超过限制(最大 10MB)', 
                type: 'warning', 
                duration: 4000 
              });
            ">
            大小超限
          </button>
        </div>
      </div>
    </div>

    <!-- 系统通知场景 -->
    <div class="cosy:card cosy:bg-base-100 cosy:shadow">
      <div class="cosy:card-body cosy:py-4">
        <h4 class="cosy:card-title cosy:text-base">系统通知</h4>
        <div class="cosy:flex cosy:gap-2">
          <button
            class="cosy:btn cosy:btn-info cosy:btn-sm"
            onclick="
              showToast({ 
                message: '系统将在 5 分钟后进行维护', 
                type: 'info', 
                duration: 8000 
              });
            ">
            维护通知
          </button>
          <button
            class="cosy:btn cosy:btn-neutral cosy:btn-sm"
            onclick="
              showToast({ 
                message: '您有 3 条新消息', 
                type: 'info' 
              });
            ">
            新消息提醒
          </button>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- Toast 容器 - 每个标签页独立 -->
<ToastContainer />

            

独立使用

Toast 组件可以独立使用,只需要添加 ToastContainer:

---
import { ToastContainer } from '@coffic/cosy-ui';
---

<!-- 页面内容 -->
<div>
  <button onclick="showToast('操作成功!')">
    点击显示通知
  </button>
</div>

<!-- Toast 容器 -->
<ToastContainer />

API 参考

全局函数

showToast(config)

显示一个 Toast 通知。

// 字符串形式(简化用法)
const id = showToast('操作成功!');

// 对象形式(完整配置)
const id = showToast({
  message: '数据保存成功',
  type: 'success',       // 'info' | 'success' | 'warning' | 'error'
  duration: 3000,        // 显示时长(毫秒),0 表示不自动关闭
  id: 'custom-id'        // 可选的自定义 ID
});

参数:

  • config (string | ToastConfig) - 消息内容或配置对象

返回值:

  • string - Toast 的唯一 ID,可用于手动关闭

closeToast(id)

关闭指定的 Toast 通知。

const toastId = showToast('正在处理...');
setTimeout(() => closeToast(toastId), 2000);

参数:

  • id (string) - Toast 的唯一 ID

clearAllToasts()

关闭所有当前显示的 Toast 通知。

clearAllToasts();

ToastConfig 接口

interface ToastConfig {
  message: string;           // 消息内容
  type?: ToastType;          // 消息类型,默认 'info'
  duration?: number;         // 显示时长(毫秒),默认 3000
  id?: string;              // 自定义 ID,不提供会自动生成
}

type ToastType = 'info' | 'success' | 'warning' | 'error';

ToastContainer 组件

用于独立使用 Toast 系统的容器组件。

---
import { ToastContainer } from '@coffic/cosy-ui';
---

<!-- 页面内容 -->
<div>
  <button onclick="showToast('Hello!')">
    显示通知
  </button>
</div>

<!-- Toast 容器 -->
<ToastContainer />

注意: 如果使用 DashboardLayout,无需手动添加 ToastContainer。

样式定制

Toast 组件使用 DaisyUI 的 alert 样式系统,支持主题切换:

/* 自定义 Toast 容器位置 */
#toast-container {
  top: 1rem;
  right: 1rem;
  z-index: 50;
}

/* 自定义动画时长 */
.toast-enter, .toast-exit {
  transition-duration: 300ms;
}

最佳实践

1. 合理使用消息类型

// ✅ 正确:根据操作结果选择合适的类型
showToast({ message: '用户创建成功', type: 'success' });
showToast({ message: '网络连接失败', type: 'error' });
showToast({ message: '请注意数据安全', type: 'warning' });
showToast({ message: '系统维护通知', type: 'info' });

// ❌ 错误:类型与消息内容不匹配
showToast({ message: '操作失败', type: 'success' });

2. 设置合适的显示时长

// ✅ 正确:根据消息重要性设置时长
showToast({ message: '保存成功', duration: 2000 });      // 简单确认
showToast({ message: '重要警告信息', duration: 5000 });   // 重要提醒
showToast({ message: '正在处理...', duration: 0 });      // 需要手动关闭

// ❌ 错误:重要信息显示时间太短
showToast({ message: '系统将重启,请保存数据', duration: 1000 });

3. 避免信息过载

// ✅ 正确:合并相关消息
showToast({ message: '批量操作完成:成功 5 项,失败 1 项', type: 'warning' });

// ❌ 错误:短时间内显示过多消息
for (let i = 0; i < 10; i++) {
  showToast(`处理第 ${i + 1} 项`);
}

4. 提供有意义的消息

// ✅ 正确:清晰的操作反馈
showToast({ message: '用户 "张三" 已删除', type: 'success' });
showToast({ message: '上传失败:文件大小超过 10MB', type: 'error' });

// ❌ 错误:模糊的消息
showToast({ message: '操作完成', type: 'success' });
showToast({ message: '出错了', type: 'error' });

常见问题

Q: 为什么 showToast 函数未定义?

A: 确保已正确集成 Toast 系统:

  1. 使用 DashboardLayout 且 enableToast 为 true(默认)
  2. 或手动添加 <ToastContainer /> 到页面中
  3. 等待页面完全加载后再调用

Q: 如何在服务器端渲染时使用?

A: Toast 是客户端功能,只能在浏览器环境中使用:

// ✅ 正确:检查环境
if (typeof window !== 'undefined') {
  showToast('客户端消息');
}

// 或在事件处理函数中使用
function handleClick() {
  showToast('点击成功');  // 事件处理函数总是在客户端执行
}

Q: 如何实现持久化通知?

A: 设置 duration 为 0,手动控制关闭:

const persistentToast = showToast({
  message: '重要:请完成必填项',
  type: 'warning',
  duration: 0  // 不自动关闭
});

// 在某个条件满足时关闭
if (formIsValid) {
  closeToast(persistentToast);
}