iter: d11 modal 补 size 档位与 footer 操作区
This commit is contained in:
@@ -136,6 +136,14 @@
|
||||
"acceptance": "ToastProps 新增 closable(显示 × 立即退场);同屏最多 4 条,超出挤掉最早一条;退场逻辑抽为内部 dismiss() 供自动/手动共用;is-closable 才接收指针事件,其余保持 pointer-events:none;manifest/文档/llms-full.txt/demo 同步;npm run check 全绿",
|
||||
"status": "done",
|
||||
"notes": "dismiss() 统一 transitionend + 320ms 双保险;超限用 firstElementChild.remove() 立即腾位(不走动画,保证硬上限);demo sec-toast 增加「可关闭」按钮演示 showToast({closable:true})"
|
||||
},
|
||||
{
|
||||
"id": "d11",
|
||||
"title": "modal 补 size 档位与 footer 操作区",
|
||||
"motivation": "弹窗内容宽窄差异大(确认框 vs 表单),底部操作按钮只能塞进 body 导致分割线语义缺失",
|
||||
"acceptance": "ModalProps 新增 size?: 'sm'|'md'|'lg'(340/420/640)与 footer?: unknown;footer 渲染右对齐操作区带上分割线;缺省行为与旧版一致;manifest/文档/llms-full.txt/demo 同步;npm run check 全绿",
|
||||
"status": "done",
|
||||
"notes": "宽度档位用 .ua-modal-sm/lg 覆盖基准 md,基础宽 min(420px,90vw) 不动;footer 仅在传入时渲染(null 分支不进 DOM);demo 的弹窗改为 size:'lg' + 取消/确定 footer 按钮"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "ui-arch-registry-index/0.1",
|
||||
"generatedAt": "2026-10-23T08:53:43.712Z",
|
||||
"generatedAt": "2026-10-23T08:54:30.235Z",
|
||||
"repoRoot": ".",
|
||||
"packages": [
|
||||
{
|
||||
@@ -164,7 +164,7 @@
|
||||
"spinner(props):加载指示器,size 控制直径",
|
||||
"progress(props):进度条,轨道 + 渐变流动填充,value 信号驱动 0-100,满格切 success 色",
|
||||
"tabs(props):标签页,active 信号双向绑定,滑动指示条 + 方向键环形导航,支持禁用页签",
|
||||
"modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭",
|
||||
"modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭,size 三档宽度,footer 提供底部操作区",
|
||||
"form(props, items):表单容器,布局 + 聚合校验,全部通过才触发 onSubmit",
|
||||
"formItem(props, control):表单字段,label + 必填红星 + 规则校验 + 错误区,返回 { el, validate } 句柄",
|
||||
"dataTable(props):数据表格,粘性表头 / 行选择(全选三态)/ 排序 / 筛选 / 分页 / 空状态;loading 为真时数据行换骨架行且筛选/翻页禁用,内核为 table-core"
|
||||
@@ -1012,6 +1012,17 @@
|
||||
"r": 1,
|
||||
"d": "标题"
|
||||
},
|
||||
{
|
||||
"n": "size",
|
||||
"t": "'sm' | 'md' | 'lg'",
|
||||
"d": "宽度档位:sm 340px / md 420px / lg 640px;缺省 md",
|
||||
"df": "md"
|
||||
},
|
||||
{
|
||||
"n": "footer",
|
||||
"t": "unknown",
|
||||
"d": "底部操作区内容(常见为按钮组,右对齐);缺省不渲染"
|
||||
},
|
||||
{
|
||||
"n": "onClose",
|
||||
"t": "() => void",
|
||||
@@ -1029,7 +1040,8 @@
|
||||
"创建布尔信号 open = signal(false),弹窗初始隐藏",
|
||||
"把 open 传给 modal,其余参数为弹窗内容子节点",
|
||||
"打开:open(true);关闭:open(false),点遮罩或 × 会自动写回 false",
|
||||
"入场自带遮罩淡入 + 弹窗上浮动画"
|
||||
"入场自带遮罩淡入 + 弹窗上浮动画",
|
||||
"底部操作按钮放进 footer(如取消/确定),需要更宽内容用 size: 'lg',窄确认框用 'sm'"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -15,3 +15,4 @@
|
||||
{"time": "2026-10-23T16:52:28+08:00", "id": "d08", "result": "done", "summary": "演示页改双栏 shell:sticky 侧边目录由 .sec 自动反推 + IntersectionObserver 滚动高亮,窄屏隐藏、reduced-motion 关平滑滚动;check 全绿"}
|
||||
{"time": "2026-10-23T16:53:06+08:00", "id": "d09", "result": "done", "summary": "新增滑块 slider:value 信号双向绑定 + min/max/step + 布尔|信号禁用 + showValue,原生 range 承载键盘与触屏,accent-color 令牌化;manifest/llms/demo 同步,check 全绿"}
|
||||
{"time": "2026-10-23T16:53:44+08:00", "id": "d10", "result": "done", "summary": "toast 新增 closable(× 手动关闭)与同屏上限 4 条,退场统一走 dismiss() 双兜底;is-closable 才接收指针;demo/manifest/llms 同步,check 全绿"}
|
||||
{"time": "2026-10-23T16:54:36+08:00", "id": "d11", "result": "done", "summary": "modal 新增 size 三档(sm/md/lg)与 footer 操作区(右对齐 + 上分割线),缺省行为不变;demo/manifest/llms 同步,check 全绿"}
|
||||
|
||||
+14
-3
@@ -241,9 +241,20 @@ const content = h(
|
||||
h('span', { class: 'out' }, () => `当前页签:${activeTab()}`),
|
||||
button({ label: '打开弹窗', onClick: () => modalOpen(true) }),
|
||||
modal(
|
||||
{ title: '确认操作', open: modalOpen, onClose: () => modalOpen(false) },
|
||||
h('p', null, '这是一个由信号驱动的弹窗组件。'),
|
||||
h('div', { class: 'row' }, button({ label: '知道了', onClick: () => modalOpen(false) }), badge({ label: 'modal', variant: 'success' })),
|
||||
{
|
||||
title: '确认操作',
|
||||
open: modalOpen,
|
||||
size: 'lg',
|
||||
onClose: () => modalOpen(false),
|
||||
footer: h(
|
||||
'div',
|
||||
{ class: 'row' },
|
||||
button({ label: '取消', variant: 'ghost', onClick: () => modalOpen(false) }),
|
||||
button({ label: '确定', onClick: () => { modalOpen(false); toast.success('已确认'); } }),
|
||||
),
|
||||
},
|
||||
h('p', null, '这是一个由信号驱动的弹窗组件(size: lg + footer 操作区)。'),
|
||||
h('div', { class: 'row' }, badge({ label: 'modal', variant: 'success' }), badge({ label: 'footer', variant: 'default' })),
|
||||
),
|
||||
),
|
||||
section(
|
||||
|
||||
+5
-2
@@ -1,6 +1,6 @@
|
||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||
|
||||
> 自动生成于 2026-10-23T08:53:43.712Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||
> 自动生成于 2026-10-23T08:54:30.235Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||
|
||||
## 快速上手
|
||||
@@ -569,6 +569,8 @@ const page = signal(1); pagination({ page, pageSize: 3, total: 24, onChange: (p)
|
||||
|
||||
- open(必填):Signal<boolean> —— 开关信号:true 显示 / false 隐藏
|
||||
- title(必填):string —— 标题
|
||||
- size(默认 md):'sm' | 'md' | 'lg' —— 宽度档位:sm 340px / md 420px / lg 640px;缺省 md
|
||||
- footer:unknown —— 底部操作区内容(常见为按钮组,右对齐);缺省不渲染
|
||||
- onClose(回调):() => void —— 关闭回调(点遮罩、× 或 Esc 触发)
|
||||
- ...children:unknown[] —— 弹窗内容子节点
|
||||
|
||||
@@ -584,6 +586,7 @@ const open = signal(false); modal({ title: '确认操作', open, onClose: () =>
|
||||
2. 把 open 传给 modal,其余参数为弹窗内容子节点
|
||||
3. 打开:open(true);关闭:open(false),点遮罩或 × 会自动写回 false
|
||||
4. 入场自带遮罩淡入 + 弹窗上浮动画
|
||||
5. 底部操作按钮放进 footer(如取消/确定),需要更宽内容用 size: 'lg',窄确认框用 'sm'
|
||||
|
||||
现场演示:apps/docs/demo.html#sec-tabs-modal
|
||||
|
||||
@@ -673,7 +676,7 @@ API 速览:
|
||||
- spinner(props):加载指示器,size 控制直径
|
||||
- progress(props):进度条,轨道 + 渐变流动填充,value 信号驱动 0-100,满格切 success 色
|
||||
- tabs(props):标签页,active 信号双向绑定,滑动指示条 + 方向键环形导航,支持禁用页签
|
||||
- modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭
|
||||
- modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭,size 三档宽度,footer 提供底部操作区
|
||||
- form(props, items):表单容器,布局 + 聚合校验,全部通过才触发 onSubmit
|
||||
- formItem(props, control):表单字段,label + 必填红星 + 规则校验 + 错误区,返回 { el, validate } 句柄
|
||||
- dataTable(props):数据表格,粘性表头 / 行选择(全选三态)/ 排序 / 筛选 / 分页 / 空状态;loading 为真时数据行换骨架行且筛选/翻页禁用,内核为 table-core
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
- spinner(props):加载指示器,size 控制直径
|
||||
- progress(props):进度条,轨道 + 渐变流动填充,value 信号驱动 0-100,满格切 success 色
|
||||
- tabs(props):标签页,active 信号双向绑定,滑动指示条 + 方向键环形导航,支持禁用页签
|
||||
- modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭
|
||||
- modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭,size 三档宽度,footer 提供底部操作区
|
||||
- form(props, items):表单容器,布局 + 聚合校验,全部通过才触发 onSubmit
|
||||
- formItem(props, control):表单字段,label + 必填红星 + 规则校验 + 错误区,返回 { el, validate } 句柄
|
||||
- dataTable(props):数据表格,粘性表头 / 行选择(全选三态)/ 排序 / 筛选 / 分页 / 空状态;loading 为真时数据行换骨架行且筛选/翻页禁用,内核为 table-core
|
||||
|
||||
@@ -16,9 +16,10 @@ export function modal(props: ModalProps, ...children: unknown[]): HTMLElement {
|
||||
});
|
||||
const box = h(
|
||||
'div',
|
||||
{ class: 'ua-modal' },
|
||||
{ class: `ua-modal ua-modal-${props.size ?? 'md'}` },
|
||||
h('div', { class: 'ua-modal-head' }, h('h3', { class: 'ua-modal-title' }, props.title), h('button', { class: 'ua-modal-close', onClick: close }, '×')),
|
||||
h('div', { class: 'ua-modal-body' }, ...children),
|
||||
props.footer ? h('div', { class: 'ua-modal-foot' }, props.footer) : null, // 底部操作区:右对齐,仅传了才渲染
|
||||
);
|
||||
overlay.append(box);
|
||||
effect(() => {
|
||||
|
||||
@@ -213,6 +213,8 @@ export interface TabsProps {
|
||||
export interface ModalProps {
|
||||
title: string; // 标题
|
||||
open: Signal<boolean>; // 开关信号:true 显示 / false 隐藏
|
||||
size?: 'sm' | 'md' | 'lg'; // 宽度档位;缺省 md(420px),sm 340px / lg 640px
|
||||
footer?: unknown; // 底部操作区内容(常见为按钮组);缺省不渲染
|
||||
onClose?: () => void; // 关闭回调(点遮罩、× 或 Esc 触发)
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"spinner(props):加载指示器,size 控制直径",
|
||||
"progress(props):进度条,轨道 + 渐变流动填充,value 信号驱动 0-100,满格切 success 色",
|
||||
"tabs(props):标签页,active 信号双向绑定,滑动指示条 + 方向键环形导航,支持禁用页签",
|
||||
"modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭",
|
||||
"modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭,size 三档宽度,footer 提供底部操作区",
|
||||
"form(props, items):表单容器,布局 + 聚合校验,全部通过才触发 onSubmit",
|
||||
"formItem(props, control):表单字段,label + 必填红星 + 规则校验 + 错误区,返回 { el, validate } 句柄",
|
||||
"dataTable(props):数据表格,粘性表头 / 行选择(全选三态)/ 排序 / 筛选 / 分页 / 空状态;loading 为真时数据行换骨架行且筛选/翻页禁用,内核为 table-core"
|
||||
@@ -883,6 +883,17 @@
|
||||
"r": 1,
|
||||
"d": "标题"
|
||||
},
|
||||
{
|
||||
"n": "size",
|
||||
"t": "'sm' | 'md' | 'lg'",
|
||||
"d": "宽度档位:sm 340px / md 420px / lg 640px;缺省 md",
|
||||
"df": "md"
|
||||
},
|
||||
{
|
||||
"n": "footer",
|
||||
"t": "unknown",
|
||||
"d": "底部操作区内容(常见为按钮组,右对齐);缺省不渲染"
|
||||
},
|
||||
{
|
||||
"n": "onClose",
|
||||
"t": "() => void",
|
||||
@@ -900,7 +911,8 @@
|
||||
"创建布尔信号 open = signal(false),弹窗初始隐藏",
|
||||
"把 open 传给 modal,其余参数为弹窗内容子节点",
|
||||
"打开:open(true);关闭:open(false),点遮罩或 × 会自动写回 false",
|
||||
"入场自带遮罩淡入 + 弹窗上浮动画"
|
||||
"入场自带遮罩淡入 + 弹窗上浮动画",
|
||||
"底部操作按钮放进 footer(如取消/确定),需要更宽内容用 size: 'lg',窄确认框用 'sm'"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -984,6 +984,20 @@
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
||||
animation: ua-pop-in 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.2);
|
||||
}
|
||||
/* 宽度档位:md 为基准,sm / lg 覆盖 */
|
||||
.ua-modal-sm {
|
||||
width: min(340px, 90vw);
|
||||
}
|
||||
.ua-modal-lg {
|
||||
width: min(640px, 92vw);
|
||||
}
|
||||
.ua-modal-foot {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: var(--ua-space-2);
|
||||
padding: 12px 16px;
|
||||
border-top: 1px solid var(--ua-color-border);
|
||||
}
|
||||
@keyframes ua-fade {
|
||||
from {
|
||||
opacity: 0;
|
||||
|
||||
Reference in New Issue
Block a user