diff --git a/.ua/backlog.json b/.ua/backlog.json index 2de633e..00b22cc 100644 --- a/.ua/backlog.json +++ b/.ua/backlog.json @@ -1252,6 +1252,14 @@ "acceptance": "BreadcrumbProps 新增 maxItems:超出时渲染「首项 + … + 末 Math.max(2, maxItems-1) 项」,折叠按钮 aria-label 报出被折叠条数、点一下原地展开全部;展开后不再折叠,末项始终是当前页;文档参数表 / 手把手 / 演示(七层路径 maxItems=4)同步;npm run check 全绿", "notes": "自补:可用性;渲染走 effect + replaceChildren,不重建整个 nav", "status": "done" + }, + { + "id": "g112", + "title": "消息提示支持撤销类操作按钮", + "motivation": "「已删除 3 条记录」这种提示最常见的下一步就是撤销,现在只能干看着它 3 秒后消失,要撤销得自己去列表里找回来;toast 只有 closable 一个交互出口", + "acceptance": "ToastProps 新增 actionLabel 与 onAction:传了文案才渲染操作按钮(accent 色、hover 下划线、focus-visible 有环),点后先收起再回调;带操作按钮的 toast 接收指针事件(原来只有 closable 才接收),悬停暂停逻辑不变;文档参数表 / 手把手 / api 说明与演示(「带撤销」按钮,5s)同步;npm run check 全绿", + "notes": "自补:可用性;沿用现有 dismiss,不新增公开 API", + "status": "open" } ] } diff --git a/.ua/index.json b/.ua/index.json index aaa0d08..61ab326 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T06:04:26.861Z", + "generatedAt": "2026-10-26T06:05:26.104Z", "repoRoot": ".", "packages": [ { @@ -1144,6 +1144,17 @@ "t": "'info' | 'success' | 'warning' | 'danger'", "d": "语义色;缺省 info(toast.error 对应 danger)", "df": "info" + }, + { + "n": "actionLabel", + "t": "string", + "d": "操作按钮文案(如「撤销」);传了才渲染,点后 toast 立即收起" + }, + { + "n": "onAction", + "t": "() => void", + "k": 1, + "d": "操作按钮回调,在 toast 收起之后触发(撤销删除之类)" } ], "example": "toast.success('保存成功'); toast.error('网络请求失败', 5000)", @@ -1152,7 +1163,8 @@ "不传 duration 时默认停留 3 秒后自动淡出并移除节点", "多条消息在右上角自动纵向堆叠,互不遮挡", "需要完整入参(含 variant)时用 showToast(props);组件挂载容器由内部懒创建,样式随 ui.css 一起引入", - "同屏最多 4 条,超出自动挤掉最早一条;需要用户主动确认的消息用 showToast({ closable: true }) 给个 ×" + "同屏最多 4 条,超出自动挤掉最早一条;需要用户主动确认的消息用 showToast({ closable: true }) 给个 ×", + "要「撤销」这类操作时给 showToast 传 actionLabel 与 onAction:按钮出现在文案右侧,点完先收起再回调,duration 建议放到 5000 让用户来得及点" ] }, { diff --git a/apps/demo/main.ts b/apps/demo/main.ts index ac97091..3fb46f6 100644 --- a/apps/demo/main.ts +++ b/apps/demo/main.ts @@ -422,6 +422,7 @@ const content = h( button({ label: '警告', onClick: () => toast.warning('磁盘空间不足') }), button({ label: '信息(1.5s)', onClick: () => toast.info('已同步云端', 1500) }), button({ label: '可关闭', variant: 'ghost', onClick: () => showToast({ message: '这条可以手动关掉', variant: 'warning', closable: true }) }), + button({ label: '带撤销', variant: 'ghost', onClick: () => showToast({ message: '已删除 3 条记录', variant: 'success', actionLabel: '撤销', duration: 5000, onAction: () => toast.info('已撤销删除') }) }), ), ), section( diff --git a/llms-full.txt b/llms-full.txt index 1338158..12a9725 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T06:04:26.861Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T06:05:26.104Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -555,6 +555,8 @@ skeleton({ variant: 'text', rows: 3 }); skeleton({ variant: 'circle' }); skeleto - duration(默认 3000):number —— 自动消失毫秒;缺省 3000 - closable(默认 false):boolean —— 显示关闭按钮,点 × 立即收起;缺省 false(仅可关闭的 toast 接收指针事件,其余保持穿透) - variant(默认 info):'info' | 'success' | 'warning' | 'danger' —— 语义色;缺省 info(toast.error 对应 danger) +- actionLabel:string —— 操作按钮文案(如「撤销」);传了才渲染,点后 toast 立即收起 +- onAction(回调):() => void —— 操作按钮回调,在 toast 收起之后触发(撤销删除之类) 示例: @@ -569,6 +571,7 @@ toast.success('保存成功'); toast.error('网络请求失败', 5000) 3. 多条消息在右上角自动纵向堆叠,互不遮挡 4. 需要完整入参(含 variant)时用 showToast(props);组件挂载容器由内部懒创建,样式随 ui.css 一起引入 5. 同屏最多 4 条,超出自动挤掉最早一条;需要用户主动确认的消息用 showToast({ closable: true }) 给个 × +6. 要「撤销」这类操作时给 showToast 传 actionLabel 与 onAction:按钮出现在文案右侧,点完先收起再回调,duration 建议放到 5000 让用户来得及点 现场演示:apps/docs/demo.html#sec-toast diff --git a/packages/skin/ui/src/toast.ts b/packages/skin/ui/src/toast.ts index 509ad96..042d0ed 100644 --- a/packages/skin/ui/src/toast.ts +++ b/packages/skin/ui/src/toast.ts @@ -29,8 +29,11 @@ export function showToast(props: ToastProps): HTMLElement { let startedAt = 0; // 本段计时起点,用于折算剩余 const item = h( 'div', - { class: `ua-toast ua-toast-${props.variant ?? 'info'}${props.closable ? ' is-closable' : ''}`, role: 'status', id: `ua-toast-${++seq}` }, + { class: `ua-toast ua-toast-${props.variant ?? 'info'}${props.closable ? ' is-closable' : ''}${props.actionLabel ? ' is-action' : ''}`, role: 'status', id: `ua-toast-${++seq}` }, h('span', { class: 'ua-toast-msg' }, props.message), + props.actionLabel + ? h('button', { type: 'button', class: 'ua-toast-action', onClick: () => { dismiss(item); props.onAction?.(); } }, props.actionLabel) // 操作按钮(如撤销):点完立即收起再回调 + : null, props.closable ? h('button', { type: 'button', class: 'ua-toast-close', 'aria-label': '关闭提示', onClick: () => dismiss(item) }, '×') : null, ); const stack = ensureHost(); diff --git a/packages/skin/ui/src/types.ts b/packages/skin/ui/src/types.ts index db06957..458bf19 100644 --- a/packages/skin/ui/src/types.ts +++ b/packages/skin/ui/src/types.ts @@ -311,6 +311,8 @@ export interface ToastProps { duration?: number; // 自动消失毫秒;缺省 3000 closable?: boolean; // 是否显示关闭按钮(手动立即收起);缺省 false variant?: 'info' | 'success' | 'warning' | 'danger'; // 语义色;缺省 info + actionLabel?: string; // 操作按钮文案(如「撤销」);传了才渲染,点后立即收起 + onAction?: () => void; // 操作按钮回调(在收起之后触发) } /*** 加载指示器入参 ***/ diff --git a/packages/skin/ui/ua.manifest.json b/packages/skin/ui/ua.manifest.json index 73cf69f..b73b0cd 100644 --- a/packages/skin/ui/ua.manifest.json +++ b/packages/skin/ui/ua.manifest.json @@ -1015,6 +1015,17 @@ "t": "'info' | 'success' | 'warning' | 'danger'", "d": "语义色;缺省 info(toast.error 对应 danger)", "df": "info" + }, + { + "n": "actionLabel", + "t": "string", + "d": "操作按钮文案(如「撤销」);传了才渲染,点后 toast 立即收起" + }, + { + "n": "onAction", + "t": "() => void", + "k": 1, + "d": "操作按钮回调,在 toast 收起之后触发(撤销删除之类)" } ], "example": "toast.success('保存成功'); toast.error('网络请求失败', 5000)", @@ -1023,7 +1034,8 @@ "不传 duration 时默认停留 3 秒后自动淡出并移除节点", "多条消息在右上角自动纵向堆叠,互不遮挡", "需要完整入参(含 variant)时用 showToast(props);组件挂载容器由内部懒创建,样式随 ui.css 一起引入", - "同屏最多 4 条,超出自动挤掉最早一条;需要用户主动确认的消息用 showToast({ closable: true }) 给个 ×" + "同屏最多 4 条,超出自动挤掉最早一条;需要用户主动确认的消息用 showToast({ closable: true }) 给个 ×", + "要「撤销」这类操作时给 showToast 传 actionLabel 与 onAction:按钮出现在文案右侧,点完先收起再回调,duration 建议放到 5000 让用户来得及点" ] }, { diff --git a/packages/skin/ui/ui.css b/packages/skin/ui/ui.css index 0f5476c..e411416 100644 --- a/packages/skin/ui/ui.css +++ b/packages/skin/ui/ui.css @@ -3804,3 +3804,25 @@ button.ua-step-dot:hover { outline: 2px solid var(--ua-color-accent); outline-offset: 1px; } + +/* —— toast 操作按钮(撤销类) —— */ +.ua-toast.is-action { + pointer-events: auto; +} +.ua-toast-action { + padding: 0; + border: none; + background: none; + color: var(--ua-color-accent); + font-size: var(--ua-font-size-md); + font-weight: 500; + cursor: pointer; + transition: color 0.15s; +} +.ua-toast-action:hover { + text-decoration: underline; +} +.ua-toast-action:focus-visible { + outline: 2px solid var(--ua-color-accent); + outline-offset: 2px; +}