42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import { h } from '@ui-arch/frame';
|
||
import type { AlertProps } from './types.js';
|
||
|
||
const DEFAULT_ICON: Record<string, string> = { info: 'ℹ', success: '✓', warning: '!', danger: '✕' }; // 语义缺省图标
|
||
|
||
/*** 提示条:variant 决定语义色,可选标题/语义图标/关闭按钮;banner 为通栏形态,关闭即退场并从 DOM 移除 ***/
|
||
export function alert(props: AlertProps): HTMLElement {
|
||
const variant = props.variant ?? 'info'; // 语义档位
|
||
const body = h(
|
||
'div',
|
||
{ class: 'ua-alert-body' },
|
||
props.title ? h('div', { class: 'ua-alert-title' }, props.title) : null,
|
||
h('div', { class: 'ua-alert-message' }, props.message),
|
||
);
|
||
const glyph = props.icon ?? (props.showIcon ? DEFAULT_ICON[variant] : null); // 自定义图标优先
|
||
const el = h(
|
||
'div',
|
||
{ class: `ua-alert ua-alert-${variant}${props.banner ? ' is-banner' : ''}`, role: 'alert' },
|
||
glyph ? h('span', { class: 'ua-alert-icon', 'aria-hidden': 'true' }, glyph) : null, // 图标纯装饰,读屏靠正文
|
||
body,
|
||
);
|
||
|
||
if (!props.closable) return el; // 纯展示形态
|
||
el.append(
|
||
h(
|
||
'button',
|
||
{
|
||
type: 'button',
|
||
class: 'ua-alert-close',
|
||
'aria-label': '关闭提示',
|
||
onClick: () => {
|
||
el.classList.add('ua-alert-out'); // 先退场
|
||
window.setTimeout(() => el.isConnected && el.remove(), 200); // 过渡结束再摘除
|
||
props.onClose?.();
|
||
},
|
||
},
|
||
'×',
|
||
),
|
||
);
|
||
return el;
|
||
}
|