组件

Toast

一个简洁的消息,会临时显示。

import * as React from "react";
import { Toast } from "radix-ui";
import "./styles.css";
const ToastDemo = () => {
const [open, setOpen] = React.useState(false);
const eventDateRef = React.useRef(new Date());
const timerRef = React.useRef(0);
React.useEffect(() => {
return () => clearTimeout(timerRef.current);
}, []);
return (
<Toast.Provider swipeDirection="right">
<button className="Button large violet" onClick={() => { setOpen(false); window.clearTimeout(timerRef.current); timerRef.current = window.setTimeout(() => { eventDateRef.current = oneWeekAway(); setOpen(true); }, 100); }} >
Add to calendar
</button>
<Toast.Root className="ToastRoot" open={open} onOpenChange={setOpen}>
<Toast.Title className="ToastTitle">Scheduled: Catch up</Toast.Title>
<Toast.Description asChild>
<time className="ToastDescription" dateTime={eventDateRef.current.toISOString()} >
{prettyDate(eventDateRef.current)}
</time>
</Toast.Description>
<Toast.Action className="ToastAction" asChild altText="Goto schedule to undo" >
<button className="Button small green">Undo</button>
</Toast.Action>
</Toast.Root>
<Toast.Viewport className="ToastViewport" />
</Toast.Provider>
);
};
function oneWeekAway(date) {
const now = new Date();
const inOneWeek = now.setDate(now.getDate() + 7);
return new Date(inOneWeek);
}
function prettyDate(date) {
return new Intl.DateTimeFormat("en-US", {
dateStyle: "full",
timeStyle: "short",
}).format(date);
}
export default ToastDemo;

特性

    自动关闭。

    悬停、聚焦和窗口失焦时暂停关闭。

    支持热键跳转到 toast 视口。

    支持通过滑动操作关闭。

    公开 CSS 变量用于滑动操作动画。

    可以受控或不受控。

安装

从命令行安装组件。

npm install @radix-ui/react-toast

解剖

导入组件。

import { Toast } from "radix-ui";
export default () => (
<Toast.Provider>
<Toast.Root>
<Toast.Title />
<Toast.Description />
<Toast.Action />
<Toast.Close />
</Toast.Root>
<Toast.Viewport />
</Toast.Provider>
);

API 参考

Provider

用于包裹您的 toast 和 toast 视口的提供器。它通常包裹应用程序。

属性类型默认值
duration
number
5000
label*
string
"Notification"
swipeDirection
enum
"right"
swipeThreshold
number
50

Viewport

Toast 显示的固定区域。用户可以通过按热键跳转到视口。您有责任确保键盘用户可以发现热键。

属性类型默认值
asChild
boolean
false
hotkey
string[]
["F8"]
label
string
"Notifications ({hotkey})"

Root

自动关闭的 toast。不应保持打开状态以获取用户响应

属性类型默认值
asChild
boolean
false
type
enum
"foreground"
duration
number
无默认值
defaultOpen
boolean
true
open
boolean
无默认值
onOpenChange
function
无默认值
onEscapeKeyDown
function
无默认值
onPause
function
无默认值
onResume
function
无默认值
onSwipeStart
function
无默认值
onSwipeMove
function
无默认值
onSwipeEnd
function
无默认值
onSwipeCancel
function
无默认值
forceMount
boolean
无默认值
数据属性
[data-state]"open" |"closed"
[data-swipe]"start" |"move" |"cancel" |"end"
[data-swipe-direction]"up" |"down" |"left" |"right"
CSS 变量描述
--radix-toast-swipe-move-x水平滑动时 toast 的偏移位置
--radix-toast-swipe-move-y垂直滑动时 toast 的偏移位置
--radix-toast-swipe-end-x水平滑动后 toast 的偏移结束位置
--radix-toast-swipe-end-y垂直滑动后 toast 的偏移结束位置

标题

toast 的可选标题。

属性类型默认值
asChild
boolean
false

描述

Toast 消息。

属性类型默认值
asChild
boolean
false

操作

可以安全忽略的操作,以确保用户不会因为时间限制而预期完成具有意外副作用的任务。

当需要获得用户响应时,将样式设置为 toast 的AlertDialog通过 portal 放入视口中。

属性类型默认值
asChild
boolean
false
altText*
string
无默认值

关闭

允许用户在 toast 持续时间结束前将其关闭的按钮。

属性类型默认值
asChild
boolean
false

示例

自定义热键

使用 keycode.info 中每个键的 event.code 值覆盖默认热键。

<Toast.Provider>
{/* ... */}
<Toast.Viewport hotkey={["altKey", "KeyT"]} />
</Toast.Provider>

自定义持续时间

自定义 toast 的持续时间以覆盖提供器值。

<Toast.Root duration={3000}>
<Toast.Description>Saved!</Toast.Description>
</Toast.Root>

重复的 toast

当每次用户点击按钮时都必须显示 toast 时,使用 state 渲染相同 toast 的多个实例(见下文)。或者,您可以抽象出各个部分以创建您自己的命令式 API

export default () => {
const [savedCount, setSavedCount] = React.useState(0);
return (
<div>
<form onSubmit={() => setSavedCount((count) => count + 1)}>
{/* ... */}
<button>save</button>
</form>
{Array.from({ length: savedCount }).map((_, index) => (
<Toast.Root key={index}>
<Toast.Description>Saved!</Toast.Description>
</Toast.Root>
))}
</div>
);
};

动画滑动操作

--radix-toast-swipe-move-[x|y]--radix-toast-swipe-end-[x|y] CSS 变量与 data-swipe="[start|move|cancel|end]" 属性结合使用,以动画化滑动关闭操作。这是一个示例

