import { h, signal } from '@ui-arch/frame'; import type { NoticeBarProps } from './types.js'; // 语义色配符号:只靠颜色区分在灰度/色弱下会失效,符号是第二条线索 const ICONS: Record = { info: 'ℹ', success: '✓', warning: '!', danger: '×' }; const EXIT_MS = 200; // 退场时长:与 alert 的关闭过渡同档,两条播报件消失手感一致 /*** 通知条:单行横条,语义色 + 可选跑马灯与关闭;关闭先淡出再隐藏并回调 ***/ export function noticeBar(props: NoticeBarProps): HTMLElement { const variant = props.variant ?? 'info'; const open = signal(true); // 关闭状态:退场结束后置 false(隐藏而非摘节点,调用方仍持有句柄) const close = (): void => { el.classList.add('is-out'); // 挂退场类:淡出 + 轻微上移,先给观感再隐藏 props.onClose?.(); window.setTimeout(() => open(false), EXIT_MS); // 与 CSS 过渡时长同源,避免节点在半路消失 }; const el = h( 'div', { class: `ua-notice ua-notice-${variant}${props.scroll ? ' is-roll' : ''}`, role: 'status', title: props.text, // 滚动/裁切时仍能悬停读到完整原文 hidden: () => !open(), }, h('span', { class: 'ua-notice-icon', 'aria-hidden': 'true' }, props.icon ?? ICONS[variant]), h('div', { class: 'ua-notice-body' }, h('span', { class: 'ua-notice-text' }, props.text)), props.closable === false ? null : h('button', { type: 'button', class: 'ua-notice-close', 'aria-label': '关闭通知', onClick: close }, '×'), ); return el; }