代码演示
如何引入
import { Toast } from '@fibrous/semi-ui-solid';
普通提示
通过调用 Toast的相关 method 可以实现弹出提示。推荐设置 stack 属性应用堆叠样式到同屏多个 Toast,Hover 展开,可有效防止一次性弹出多个并列 Toast 对用户造成干扰。
代码
import { throttle } from 'es-toolkit';
import { Button, Toast } from '@fibrous/semi-ui-solid';
const opts = {
content: 'Hi, Bytedance dance dance',
duration: 3,
stack: true,
};
export default function ToastDemo() {
const throttled = throttle(
() =>
Toast.info({
content: 'Hi, Bytedance dance dance',
duration: 10,
onClose: () => throttled.cancel(),
stack: true,
}),
10000,
{ edges: ['leading'] }
);
return (
<div>
<Button onClick={() => Toast.info(opts)}>Display Toast</Button>
<br />
<br />
<Button onClick={throttled}>Throttled Toast</Button>
</div>
);
}其他提示类型
包括成功、失败、警告
代码
import { Button, Toast } from '@fibrous/semi-ui-solid';
const opts = {
content: 'Hi, Bytedance dance dance',
duration: 3,
};
export default function ToastDemo() {
return (
<>
<Button style={{ color: 'var(--semi-color-success)' }} onClick={() => Toast.success('Hi,Bytedance dance dance')}>
Success
</Button>
<br />
<br />
<Button type="warning" onClick={() => Toast.warning(opts)}>
Warning
</Button>
<br />
<br />
<Button type="danger" onClick={() => Toast.error(opts)}>
Error
</Button>
</>
);
}多色样式
可以使用 theme 设置浅色填充样式提高与界面的对比,默认为 'normal' 的白色模式。
代码
import { Button, Toast } from '@fibrous/semi-ui-solid';
const opts = {
content: 'Hi, Bytedance dance dance',
duration: 3,
theme: 'light',
} as const;
export default function ToastDemo() {
return (
<>
<Button onClick={() => Toast.info(opts)}>Info</Button>
<br />
<br />
<Button style={{ color: 'var(--semi-color-success)' }} onClick={() => Toast.success(opts)}>
Success
</Button>
<br />
<br />
<Button type="warning" onClick={() => Toast.warning(opts)}>
Warning
</Button>
<br />
<br />
<Button type="danger" onClick={() => Toast.error(opts)}>
Error
</Button>
</>
);
}堆叠样式
设置 stack 后,同屏 Toast 超过阈值时堆叠展示,Hover 展开。true 的阈值为 3,传数字可自定义阈值;堆叠时只显示最前面的 3 层。
代码
import { Button, Toast } from '@fibrous/semi-ui-solid';
const opts = {
content: 'Hi, Bytedance dance dance',
duration: 10,
stack: true,
};
export default function ToastDemo() {
return <Button onClick={() => Toast.info(opts)}>多次点击</Button>;
}链接文本
配合 Typography 可以自定义链接文本,用来配合更复杂的场景的使用。
代码
import { Button, Toast, Typography } from '@fibrous/semi-ui-solid';
const { Text } = Typography;
// content as a function: the toast creates it when shown, under its own root
const opts = {
content: () => (
<span>
<Text>Hi, Bytedance dance dance</Text>
<Text link style={{ 'margin-left': '12px' }}>
更多
</Text>
</span>
),
duration: 3,
};
const multiLineOpts = {
content: () => (
<>
<div>Hi, Bytedance dance dance</div>
<div style={{ 'margin-top': '8px' }}>
<Text link>查看详情</Text>
<Text link style={{ 'margin-left': '20px' }}>
一会再看
</Text>
</div>
</>
),
duration: 3,
};
export default function ToastDemo() {
return (
<>
<Button onClick={() => Toast.info(opts)}>Display Toast</Button>
<br />
<br />
<Button onClick={() => Toast.info(multiLineOpts)}>Display Multi-line Toast</Button>
</>
);
}修改延时
自定义时长 10s,默认时长为 3s
代码
import { Button, Toast } from '@fibrous/semi-ui-solid';
const opts = {
content: 'Hi, Bytedance dance dance',
duration: 10,
};
export default function ToastDemo() {
return <Button onClick={() => Toast.info(opts)}>Close After 10s</Button>;
}手动关闭
当 duration 设置为 0 时,toast 不会自动关闭,此时必须通过手动关闭。
代码
import { createSignal } from 'solid-js';
import { Button, Toast } from '@fibrous/semi-ui-solid';
export default function ToastDemo() {
const [toastId, setToastId] = createSignal<string | null>(null);
const show = () => {
if (toastId()) {
return;
}
setToastId(Toast.info({ content: 'Not auto close', duration: 0, onClose: () => setToastId(null) }));
};
const hide = () => {
const id = toastId();
if (id) {
Toast.close(id);
}
setToastId(null);
};
return (
<>
<Button type="primary" onClick={show}>
Show Toast
</Button>
<br />
<br />
<Button type="primary" onClick={hide}>
Hide Toast
</Button>
</>
);
}更新消息内容
可以通过唯一的 id 来更新内容。
代码
import { Button, Toast } from '@fibrous/semi-ui-solid';
export default function ToastDemo() {
const show = () => {
const id = 'toastid';
Toast.info({ content: 'Update Content By Id', id });
setTimeout(() => {
Toast.success({ content: 'Id By Content Update', id });
}, 1000);
};
return (
<Button type="primary" onClick={show}>
Update Content By Id
</Button>
);
}销毁所有
全局销毁:
Toast.destroyAll()
消费 Context
通过 Toast.useToast() 创建支持读取 context 的 contextHolder。此时的 toast 会渲染在 contextHolder 所在的节点处,继承该位置的 context、ConfigProvider 和语言;contextHolder 在调用 useToast() 的 owner 下创建,只放置一次。
Toast.useToast() 返回元组 [toast, contextHolder]:toast 对象的 info、success、warning、error、open 接收不含 type、id、zIndex、getPopupContainer 的 Options,返回 toastId;close(toastId) 手动关闭。content、icon 传元素时,元素在事件处理函数中创建,没有 owner,读不到 context;需要读取 context 时传函数,函数在 Toast 渲染处调用。ConfigProvider、LocaleProvider 的值静态 Toast 读不到,需要时改用 useToast()。
代码
import { createContext, useContext } from 'solid-js';
import { Button, Toast } from '@fibrous/semi-ui-solid';
const ReachableContext = createContext<string>();
export default function ToastDemo() {
const [toast, contextHolder] = Toast.useToast();
return (
<ReachableContext.Provider value="Light">
<div>
<Button
onClick={() => {
// A function is called where the toast renders, so it reads the context around contextHolder
toast.success({ duration: 0, content: () => `ReachableContext: ${useContext(ReachableContext)}` });
}}
>
Hook Toast
</Button>
</div>
{contextHolder}
</ReachableContext.Provider>
);
}创建不同配置 Toast
ToastFactory.create(config) => Toast
如果您的应用中需要使用不同 config 的 Toast,可以使用 ToastFactory.create(config)创建新的 Toast:
代码
import { onCleanup } from 'solid-js';
import { Button, Toast, ToastFactory } from '@fibrous/semi-ui-solid';
const ToastInCustomContainer = ToastFactory.create({
getPopupContainer: () => document.getElementById('custom-toast-container') as HTMLElement,
});
export default function ToastDemo() {
onCleanup(() => ToastInCustomContainer.destroyAll());
return (
<div>
<Button onClick={() => Toast.info('Toast')}>Default Toast</Button>
<br />
<br />
<Button onClick={() => ToastInCustomContainer.info('Toast in some container')}>Toast in custom container</Button>
<div id="custom-toast-container">custom container</div>
</div>
);
}API 参考
组件提供的静态方法,使用方式和参数如下:展示:可以直接传入 options 对象或 string:
全局配置, 在调用前提前配置,全局一次生效
Toast.config(config)Toast.resetConfig()将全局配置恢复为默认值,只影响之后弹出的 Toast。ToastFactory.create(config)创建的实例恢复为创建时传入的config
直接展示 Toast
Toast.info(options || string)Toast.error(options || string)Toast.warning(options || string)Toast.success(options || string)
info error warning success 返回值为toastId, 可用于手动关闭
const toastId = Toast.info({ /*...options*/ })
Toast.close(toastId)手动关闭
Options
Toast Options 支持以下 API 及 Config 中的 API
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| content | 提示内容,可传元素或返回元素的函数;函数在 Toast 渲染处调用,用 Toast.useToast() 时可以读取 holder 所在位置的 context | JSX.Element | (() => JSX.Element) | '' |
| icon | 自定义图标,可传元素或返回元素的函数,替换 type 对应的图标;未自带尺寸的 Semi 图标取 large | JSX.Element | (() => JSX.Element) | - |
| showClose | 是否展示关闭按钮 | boolean | true |
| textMaxWidth | 内容的最大宽度,数字单位为 px | number | string | 450 |
| onClose | Toast 关闭的回调函数 | () => void | - |
| stack | 同屏 Toast 超过多少条时堆叠展示,true 为 3,false 不堆叠 | boolean | number | false |
| id | 自定义 ToastId,相同 id 的 Toast 会被更新 | string | - |
| motion | 是否开启进出场动画 | boolean | true |
| class | 类名 | string | - |
| style | 样式 | JSX.CSSProperties | string | - |
class、style 与未声明的选项(如 data-*、aria-*)落在 .semi-toast 上,堆叠模式下同样如此。
Config
以下 API 支持全局配置,用于更改当前 Toast 的默认配置
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| bottom | 弹出位置 bottom | number | string | - |
| left | 弹出位置 left | number | string | - |
| right | 弹出位置 right | number | string | - |
| top | 弹出位置 top | number | string | - |
| zIndex | 弹层 z-index 值 | number | 1010 |
| theme | 填充样式,支持 light, normal | string | normal |
| duration | 自动关闭的延时,单位 s,设为 0 时不自动关闭 | number | 3 |
| getPopupContainer | 指定父级 DOM,弹层将会渲染至该 DOM 中,自定义需要设置 container 和 内部的 .semi-toast-wrapper position: relative, 这会改变浮层 DOM 树位置,但不会改变视图渲染位置。 | () => HTMLElement | () => document.body |
Accessibility
ARIA
- Toast 的 role 按类型区分:
warning、error为alert,info、success与没有type的为status status类 Toast 由列表常驻的aria-live="polite"播报区朗读,Toast 自身为aria-live="off",只播报content的文本;warning、error仍由alert自行播报
键盘和焦点
- 关闭按钮是原生
button,可以用Tab聚焦,Enter或Space触发关闭 - Toast 出现时不会抢走焦点
- 指针或键盘焦点进入 Toast 时暂停自动关闭的计时,并展开堆叠;移出后恢复计时
文案规范
- 保持简洁
- 句尾不使用句号
- 使用 名词 + 动词 的格式进行说明
| ✅ 推荐用法 | ❌ 不推荐用法 |
|---|---|
| Language added | New language has been added successfully |
| Ticket transfer failed | Can't transfer ticket |
- 提供动作的提示消息
- 只提供一个动作
- 不使用类似于「已读」类的动作,例如 OK, Got it, Dismiss, Cancel
| ✅ 推荐用法 | ❌ 不推荐用法 |
|---|---|
Ticket transfer failed Retry | Ticket transfer failed Dismiss |
设计变量
| Sass 变量 | 值 | 用法 |
|---|---|---|
| $animation_duration-toast-show | 300ms | |
| $animation_duration-toast-hide | 300ms | |
| $animation_function-toast-show | cubic-bezier(0.22, 0.57, 0.02, 1.2) | |
| $animation_function-toast-hide | cubic-bezier(0.22, 0.57, 0.02, 1.2) | |
| $animation_delay-toast-show | 0s | |
| $animation_delay-toast-hide | 0s | |
| $animation_opacity-toast-show | 0 | |
| $animation_opacity-toast-hide | 0 | |
| $animation_transform_translateY-toast-show | -100% | |
| $animation_transform_translateY-toast-hide | -100% | |
| $animation_duration-toast-stack | 300ms | |
| $animation_function-toast-stack | cubic-bezier(0.22, 0.57, 0.02, 1.2) | |
| $color-toast-bg-default | var(--semi-color-bg-3) | 提示背景颜色 - 默认 |
| $color-toast-text-default | var(--semi-color-text-0) | 提示文字颜色 - 默认 |
| $color-toast_warning-icon | var(--semi-color-warning) | 警告提示图标颜色 |
| $color-toast_success-icon | var(--semi-color-success) | 成功提示图标颜色 |
| $color-toast_info-icon | var(--semi-color-info) | 通知提示图标颜色 |
| $color-toast_danger-icon | var(--semi-color-danger) | 错误提示图标颜色 |
| $color-toast_warning_light-bg | var(--semi-color-warning-light-default) | 多色样式 警告提示背景颜色 |
| $color-toast_warning_light-icon | $color-toast_warning-icon | 多色样式 警告提示图标颜色 |
| $color-toast_warning_light-border | var(--semi-color-warning) | 多色样式 警告提示描边颜色 |
| $color-toast_success_light-bg | var(--semi-color-success-light-default) | 多色样式 成功提示背景颜色 |
| $color-toast_success_light-icon | $color-toast_success-icon | 多色样式 成功提示图标颜色 |
| $color-toast_success_light-border | var(--semi-color-success) | 多色样式 成功提示描边颜色 |
| $color-toast_info_light-bg | var(--semi-color-info-light-default) | 多色样式 通知提示背景颜色 |
| $color-toast_info_light-icon | $color-toast_info-icon | 多色样式 通知提示图标颜色 |
| $color-toast_info_light-border | var(--semi-color-info) | 多色样式 通知提示描边颜色 |
| $color-toast_danger_light-bg | var(--semi-color-danger-light-default) | 多色样式 错误提示背景颜色 |
| $color-toast_danger_light-icon | $color-toast_danger-icon | 多色样式 错误提示图标颜色 |
| $color-toast_danger_light-border | var(--semi-color-danger) | 多色样式 错误提示描边颜色 |
| $spacing-toast_wrapper-top | 0 | 通知容器顶部位置 |
| $spacing-toast_content-paddingY | $spacing-base-tight | 通知内容垂直内边距 |
| $spacing-toast_content-paddingX | $spacing-tight | 通知内容水平内边距 |
| $spacing-toast_content-paddingTop | $spacing-toast_content-paddingY | 通知内容 top 内边距 |
| $spacing-toast_content-paddingBottom | $spacing-toast_content-paddingY | 通知内容 bottom 内边距 |
| $spacing-toast_content-paddingLeft | $spacing-toast_content-paddingX | 通知内容 left 内边距 |
| $spacing-toast_content-paddingRight | $spacing-toast_content-paddingX | 通知内容 right 内边距 |
| $spacing-toast_content-margin | $spacing-base-tight | 通知内容外边距 |
| $spacing-toast_content_close_btn-marginTop | -2px | 通知关闭按钮顶部外边距 |
| $spacing-toast_content_text-marginLeft | $spacing-base-tight | 通知文本左侧外边距 |
| $spacing-toast_content_text-marginRight | $spacing-base-tight | 通知文本右侧外边距 |
| $spacing-toast-perspective-originY | 280px | 通知透视原点 Y 轴位置 |
| $spacing-toast-perspective | 280px | 通知透视距离 |
| $width-toast_wrapper | 100% | 通知容器整体宽度 |
| $width-toast_light-border | 1px | 多色样式 通知描边宽度 |
| $radius-toast_content | var(--semi-border-radius-medium) | 通知圆角 |
| $font-toast_content-fontWeight | $font-weight-bold | 通知文本字重 |