iter(g141): 通知支持四角停靠
This commit is contained in:
@@ -1484,6 +1484,14 @@
|
|||||||
"acceptance": "dataTable 新增 onRowClick:传了则该行 tabindex=0 并响应点击 / Enter / 空格,未传时行为与现在完全一致(不进 Tab 序列);文档 props/steps 与演示同步;单文件仍 ≤200 行;npm run check 全绿",
|
"acceptance": "dataTable 新增 onRowClick:传了则该行 tabindex=0 并响应点击 / Enter / 空格,未传时行为与现在完全一致(不进 Tab 序列);文档 props/steps 与演示同步;单文件仍 ≤200 行;npm run check 全绿",
|
||||||
"notes": "自补:既有组件可用性细节(行数恰好压到 200 行上限,靠合并注释行达标)",
|
"notes": "自补:既有组件可用性细节(行数恰好压到 200 行上限,靠合并注释行达标)",
|
||||||
"status": "done"
|
"status": "done"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "g141",
|
||||||
|
"title": "通知支持四角停靠",
|
||||||
|
"motivation": "notification 只能堆在右下角,与抽屉 / 悬浮按钮抢位置;页面里已有 toast 占右上,通知没有别处可去",
|
||||||
|
"acceptance": "notification 新增 placement(四个角),每角独立容器与 3 条上限,顶部角落新通知贴边出现、旧的往下让;文档 props/steps 与演示同步;npm run check 全绿",
|
||||||
|
"notes": "自补:既有组件可用性细节",
|
||||||
|
"status": "open"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "ui-arch-registry-index/0.1",
|
"$schema": "ui-arch-registry-index/0.1",
|
||||||
"generatedAt": "2026-10-26T07:33:59.912Z",
|
"generatedAt": "2026-10-26T07:36:09.637Z",
|
||||||
"repoRoot": ".",
|
"repoRoot": ".",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
@@ -2369,6 +2369,12 @@
|
|||||||
"n": "action",
|
"n": "action",
|
||||||
"t": "unknown",
|
"t": "unknown",
|
||||||
"d": "操作区内容(如按钮);缺省不渲染"
|
"d": "操作区内容(如按钮);缺省不渲染"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"n": "placement",
|
||||||
|
"t": "'top-right' | 'bottom-right' | 'top-left' | 'bottom-left'",
|
||||||
|
"df": "bottom-right",
|
||||||
|
"d": "停靠角落;每个角落独立堆叠(同角最多 3 条),右上与 toast 同侧,建议次要信息放左侧"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"example": "const { close } = notification({ title: '导出完成', description: 'report.csv 已开始下载', variant: 'success', duration: 4000 }); // close() 手动关闭",
|
"example": "const { close } = notification({ title: '导出完成', description: 'report.csv 已开始下载', variant: 'success', duration: 4000 }); // close() 手动关闭",
|
||||||
@@ -2377,7 +2383,8 @@
|
|||||||
"缺省常驻(duration 0),需要自动消失就传毫秒数,如 duration: 4000",
|
"缺省常驻(duration 0),需要自动消失就传毫秒数,如 duration: 4000",
|
||||||
"返回 { el, close } 句柄:程序化关闭用 close(),需要自己挂交互就用 el",
|
"返回 { el, close } 句柄:程序化关闭用 close(),需要自己挂交互就用 el",
|
||||||
"action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色",
|
"action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色",
|
||||||
"与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作"
|
"与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作",
|
||||||
|
"停靠角落用 placement 调:四个角各自独立堆叠与节流,顶部角落新通知从屏幕边缘长出、旧的往下让"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -862,6 +862,7 @@ const content = h(
|
|||||||
button({ label: '成功(4s 自动关)', onClick: () => notification({ title: '导出完成', description: 'report-2026-10.csv 已开始下载', variant: 'success', duration: 4000 }) }),
|
button({ label: '成功(4s 自动关)', onClick: () => notification({ title: '导出完成', description: 'report-2026-10.csv 已开始下载', variant: 'success', duration: 4000 }) }),
|
||||||
button({ label: '警告(常驻)', variant: 'ghost', onClick: () => notification({ title: '连接不稳定', description: '正在重试第 2 次,请检查网络', variant: 'warning' }) }),
|
button({ label: '警告(常驻)', variant: 'ghost', onClick: () => notification({ title: '连接不稳定', description: '正在重试第 2 次,请检查网络', variant: 'warning' }) }),
|
||||||
button({ label: '错误(可关)', variant: 'danger', onClick: () => notification({ title: '保存失败', description: '服务端返回 500,请稍后重试', variant: 'danger' }) }),
|
button({ label: '错误(可关)', variant: 'danger', onClick: () => notification({ title: '保存失败', description: '服务端返回 500,请稍后重试', variant: 'danger' }) }),
|
||||||
|
button({ label: '左上角通知', variant: 'ghost', onClick: () => notification({ title: '后台任务已排队', description: '四个角各自独立堆叠,这条去左上角', placement: 'top-left' }) }),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
section(
|
section(
|
||||||
|
|||||||
+3
-1
@@ -1,6 +1,6 @@
|
|||||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||||
|
|
||||||
> 自动生成于 2026-10-26T07:33:59.912Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
> 自动生成于 2026-10-26T07:36:09.637Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||||
|
|
||||||
## 快速上手
|
## 快速上手
|
||||||
@@ -1234,6 +1234,7 @@ upload({ multiple: true, accept: 'image/*', hint: '拖拽图片到此处', onCha
|
|||||||
- duration:number —— 自动关闭毫秒;缺省 0 = 常驻不自动关,非 0 时悬停 / 聚焦暂停计时
|
- duration:number —— 自动关闭毫秒;缺省 0 = 常驻不自动关,非 0 时悬停 / 聚焦暂停计时
|
||||||
- closable:boolean —— 是否显示关闭按钮;缺省 true
|
- closable:boolean —— 是否显示关闭按钮;缺省 true
|
||||||
- action:unknown —— 操作区内容(如按钮);缺省不渲染
|
- action:unknown —— 操作区内容(如按钮);缺省不渲染
|
||||||
|
- placement(默认 bottom-right):'top-right' | 'bottom-right' | 'top-left' | 'bottom-left' —— 停靠角落;每个角落独立堆叠(同角最多 3 条),右上与 toast 同侧,建议次要信息放左侧
|
||||||
|
|
||||||
示例:
|
示例:
|
||||||
|
|
||||||
@@ -1248,6 +1249,7 @@ const { close } = notification({ title: '导出完成', description: 'report.csv
|
|||||||
3. 返回 { el, close } 句柄:程序化关闭用 close(),需要自己挂交互就用 el
|
3. 返回 { el, close } 句柄:程序化关闭用 close(),需要自己挂交互就用 el
|
||||||
4. action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色
|
4. action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色
|
||||||
5. 与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作
|
5. 与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作
|
||||||
|
6. 停靠角落用 placement 调:四个角各自独立堆叠与节流,顶部角落新通知从屏幕边缘长出、旧的往下让
|
||||||
|
|
||||||
现场演示:apps/docs/demo.html#sec-notification
|
现场演示:apps/docs/demo.html#sec-notification
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import { h } from '@ui-arch/frame';
|
import { h } from '@ui-arch/frame';
|
||||||
import type { NotificationProps } from './types.js';
|
import type { NotificationProps } from './types.js';
|
||||||
|
|
||||||
let host: HTMLElement | null = null; // 右下角堆叠容器:首条通知出现时懒创建
|
const hosts = new Map<string, HTMLElement>(); // 每个角落一个堆叠容器,首次用到该角落时懒创建
|
||||||
const MAX_STACK = 3; // 同屏最多条数,超出挤掉最早一条
|
const MAX_STACK = 3; // 同一角落最多条数,超出挤掉最早一条
|
||||||
|
|
||||||
/*** 确保堆叠容器存在:fixed 挂 body 末尾,与右上角 toast 分区不打架 ***/
|
/*** 确保指定角落的堆叠容器存在:fixed 挂 body 末尾,与 toast 的右上角分区不打架 ***/
|
||||||
function ensureHost(): HTMLElement {
|
function ensureHost(place: string): HTMLElement {
|
||||||
if (host) return host;
|
const hit = hosts.get(place);
|
||||||
host = h('div', { class: 'ua-notice-host' });
|
if (hit) return hit;
|
||||||
document.body.appendChild(host);
|
const el = h('div', { class: `ua-notice-host is-${place}` });
|
||||||
return host;
|
document.body.appendChild(el);
|
||||||
|
hosts.set(place, el);
|
||||||
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** 退场并移除:摘 ua-open 触发过渡,transitionend 与 320ms 超时二选一兜底 ***/
|
/*** 退场并移除:摘 ua-open 触发过渡,transitionend 与 320ms 超时二选一兜底 ***/
|
||||||
@@ -61,7 +63,7 @@ export function notification(props: NotificationProps): { el: HTMLElement; close
|
|||||||
el.addEventListener('focusin', pause); // 键盘聚焦到关闭/操作按钮同样暂停
|
el.addEventListener('focusin', pause); // 键盘聚焦到关闭/操作按钮同样暂停
|
||||||
el.addEventListener('focusout', resume);
|
el.addEventListener('focusout', resume);
|
||||||
|
|
||||||
const stack = ensureHost();
|
const stack = ensureHost(props.placement ?? 'bottom-right'); // 缺省右下,与右上角 toast 错开
|
||||||
if (stack.childElementCount >= MAX_STACK) stack.firstElementChild?.remove(); // 超出上限挤掉最早一条
|
if (stack.childElementCount >= MAX_STACK) stack.firstElementChild?.remove(); // 超出上限挤掉最早一条
|
||||||
stack.appendChild(el);
|
stack.appendChild(el);
|
||||||
requestAnimationFrame(() => el.classList.add('ua-open')); // 下一帧入场,保证过渡生效
|
requestAnimationFrame(() => el.classList.add('ua-open')); // 下一帧入场,保证过渡生效
|
||||||
|
|||||||
@@ -486,6 +486,7 @@ export interface NotificationProps {
|
|||||||
duration?: number; // 自动关闭毫秒;缺省 0 = 常驻(通知通常要读完)
|
duration?: number; // 自动关闭毫秒;缺省 0 = 常驻(通知通常要读完)
|
||||||
closable?: boolean; // 是否显示关闭按钮;缺省 true
|
closable?: boolean; // 是否显示关闭按钮;缺省 true
|
||||||
action?: unknown; // 操作区内容(如按钮);缺省不渲染
|
action?: unknown; // 操作区内容(如按钮);缺省不渲染
|
||||||
|
placement?: 'top-right' | 'bottom-right' | 'top-left' | 'bottom-left'; // 停靠角落;缺省 bottom-right(避开右上角 toast)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** 文件选择入参 ***/
|
/*** 文件选择入参 ***/
|
||||||
|
|||||||
@@ -2240,6 +2240,12 @@
|
|||||||
"n": "action",
|
"n": "action",
|
||||||
"t": "unknown",
|
"t": "unknown",
|
||||||
"d": "操作区内容(如按钮);缺省不渲染"
|
"d": "操作区内容(如按钮);缺省不渲染"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"n": "placement",
|
||||||
|
"t": "'top-right' | 'bottom-right' | 'top-left' | 'bottom-left'",
|
||||||
|
"df": "bottom-right",
|
||||||
|
"d": "停靠角落;每个角落独立堆叠(同角最多 3 条),右上与 toast 同侧,建议次要信息放左侧"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"example": "const { close } = notification({ title: '导出完成', description: 'report.csv 已开始下载', variant: 'success', duration: 4000 }); // close() 手动关闭",
|
"example": "const { close } = notification({ title: '导出完成', description: 'report.csv 已开始下载', variant: 'success', duration: 4000 }); // close() 手动关闭",
|
||||||
@@ -2248,7 +2254,8 @@
|
|||||||
"缺省常驻(duration 0),需要自动消失就传毫秒数,如 duration: 4000",
|
"缺省常驻(duration 0),需要自动消失就传毫秒数,如 duration: 4000",
|
||||||
"返回 { el, close } 句柄:程序化关闭用 close(),需要自己挂交互就用 el",
|
"返回 { el, close } 句柄:程序化关闭用 close(),需要自己挂交互就用 el",
|
||||||
"action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色",
|
"action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色",
|
||||||
"与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作"
|
"与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作",
|
||||||
|
"停靠角落用 placement 调:四个角各自独立堆叠与节流,顶部角落新通知从屏幕边缘长出、旧的往下让"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4399,3 +4399,16 @@ h5.ua-type-title { font-size: var(--ua-font-size-md); }
|
|||||||
outline: 2px solid var(--ua-color-accent);
|
outline: 2px solid var(--ua-color-accent);
|
||||||
outline-offset: -2px; /* 环画在行内,避免被表格滚动容器裁掉 */
|
outline-offset: -2px; /* 环画在行内,避免被表格滚动容器裁掉 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* —— 通知角落:右上与 toast 同侧,左列放次要信息 —— */
|
||||||
|
.ua-notice-host.is-top-right,
|
||||||
|
.ua-notice-host.is-top-left {
|
||||||
|
top: var(--ua-space-4);
|
||||||
|
bottom: auto;
|
||||||
|
flex-direction: column-reverse; /* 新通知贴着屏幕边缘出现,旧的下移 */
|
||||||
|
}
|
||||||
|
.ua-notice-host.is-top-left,
|
||||||
|
.ua-notice-host.is-bottom-left {
|
||||||
|
left: var(--ua-space-4);
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user