---
title: 轻提示 Toast
url: https://ui.zhaozimin.cn/components/toast/
markdown: https://ui.zhaozimin.cn/components/toast.md
group: 组件
origin: 提炼层组件（src/extracted），本仓库是唯一源头
source:
  - src/extracted/Feedback.jsx  # https://ui.zhaozimin.cn/src/extracted/Feedback.jsx
  - src/extracted/extracted.css  # https://ui.zhaozimin.cn/src/extracted/extracted.css
version: v0.2.0  # 设计系统版本，发布于 2026-09-23
scope: .zzm-v4   # 根节点必须带这个类，否则样式不生效
css: https://ui.zhaozimin.cn/v/0.2.0/zzm.css   # 锁版本地址，本仓库再改也不影响你
---

# 轻提示 Toast

> 深墨胶囊，从下方浮起，1.8 秒后消失。它不可点，所以可以是胶囊。文案说结果，不说过程：「已保存到你的笔记库」。

### 样张 · 点一下试试

React：

```jsx
import { useRef, useState } from 'react'
import { Toast } from './extracted/Feedback.jsx'
import { Btn } from './components/v4/Button.jsx'

export default function ToastDemo() {
  const [show, setShow] = useState(false)
  const timer = useRef(null)
  const fire = () => {
    clearTimeout(timer.current)
    setShow(false)
    requestAnimationFrame(() => setShow(true))
    timer.current = setTimeout(() => setShow(false), 1800)
  }
  return (
    <div style={{ position: 'relative', width: '100%', minHeight: 112, display: 'grid', placeItems: 'center' }}>
      <Btn onClick={fire}>保存笔记</Btn>
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, display: 'flex', justifyContent: 'center', pointerEvents: 'none' }}>
        {show ? <Toast>✓ 已保存到你的笔记库</Toast> : null}
      </div>
    </div>
  )
}
```

HTML（构建时由上面的 React 渲染得到，可直接粘贴）：

```html
<div style="position: relative; width: 100%; min-height: 112px; display: grid; place-items: center">
  <button type="button" class="zzm-btn">保存笔记</button>
  <div
    style="
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      display: flex;
      justify-content: center;
      pointer-events: none;
    "
  ></div>
</div>
```

### 样张 · 静态样式

React：

```jsx
import { Toast } from './extracted/Feedback.jsx'

export function Static() {
  return <Toast>✓ 已保存到你的笔记库</Toast>
}
```

HTML（构建时由上面的 React 渲染得到，可直接粘贴）：

```html
<div role="status" class="zzm-toast">✓ 已保存到你的笔记库</div>
```

## 定位的坑

`.zzm-toast` 带 `zzmUp` 进场动画，动画结束帧是 `transform: none`——如果你用 `left 50%` 加 `translateX(-50%)` 居中，动画会把 transform 覆盖掉，提示就偏到右边去了。**用外层 flex 居中**：

正确的居中方式：

```html
<div style="position:fixed;left:0;right:0;bottom:24px;display:flex;justify-content:center;pointer-events:none">
  <div class="zzm-toast" role="status">✓ 已保存到你的笔记库</div>
</div>
```

## 铁律

- ✓ 要：说结果：「已保存」「已复制」「已删除」
- ✗ 不要：说过程或道歉：「操作成功！」「抱歉，出错了」
- ✓ 要：1.8 秒自动消失；出错要让人处理时用确认窗或内联错误

## 本页用到的 CSS

按样张里出现的类名，从源文件原样裁出（完整版见 zzm.css）：

```css
/* controls.css */

.zzm-v4 .zzm-btn {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 36px;
  padding: 0 16px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .2px;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  border-radius: 8px;                                   /* 圆角矩形——按钮禁胶囊 */
  border: 1px solid rgba(0, 0, 0, .14);
  color: #3F3F3B;
  background: linear-gradient(180deg, #FFFFFF 0%, #F2F2EF 100%);
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .55),                 /* ④ 反光光晕环 */
    0 1px 2px rgba(0, 0, 0, .09),                       /* ③ 近影 */
    0 2px 6px rgba(0, 0, 0, .06),                       /* ③ 远影 */
    inset 0 1px 0 rgba(255, 255, 255, .92),             /* ② 顶部反光 */
    inset 0 -1px 0 rgba(0, 0, 0, .05);                  /* ① 底缘收沉 */
  transition: box-shadow .16s ease, transform .16s ease, background .16s ease,
    border-color .16s ease, filter .16s ease, opacity .16s ease;
}

.zzm-v4 .zzm-btn:hover {
  transform: translateY(-1px);
  border-color: rgba(0, 0, 0, .18);
  box-shadow:
    0 0 0 4px rgba(255, 255, 255, .8),
    0 2px 4px rgba(0, 0, 0, .10),
    0 4px 12px rgba(0, 0, 0, .09),
    inset 0 1px 0 rgba(255, 255, 255, .95),
    inset 0 -1px 0 rgba(0, 0, 0, .05);
}

.zzm-v4 .zzm-btn:active {
  transform: translateY(0);
  background: linear-gradient(180deg, #ECECE9 0%, #F4F4F1 100%);   /* ⑤ 凹面翻转 */
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .45),
    0 1px 0 rgba(255, 255, 255, .65),
    inset 0 2px 4px rgba(0, 0, 0, .13),
    inset 0 1px 2px rgba(0, 0, 0, .09);
}

.zzm-v4 .zzm-btn:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 3px rgba(166, 64, 47, .20),                   /* 键盘焦点＝朱色光晕 */
    0 1px 2px rgba(0, 0, 0, .09),
    0 2px 6px rgba(0, 0, 0, .06),
    inset 0 1px 0 rgba(255, 255, 255, .92);
}

.zzm-v4 .zzm-btn:disabled {
  cursor: not-allowed;
  transform: none;
}

.zzm-v4 .zzm-btn:disabled:not(.zzm-btn--busy) {
  color: #A2A29C;
  background: #F2F2EF;
  border-color: rgba(0, 0, 0, .08);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .7), 0 1px 2px rgba(0, 0, 0, .04);
}

/* extracted.css */

.zzm-v4 .zzm-toast {
  display: inline-block; background: #1D1D1B; color: #FFFFFF; font-size: 12px;
  padding: 9px 18px; border-radius: 999px; white-space: nowrap;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .3);
  animation: zzmUp .25s ease both;
}

/* keyframes */
@keyframes zzmUp    { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: none } }
```

---

上一页：[确认窗](https://ui.zhaozimin.cn/components/dialog.md) · 下一页：[进度条](https://ui.zhaozimin.cn/components/progress.md) · 全站目录：https://ui.zhaozimin.cn/llms.txt
