Toast
Thông báo ngắn về việc người dùng vừa làm, ở góc màn hình: Đã lưu thay đổi, Đã sao chép liên kết, Tải lên thất bại. Nó tự đóng sau vài giây. Mount một Toaster ở root của app và gọi toast({ title }) từ một event handler; một phần tử Toast hiện bằng state cũng được.
Xem trước
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} title="Đã lưu thay đổi" description="Dự án của bạn đã cập nhật." />
</Toaster>Cách dùng
Khi nào dùng
- Xác nhận một hành động người dùng vừa làm, mà không chặn họ: Đã lưu thay đổi, Đã sao chép liên kết.
- Đưa một lần hoàn tác nhanh ngay sau một hành động, khi cùng thao tác hoàn tác đó cũng tồn tại ở chỗ khác.
Khi nào không dùng
- Lỗi chặn công việc. Hiện trên trang, cạnh chỗ thất bại, chẳng hạn với Field.
- Câu hỏi hoặc quyết định. Dùng AlertDialog.
- Trạng thái kéo dài, chẳng hạn một build thất bại. Dùng Badge.
Biến thể
variant
default không có icon. success, danger, warning và info thêm icon trạng thái của chúng; surface vẫn trung tính.
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} title="Đã lưu thay đổi" description="Dự án của bạn đã cập nhật." />
</Toaster>
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="success" title="Đã lưu thay đổi" description="Dự án của bạn đã cập nhật." />
</Toaster>
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="danger" title="Đã lưu thay đổi" description="Dự án của bạn đã cập nhật." />
</Toaster>
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="warning" title="Đã lưu thay đổi" description="Dự án của bạn đã cập nhật." />
</Toaster>
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="info" title="Đã lưu thay đổi" description="Dự án của bạn đã cập nhật." />
</Toaster>Ví dụ
Đã lưu
Ở đây hiện bằng state; trong app, gọi toast({ variant: "success", title: "Changes saved" }).
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="success" title="Đã lưu thay đổi" />
</Toaster>Có action
Duration dài hơn, vì người dùng phải tới được button. Action cũng nằm trong panel Lịch sử.
import { useState } from "react"
import { Toast, ToastAction, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} title="Đã lưu trữ dự án" description="Nó bị ẩn khỏi danh sách dự án của bạn." duration={8000} action={<ToastAction altText="Undo from the History panel" onClick={undo}>Hoàn tác</ToastAction>} />
</Toaster>Thất bại
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="danger" title="Tải lên thất bại" description="Tệp lớn hơn 25 MB." />
</Toaster>Thông tin
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="info" title="Đã bắt đầu xuất" description="Tệp được tải xuống khi sẵn sàng." />
</Toaster>Nên và không nên
Nên
- Xác nhận một hành động người dùng vừa làm: Đã lưu thay đổi, Đã sao chép liên kết.
- Viết title ở thì quá khứ, và giữ trong vài từ.
- Mount một Toaster ở root của app, và gọi toast() sau khi hành động xong.
Không nên
- Đừng đặt lỗi chặn công việc trong toast; hiện lỗi trên trang, cạnh chỗ thất bại.
- Đừng dùng cho câu hỏi hoặc quyết định; dùng AlertDialog.
- Đừng đặt cách duy nhất để làm một việc trong action của toast; toast tự đóng.
Props
| Tên | Kiểu | Giá trị | Mặc định | Mô tả |
|---|---|---|---|---|
| variant | enum | default | success | danger | warning | info | default | default không có icon. success, danger, warning và info thêm icon trạng thái của chúng; surface vẫn trung tính. |
| title bắt buộc | node | - | - | Việc đã xảy ra, trong vài từ, thì quá khứ: Đã lưu thay đổi. |
| description | node | - | - | Thêm một câu khi title chưa đủ. |
| duration | number | - | 4000 | Ở lại bao lâu, tính bằng ms. Đặt lâu hơn cho toast có action hoặc description dài. |
| action | node | - | - | Một ToastAction, chẳng hạn Hoàn tác. altText của nó nói còn làm việc đó ở đâu. |
| dismissible | boolean | - | true | Button Dismiss. Giữ nó, để toast không bao giờ che nội dung người dùng cần. |
| open | boolean | - | - | Đặt trên Toast hiện bằng state. Có đang hiện hay không. Đi cùng onOpenChange. |
| onOpenChange | function | - | - | Đặt trên Toast hiện bằng state. Được gọi với false khi hết giờ, hoặc khi Dismiss, Escape hoặc vuốt. |
Slot
| Tên | Bắt buộc | Mô tả |
|---|---|---|
| toaster | có | Một Toaster, mount một lần ở root của app. |
Cấu tạo
| Phần | Mô tả |
|---|---|
| root | Toast: surface nổi có viền, radius-container và shadow-med, px-lg py-md, gap-md giữa các phần. |
| viewport | Toaster: chồng ở góc end, đáy màn hình, rộng tối đa 384px, gap-sm giữa các toast, cách các mép p-lg. |
| icon | Icon trạng thái cho success, danger, warning và info: icon Tabler, 16px, màu chữ của trạng thái, thẳng hàng với title. |
| title | Việc đã xảy ra: chữ primary medium 14px. |
| description | Dòng thứ hai tùy chọn: chữ secondary 14px. |
| action | ToastAction: một Button secondary nhỏ, chẳng hạn Hoàn tác. |
| close | Button Dismiss: icon button 24px với Tabler X, 16px, secondary. |
| hitArea | ::before trong suốt trên button Dismiss, không bao giờ nhỏ hơn size-target-min. |
Khả năng truy cập
Role: status
| Phím | Hành động |
|---|---|
| F8 | Chuyển focus tới các toast, để người dùng bàn phím tới được action hoặc đóng chúng. |
| Tab | Chuyển qua action và button Dismiss của mỗi toast. |
| Escape | Đóng toast đang focus. |
- Mọi toast được thông báo polite, sau phần trình đọc màn hình đang đọc. Toast không bao giờ lấy focus.
- Bộ đếm tạm dừng khi con trỏ ở trên toast hoặc focus nằm trong toast, và khi cửa sổ đang ở nền.
- ToastAction cần altText: cách làm việc đó khi không có toast (Hoàn tác từ panel Lịch sử). Toast có thể đóng trước khi ai tới được, nên action cũng phải tồn tại ở chỗ khác.
- Icon trạng thái chỉ để trang trí; title nói việc đã xảy ra, nên trạng thái không chỉ dựa vào màu.
- Nó chỉ trồi lên khi người dùng cho phép motion, còn không thì fade vào. Nó rời sang phải, cùng hướng vuốt để đóng, và fade ra khi reduced motion. Khi đang vuốt, nó theo ngón tay; thả quá sớm thì nó bật trở lại.
Cài đặt
npx werewolf-ui add toastChạy npx werewolf-ui init một lần trong app trước khi thêm component. Init cài token, thêm CSS import và luật cho agent. Add cài component này cùng các dependency và giữ nguyên theme của bạn. Xem Cài đặt để biết yêu cầu và cách cài qua registry.