// index.jsx
import { Toast } from "radix-ui";
import "./styles.css";
export default () => (
<Toast.Provider swipeDirection="right">
<Toast.Root className="ToastRoot">...</Toast.Root>
<Toast.Viewport />
</Toast.Provider>
);
/* styles.css */
.ToastRoot[data-swipe="move"] {
transform: translateX(var(--radix-toast-swipe-move-x));
}
.ToastRoot[data-swipe="cancel"] {
transform: translateX(0);
transition: transform 200ms ease-out;
}
.ToastRoot[data-swipe="end"] {
animation: slideRight 100ms ease-out;
}
@keyframes slideRight {
from {
transform: translateX(var(--radix-toast-swipe-end-x));
}
to {
transform: translateX(100%);
}
}

可访问性

遵循 aria-live 要求

灵敏度

使用 type 属性控制 toast 对屏幕阅读器的灵敏度。

对于用户操作产生的 toast,请选择 foreground。从后台任务生成的 Toast 应使用 background

Foreground

Foreground toast 会立即宣布。当出现 foreground toast 时,辅助技术可能会选择清除之前排队的消息。尽量避免同时堆叠不同的 foreground toast。

Background

Background toast 会在下一个合适的时机宣布,例如,当屏幕阅读器完成读取当前句子时。它们不会清除排队的消息,因此在响应用户交互时过度使用它们可能会被屏幕阅读器用户感知为用户体验滞后。

<Toast.Root type="foreground">
<Toast.Description>File removed successfully.</Toast.Description>
<Toast.Close>Dismiss</Toast.Close>
</Toast.Root>
<Toast.Root type="background">
<Toast.Description>We've just released Radix 1.0.</Toast.Description>
<Toast.Close>Dismiss</Toast.Close>
</Toast.Root>

替代操作

Action 上使用 altText 属性,以指示屏幕阅读器用户操作 toast 的替代方法。

您可以引导用户到应用程序中的永久位置,在那里他们可以操作它,或者实现您自己的自定义热键逻辑。如果实现后者,请使用 foreground 类型立即宣布并增加持续时间,以便给用户充足的时间。

<Toast.Root type="background">
<Toast.Title>Upgrade Available!</Toast.Title>
<Toast.Description>We've just released Radix 1.0.</Toast.Description>
<Toast.Action altText="Goto account settings to upgrade">
Upgrade
</Toast.Action>
<Toast.Close>Dismiss</Toast.Close>
</Toast.Root>
<Toast.Root type="foreground" duration={10000}>
<Toast.Description>File removed successfully.</Toast.Description>
<Toast.Action altText="Undo (Alt+U)">
Undo <kbd>Alt</kbd>+<kbd>U</kbd>
</Toast.Action>
<Toast.Close>Dismiss</Toast.Close>
</Toast.Root>

关闭图标按钮

当提供图标(或字体图标)时,请记住为屏幕阅读器用户正确标记它。

<Toast.Root type="foreground">
<Toast.Description>Saved!</Toast.Description>
<Toast.Close aria-label="Close">
<span aria-hidden>×</span>
</Toast.Close>
</Toast.Root>

键盘交互

描述
F8
聚焦 toasts 视口。
Tab
将焦点移动到下一个可聚焦元素。
Shift + Tab
将焦点移动到上一个可聚焦元素。
Space
当焦点位于 Toast.Action Toast.Close 时,关闭 toast。
Enter
当焦点位于 Toast.Action Toast.Close 时,关闭 toast。
Esc
当焦点位于 Toast 时,关闭 toast。

自定义 API

抽象部分

通过将原始部分抽象到您自己的组件中来创建您自己的 API。

用法

import { Toast } from "./your-toast";
export default () => (
<Toast title="Upgrade available" content="We've just released Radix 3.0!">
<button onClick={handleUpgrade}>Upgrade</button>
</Toast>
);

实现

// your-toast.jsx
import { Toast as ToastPrimitive } from "radix-ui";
export const Toast = ({ title, content, children, ...props }) => {
return (
<ToastPrimitive.Root {...props}>
{title && <ToastPrimitive.Title>{title}</ToastPrimitive.Title>}
<ToastPrimitive.Description>{content}</ToastPrimitive.Description>
{children && (
<ToastPrimitive.Action asChild>{children}</ToastPrimitive.Action>
)}
<ToastPrimitive.Close aria-label="Close">
<span aria-hidden>×</span>
</ToastPrimitive.Close>
</ToastPrimitive.Root>
);
};

命令式 API

创建您自己的命令式 API,以允许在需要时重复 toast

用法

import { Toast } from "./your-toast";
export default () => {
const savedRef = React.useRef();
return (
<div>
<form onSubmit={() => savedRef.current.publish()}>
{/* ... */}
<button>Save</button>
</form>
<Toast ref={savedRef}>Saved successfully!</Toast>
</div>
);
};

实现

// your-toast.jsx
import * as React from "react";
import { Toast as ToastPrimitive } from "radix-ui";
export const Toast = React.forwardRef((props, forwardedRef) => {
const { children, ...toastProps } = props;
const [count, setCount] = React.useState(0);
React.useImperativeHandle(forwardedRef, () => ({
publish: () => setCount((count) => count + 1),
}));
return (
<>
{Array.from({ length: count }).map((_, index) => (
<ToastPrimitive.Root key={index} {...toastProps}>
<ToastPrimitive.Description>{children}</ToastPrimitive.Description>
<ToastPrimitive.Close>Dismiss</ToastPrimitive.Close>
</ToastPrimitive.Root>
))}
</>
);
});
上一个Tabs
下一个Toggle