iter: b02 新增 toast 消息提示组件(四语义工厂 + 右上角堆叠 + 3s 自动消失)

This commit is contained in:
HIsheR
2026-10-23 15:50:20 +08:00
parent aaf6fdc5ac
commit ece38bcac9
11 changed files with 202 additions and 10 deletions
+1
View File
@@ -9,6 +9,7 @@ export { radioGroup } from './radioGroup.js';
export { card } from './card.js';
export { badge } from './badge.js';
export { alert } from './alert.js';
export { toast, showToast } from './toast.js';
export { tooltip } from './tooltip.js';
export { spinner } from './spinner.js';
export { progress } from './progress.js';
+37
View File
@@ -0,0 +1,37 @@
import { h } from '@ui-arch/frame';
import type { ToastProps } from './types.js';
let host: HTMLElement | null = null; // 全局右上角堆叠容器:首条消息出现时懒创建
let seq = 0; // 自增序号:为每条 toast 生成唯一 id,辅助无障碍定位
/*** 确保堆叠容器存在:fixed 挂在 body 末尾,后续消息依次向上堆叠 ***/
function ensureHost(): HTMLElement {
if (host) return host;
host = h('div', { class: 'ua-toast-host' });
document.body.appendChild(host);
return host;
}
/*** 弹出一条 toast:语义色由 variant 决定,duration 毫秒后自动淡出并移除节点 ***/
export function showToast(props: ToastProps): HTMLElement {
// —— 状态集中声明 ——
const item = h('div', { class: `ua-toast ua-toast-${props.variant ?? 'info'}`, role: 'status', id: `ua-toast-${++seq}` }, props.message);
const duration = props.duration ?? 3000; // 停留时长毫秒
ensureHost().appendChild(item);
requestAnimationFrame(() => item.classList.add('ua-open')); // 下一帧入场,保证过渡生效
window.setTimeout(() => {
item.classList.remove('ua-open'); // 先退场再摘除,退场动画与 reduced-motion 兜底都安全
item.addEventListener('transitionend', () => item.remove(), { once: true });
window.setTimeout(() => item.isConnected && item.remove(), 320); // transition 不触发时的兜底移除
}, duration);
return item;
}
/*** toast 语义快捷工厂:toast.info / success / warning / error(message, duration?) ***/
export const toast = {
info: (message: string, duration?: number): HTMLElement => showToast({ message, duration, variant: 'info' }), // 中性信息
success: (message: string, duration?: number): HTMLElement => showToast({ message, duration, variant: 'success' }), // 成功反馈
warning: (message: string, duration?: number): HTMLElement => showToast({ message, duration, variant: 'warning' }), // 警告
error: (message: string, duration?: number): HTMLElement => showToast({ message, duration, variant: 'danger' }), // 错误
};
+7
View File
@@ -92,6 +92,13 @@ export interface AlertProps {
variant?: 'info' | 'success' | 'warning' | 'danger'; // 语义色;缺省 info
}
/*** toast 消息提示入参 ***/
export interface ToastProps {
message: string; // 提示文案
duration?: number; // 自动消失毫秒;缺省 3000
variant?: 'info' | 'success' | 'warning' | 'danger'; // 语义色;缺省 info
}
/*** 加载指示器入参 ***/
export interface SpinnerProps {
size?: number; // 直径像素;缺省 18