iter: d23 alert 标题行 + 可关闭 + role=alert

This commit is contained in:
ui-arch-bot
2026-10-23 17:04:28 +08:00
parent f86da9866c
commit f361a1933d
10 changed files with 128 additions and 10 deletions
+8
View File
@@ -232,6 +232,14 @@
"acceptance": "新增 avatar.ts:name 必填(alt / title / 首字来源),src 可选(有则图片、无则首字占位),size 可调,variant 四档语义底色;只消费 --ua-* 令牌;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿", "acceptance": "新增 avatar.ts:name 必填(alt / title / 首字来源),src 可选(有则图片、无则首字占位),size 可调,variant 四档语义底色;只消费 --ua-* 令牌;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿",
"status": "done", "status": "done",
"notes": "首字占位对中文取首字、英文大写,空名兜底 ?;flex:none 保证不被挤压;首次跑 verify 被自身新门禁拦下(声明 sec-avatar 但 demo 缺区块),补独立区块后通过——门禁有效性再次得到验证" "notes": "首字占位对中文取首字、英文大写,空名兜底 ?;flex:none 保证不被挤压;首次跑 verify 被自身新门禁拦下(声明 sec-avatar 但 demo 缺区块),补独立区块后通过——门禁有效性再次得到验证"
},
{
"id": "d23",
"title": "alert 补标题行与可关闭,并补 role=alert",
"motivation": "常驻提示无法消除(错误已处理完仍占版面),且只有单层正文放不下「结论 + 详情」;role=alert 缺失导致读屏不播报",
"acceptance": "AlertProps 新增 title? / closable? / onClose?;关闭时先退场(opacity+上移,200ms)再从 DOM 移除;容器 role=alert;只消费 --ua-* 令牌;demo 新增 sec-alert 展示无标题与可关闭带标题两种;manifest/文档/llms-full.txt 同步;npm run check 全绿",
"status": "done",
"notes": "与 toast 的分工保持:alert 常驻在页面流里、toast 全局浮动;关闭后由调用方自行决定是否重新渲染;body/title/message 三层结构让 flex 布局能把 × 对齐到首行;对现有 alert({message}) 调用完全兼容"
} }
] ]
} }
+22 -3
View File
@@ -1,6 +1,6 @@
{ {
"$schema": "ui-arch-registry-index/0.1", "$schema": "ui-arch-registry-index/0.1",
"generatedAt": "2026-10-23T09:03:43.931Z", "generatedAt": "2026-10-23T09:04:21.317Z",
"repoRoot": ".", "repoRoot": ".",
"packages": [ "packages": [
{ {
@@ -157,7 +157,7 @@
"badge(props):徽标,variant = default | success | warning | danger", "badge(props):徽标,variant = default | success | warning | danger",
"tag(props):可关闭标签,variant 五档语义色,closable + onClose 支持从数据源移除(纯展示请用 badge)", "tag(props):可关闭标签,variant 五档语义色,closable + onClose 支持从数据源移除(纯展示请用 badge)",
"avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色", "avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色",
"alert(props):提示条,variant = info | success | warning | danger", "alert(props):提示条,variant 四档语义色 + 可选 title 与 closable 关闭按钮,role=alert 读屏可播报",
"toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条)", "toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条)",
"tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起", "tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起",
"popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素", "popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素",
@@ -788,18 +788,37 @@
"r": 1, "r": 1,
"d": "提示内容" "d": "提示内容"
}, },
{
"n": "title",
"t": "string",
"d": "加粗标题行;缺省只渲染正文"
},
{ {
"n": "variant", "n": "variant",
"t": "'info' | 'success' | 'warning' | 'danger'", "t": "'info' | 'success' | 'warning' | 'danger'",
"d": "语义色;缺省 info", "d": "语义色;缺省 info",
"df": "info" "df": "info"
},
{
"n": "closable",
"t": "boolean",
"d": "显示 × 关闭按钮,退场后从 DOM 移除;缺省 false",
"df": "false"
},
{
"n": "onClose",
"t": "() => void",
"k": 1,
"d": "关闭回调,供调用方同步业务状态"
} }
], ],
"example": "alert({ message: '操作可能存在风险', variant: 'warning' })", "example": "alert({ message: '操作可能存在风险', variant: 'warning' })",
"steps": [ "steps": [
"按信息级别选 variant:info 提示、success 成功、warning 警告、danger 错误", "按信息级别选 variant:info 提示、success 成功、warning 警告、danger 错误",
"传入 message 即可,入场自带下滑动画", "传入 message 即可,入场自带下滑动画",
"需要可关闭或带操作按钮时,外层用 h() 组合 button 自行拼装,alert 只负责语义底色" "需要可关闭或带操作按钮时,外层用 h() 组合 button 自行拼装,alert 只负责语义底色",
"需要用户可自行消除的提示传 closable: true:点 × 淡出并从 DOM 移除,配合 onClose 同步业务状态",
"有标题与正文两层信息时传 title(加粗首行),正文仍走 message"
] ]
}, },
{ {
+1
View File
@@ -27,3 +27,4 @@
{"time": "2026-10-23T17:02:24+08:00", "id": "d20", "result": "done", "summary": "progress 支持不确定态:value 可选,缺省时 35% 填充块往复 + aria-label 进行中;定量态补 aria-valuenow;demo/manifest/llms 同步,check 全绿"} {"time": "2026-10-23T17:02:24+08:00", "id": "d20", "result": "done", "summary": "progress 支持不确定态:value 可选,缺省时 35% 填充块往复 + aria-label 进行中;定量态补 aria-valuenow;demo/manifest/llms 同步,check 全绿"}
{"time": "2026-10-23T17:03:02+08:00", "id": "d21", "result": "done", "summary": "无障碍收尾:modal × 补 aria-label/type、spinner role=status、skeleton aria-hidden、tablist aria-label + 禁用页签 aria-disabled;conventions 记录基线;check 全绿"} {"time": "2026-10-23T17:03:02+08:00", "id": "d21", "result": "done", "summary": "无障碍收尾:modal × 补 aria-label/type、spinner role=status、skeleton aria-hidden、tablist aria-label + 禁用页签 aria-disabled;conventions 记录基线;check 全绿"}
{"time": "2026-10-23T17:03:49+08:00", "id": "d22", "result": "done", "summary": "新增头像 avatar(src 图片 / 首字占位 + size + 四档语义底色),demo 独立 sec-avatar;中途被 verify 的 demo 锚点检查拦下已补;check 全绿"} {"time": "2026-10-23T17:03:49+08:00", "id": "d22", "result": "done", "summary": "新增头像 avatar(src 图片 / 首字占位 + size + 四档语义底色),demo 独立 sec-avatar;中途被 verify 的 demo 锚点检查拦下已补;check 全绿"}
{"time": "2026-10-23T17:04:27+08:00", "id": "d23", "result": "done", "summary": "alert 新增 title / closable / onClose 与 role=alert,关闭走 200ms 退场后摘除;demo 独立 sec-alert;manifest/llms 同步,check 全绿"}
+7
View File
@@ -246,6 +246,13 @@ const content = h(
progress({ value: percent }), progress({ value: percent }),
h('div', { class: 'row' }, h('span', { class: 'out' }, '不确定态:'), progress()), h('div', { class: 'row' }, h('span', { class: 'out' }, '不确定态:'), progress()),
), ),
section(
'sec-alert',
'提示条',
'alert:四档语义色 + 可选标题与关闭按钮,role=alert 由读屏播报。',
alert({ message: '这是一条中性提示(无标题)', variant: 'info' }),
alert({ title: '保存失败', message: '网络波动,请稍后重试;本次修改已保留在本地草稿。', variant: 'danger', closable: true, onClose: () => toast.warning('提示已关闭') }),
),
section( section(
'sec-tooltip', 'sec-tooltip',
'悬浮提示', '悬浮提示',
+7 -2
View File
@@ -1,6 +1,6 @@
# @ui-arch 组件库 Agent 文档(无图形版) # @ui-arch 组件库 Agent 文档(无图形版)
> 自动生成于 2026-10-23T09:03:43.931Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 自动生成于 2026-10-23T09:04:21.317Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
## 快速上手 ## 快速上手
@@ -413,7 +413,10 @@ avatar({ name: '张三' }); avatar({ name: 'Alice', size: 40, variant: 'success'
参数: 参数:
- message(必填):string —— 提示内容 - message(必填):string —— 提示内容
- title:string —— 加粗标题行;缺省只渲染正文
- variant(默认 info):'info' | 'success' | 'warning' | 'danger' —— 语义色;缺省 info - variant(默认 info):'info' | 'success' | 'warning' | 'danger' —— 语义色;缺省 info
- closable(默认 false):boolean —— 显示 × 关闭按钮,退场后从 DOM 移除;缺省 false
- onClose(回调):() => void —— 关闭回调,供调用方同步业务状态
示例: 示例:
@@ -426,6 +429,8 @@ alert({ message: '操作可能存在风险', variant: 'warning' })
1. 按信息级别选 variant:info 提示、success 成功、warning 警告、danger 错误 1. 按信息级别选 variant:info 提示、success 成功、warning 警告、danger 错误
2. 传入 message 即可,入场自带下滑动画 2. 传入 message 即可,入场自带下滑动画
3. 需要可关闭或带操作按钮时,外层用 h() 组合 button 自行拼装,alert 只负责语义底色 3. 需要可关闭或带操作按钮时,外层用 h() 组合 button 自行拼装,alert 只负责语义底色
4. 需要用户可自行消除的提示传 closable: true:点 × 淡出并从 DOM 移除,配合 onClose 同步业务状态
5. 有标题与正文两层信息时传 title(加粗首行),正文仍走 message
现场演示:apps/docs/demo.html#sec-feedback 现场演示:apps/docs/demo.html#sec-feedback
@@ -762,7 +767,7 @@ API 速览:
- badge(props):徽标,variant = default | success | warning | danger - badge(props):徽标,variant = default | success | warning | danger
- tag(props):可关闭标签,variant 五档语义色,closable + onClose 支持从数据源移除(纯展示请用 badge) - tag(props):可关闭标签,variant 五档语义色,closable + onClose 支持从数据源移除(纯展示请用 badge)
- avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色 - avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色
- alert(props):提示条,variant = info | success | warning | danger - alert(props):提示条,variant 四档语义色 + 可选 title 与 closable 关闭按钮,role=alert 读屏可播报
- toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条) - toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条)
- tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起 - tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起
- popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素 - popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素
+1 -1
View File
@@ -62,7 +62,7 @@
- badge(props):徽标,variant = default | success | warning | danger - badge(props):徽标,variant = default | success | warning | danger
- tag(props):可关闭标签,variant 五档语义色,closable + onClose 支持从数据源移除(纯展示请用 badge) - tag(props):可关闭标签,variant 五档语义色,closable + onClose 支持从数据源移除(纯展示请用 badge)
- avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色 - avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色
- alert(props):提示条,variant = info | success | warning | danger - alert(props):提示条,variant 四档语义色 + 可选 title 与 closable 关闭按钮,role=alert 读屏可播报
- toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条) - toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条)
- tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起 - tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起
- popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素 - popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素
+27 -2
View File
@@ -1,7 +1,32 @@
import { h } from '@ui-arch/frame'; import { h } from '@ui-arch/frame';
import type { AlertProps } from './types.js'; import type { AlertProps } from './types.js';
/*** 提示条:variant 决定语义色,纯展示不持有状态 ***/ /*** 提示条:variant 决定语义色,可选标题与关闭按钮;关闭即退场并从 DOM 移除(内容由调用方持有) ***/
export function alert(props: AlertProps): HTMLElement { export function alert(props: AlertProps): HTMLElement {
return h('div', { class: `ua-alert ua-alert-${props.variant ?? 'info'}` }, props.message); 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 el = h('div', { class: `ua-alert ua-alert-${props.variant ?? 'info'}`, role: 'alert' }, 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;
} }
+3
View File
@@ -189,7 +189,10 @@ export interface TagProps {
/*** 提示条入参 ***/ /*** 提示条入参 ***/
export interface AlertProps { export interface AlertProps {
message: string; // 提示内容 message: string; // 提示内容
title?: string; // 可选的加粗标题行;缺省只渲染正文
variant?: 'info' | 'success' | 'warning' | 'danger'; // 语义色;缺省 info variant?: 'info' | 'success' | 'warning' | 'danger'; // 语义色;缺省 info
closable?: boolean; // 显示 × 关闭按钮(退场后从 DOM 移除);缺省 false
onClose?: () => void; // 关闭回调,供调用方同步业务状态
} }
/*** 骨架屏入参 ***/ /*** 骨架屏入参 ***/
+21 -2
View File
@@ -28,7 +28,7 @@
"badge(props):徽标,variant = default | success | warning | danger", "badge(props):徽标,variant = default | success | warning | danger",
"tag(props):可关闭标签,variant 五档语义色,closable + onClose 支持从数据源移除(纯展示请用 badge)", "tag(props):可关闭标签,variant 五档语义色,closable + onClose 支持从数据源移除(纯展示请用 badge)",
"avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色", "avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色",
"alert(props):提示条,variant = info | success | warning | danger", "alert(props):提示条,variant 四档语义色 + 可选 title 与 closable 关闭按钮,role=alert 读屏可播报",
"toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条)", "toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条)",
"tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起", "tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起",
"popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素", "popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素",
@@ -659,18 +659,37 @@
"r": 1, "r": 1,
"d": "提示内容" "d": "提示内容"
}, },
{
"n": "title",
"t": "string",
"d": "加粗标题行;缺省只渲染正文"
},
{ {
"n": "variant", "n": "variant",
"t": "'info' | 'success' | 'warning' | 'danger'", "t": "'info' | 'success' | 'warning' | 'danger'",
"d": "语义色;缺省 info", "d": "语义色;缺省 info",
"df": "info" "df": "info"
},
{
"n": "closable",
"t": "boolean",
"d": "显示 × 关闭按钮,退场后从 DOM 移除;缺省 false",
"df": "false"
},
{
"n": "onClose",
"t": "() => void",
"k": 1,
"d": "关闭回调,供调用方同步业务状态"
} }
], ],
"example": "alert({ message: '操作可能存在风险', variant: 'warning' })", "example": "alert({ message: '操作可能存在风险', variant: 'warning' })",
"steps": [ "steps": [
"按信息级别选 variant:info 提示、success 成功、warning 警告、danger 错误", "按信息级别选 variant:info 提示、success 成功、warning 警告、danger 错误",
"传入 message 即可,入场自带下滑动画", "传入 message 即可,入场自带下滑动画",
"需要可关闭或带操作按钮时,外层用 h() 组合 button 自行拼装,alert 只负责语义底色" "需要可关闭或带操作按钮时,外层用 h() 组合 button 自行拼装,alert 只负责语义底色",
"需要用户可自行消除的提示传 closable: true:点 × 淡出并从 DOM 移除,配合 onClose 同步业务状态",
"有标题与正文两层信息时传 title(加粗首行),正文仍走 message"
] ]
}, },
{ {
+31
View File
@@ -697,8 +697,12 @@
/* —— 提示条 —— */ /* —— 提示条 —— */
.ua-alert { .ua-alert {
display: flex;
align-items: flex-start;
gap: var(--ua-space-2);
width: 100%; width: 100%;
padding: 8px 12px; padding: 8px 12px;
transition: opacity 0.2s ease, transform 0.2s ease;
border-radius: var(--ua-radius-md); border-radius: var(--ua-radius-md);
border: 1px solid; border: 1px solid;
font-size: var(--ua-font-size-md); font-size: var(--ua-font-size-md);
@@ -710,6 +714,33 @@
transform: translateY(-6px); transform: translateY(-6px);
} }
} }
.ua-alert-body {
flex: 1;
min-width: 0;
}
.ua-alert-title {
margin-bottom: 2px;
font-weight: 600;
}
.ua-alert-close {
flex: none;
padding: 0 2px;
border: none;
background: none;
color: var(--ua-color-text-muted);
font-size: 14px;
line-height: 1.4;
cursor: pointer;
transition: color 0.15s;
}
.ua-alert-close:hover {
color: var(--ua-color-text);
}
/* 关闭退场:淡出 + 轻微上移,配合 200ms 后摘除节点 */
.ua-alert-out {
opacity: 0;
transform: translateY(-4px);
}
.ua-alert-info { .ua-alert-info {
border-color: var(--ua-color-accent); border-color: var(--ua-color-accent);
background: color-mix(in srgb, var(--ua-color-accent) 10%, transparent); background: color-mix(in srgb, var(--ua-color-accent) 10%, transparent);