Components

提示框

¥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;

Features

    Automatically closes.

    Pauses closing on hover, focus and window blur.

    Supports hotkey to jump to toast viewport.

    Supports closing via swipe gesture.

    Exposes CSS variables for swipe gesture animations.

    Can be controlled or uncontrolled.

安装

¥Installation

从命令行安装组件。

¥Install the component from your command line.

npm install @radix-ui/react-toast

结构

¥Anatomy

导入组件。

¥Import the component.

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 参考

¥API Reference

提供者

¥Provider

封装 Toast 和 Toast 视口的提供程序。它通常封装应用。

¥The provider that wraps your toasts and toast viewport. It usually wraps the application.

PropTypeDefault
duration
number
5000
label*
string
"Notification"
swipeDirection
enum
"right"
swipeThreshold
number
50

视口

¥Viewport

提示框出现的固定区域。用户可以通过按下热键跳转到视口。你需要确保键盘用户能够发现热键。

¥The fixed area where toasts appear. Users can jump to the viewport by pressing a hotkey. It is up to you to ensure the discoverability of the hotkey for keyboard users.

PropTypeDefault
asChild
boolean
false
hotkey
string[]
["F8"]
label
string
"Notifications ({hotkey})"

¥Root

自动关闭的提示框。它不应该保持对 获取用户响应 的打开状态。

¥The toast that automatically closes. It should not be held open to acquire a user response.

PropTypeDefault
asChild
boolean
false
type
enum
"foreground"
duration
number
No default value
defaultOpen
boolean
true
open
boolean
No default value
onOpenChange
function
No default value
onEscapeKeyDown
function
No default value
onPause
function
No default value
onResume
function
No default value
onSwipeStart
function
No default value
onSwipeMove
function
No default value
onSwipeEnd
function
No default value
onSwipeCancel
function
No default value
forceMount
boolean
No default value
Data attributeValues
[data-state]"open" | "closed"
[data-swipe]"start" | "move" | "cancel" | "end"
[data-swipe-direction]"up" | "down" | "left" | "right"
CSS VariableDescription
--radix-toast-swipe-move-xThe offset position of the toast when horizontally swiping
--radix-toast-swipe-move-yThe offset position of the toast when vertically swiping
--radix-toast-swipe-end-xThe offset end position of the toast after horizontally swiping
--radix-toast-swipe-end-yThe offset end position of the toast after vertically swiping

标题

¥Title

用于提示框的可选标题。

¥An optional title for the toast.

PropTypeDefault
asChild
boolean
false

描述

¥Description

提示消息。

¥The toast message.

PropTypeDefault
asChild
boolean
false

操作

¥Action

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

¥An action that is safe to ignore to ensure users are not expected to complete tasks with unexpected side effects as a result of a time limit.

当需要获取用户响应时,将样式为 Toast 的 AlertDialog 传送到视口中。

¥When obtaining a user response is necessary, portal an AlertDialog styled as a toast into the viewport instead.

PropTypeDefault
asChild
boolean
false
altText*
string
No default value

关闭

¥Close

一个按钮,允许用户在提示框持续时间结束前将其关闭。

¥A button that allows users to dismiss the toast before its duration has elapsed.

PropTypeDefault
asChild
boolean
false

示例

¥Examples

自定义热键

¥Custom hotkey

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

¥Override the default hotkey using the event.code value for each key from keycode.info.

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

自定义时长

¥Custom duration

自定义提示框的持续时间以覆盖提供程序的值。

¥Customise the duration of a toast to override the provider value.

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

重复的提示框

¥Duplicate toasts

如果每次用户点击按钮时都必须出现提示框,请使用状态来渲染同一提示框的多个实例(见下文)。或者,你可以抽象各个部分来创建你自己的 命令式 API

¥When a toast must appear every time a user clicks a button, use state to render multiple instances of the same toast (see below). Alternatively, you can abstract the parts to create your own imperative 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>
);
};

滑动手势动画

¥Animating swipe gesture

--radix-toast-swipe-move-[x|y]--radix-toast-swipe-end-[x|y] CSS 变量与 data-swipe="[start|move|cancel|end]" 属性相结合,即可为滑动关闭手势添加动画效果。这是一个示例:

¥Combine --radix-toast-swipe-move-[x|y] and --radix-toast-swipe-end-[x|y] CSS variables with data-swipe="[start|move|cancel|end]" attributes to animate a swipe to close gesture. Here's an example:

// 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%);
}
}

可访问性

¥Accessibility

遵循 aria-live 要求

¥Adheres to the aria-live requirements.

灵敏度

¥Sensitivity

使用 type 属性控制屏幕阅读器提示框的敏感度。

¥Control the sensitivity of the toast for screen readers using the type prop.

对于由用户操作生成的 Toast,请选择 foreground。后台任务生成的 Toast 消息应该使用 background

¥For toasts that are the result of a user action, choose foreground. Toasts generated from background tasks should use background.

前景

¥Foreground

前台 Toast 会立即显示。当出现前台 Toast 消息时,辅助技术可以选择清除之前排队的消息。尽量避免同时堆叠不同的前台 Toast。

¥Foreground toasts are announced immediately. Assistive technologies may choose to clear previously queued messages when a foreground toast appears. Try to avoid stacking distinct foreground toasts at the same time.

背景

¥Background

背景提示会在下一个合适的时机(例如,当屏幕阅读器读完当前句子时)发出。它们不会清除排队消息,因此过度使用它们可能会让屏幕阅读器用户在响应用户交互时感到用户体验迟钝。

¥Background toasts are announced at the next graceful opportunity, for example, when the screen reader has finished reading its current sentence. They do not clear queued messages so overusing them can be perceived as a laggy user experience for screen reader users when used in response to a user interaction.

<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>

其他操作

¥Alternative action

Action 上使用 altText 属性来指示向屏幕阅读器用户发出提示的另一种方式。

¥Use the altText prop on the Action to instruct an alternative way of actioning the toast to screen reader users.

你可以将用户引导到应用中的永久位置,以便他们执行操作或实现你自己的自定义热键逻辑。如果实现后者,请使用 foreground 类型来立即通知,并增加持续时间以给用户充足的时间。

¥You can direct the user to a permanent place in your application where they can action it or implement your own custom hotkey logic. If implementing the latter, use foreground type to announce immediately and increase the duration to give the user ample time.

<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>

关闭图标按钮

¥Close icon button

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

¥When providing an icon (or font icon), remember to label it correctly for screen reader users.

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

键盘交互

¥Keyboard Interactions

KeyDescription
F8
Focuses toasts viewport.
Tab
Moves focus to the next focusable element.
Shift + Tab
Moves focus to the previous focusable element.
Space
When focus is on a Toast.Action or Toast.Close, closes the toast.
Enter
When focus is on a Toast.Action or Toast.Close, closes the toast.
Esc
When focus is on a Toast, closes the toast.

自定义 API

¥Custom APIs

抽象部分

¥Abstract parts

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

¥Create your own API by abstracting the primitive parts into your own component.

用法

¥Usage

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>
);

实现

¥Implementation

// 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

¥Imperative API

如果需要,请创建你自己的命令式 API 以允许使用 toast 重复

¥Create your own imperative API to allow toast duplication if preferred.

用法

¥Usage

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>
);
};

实现

¥Implementation

// 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>
))}
</>
);
});
Previous标签