From 3058da101d87ebfcd5f60883b65ade197fa02605 Mon Sep 17 00:00:00 2001 From: HIsheR Date: Mon, 26 Oct 2026 15:38:50 +0800 Subject: [PATCH] =?UTF-8?q?iter(g143):=20=E9=A1=B5=E7=AD=BE=E6=A0=8F?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8F=B3=E4=BE=A7=E6=93=8D=E4=BD=9C=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ua/backlog.json | 8 ++++++++ .ua/index.json | 10 ++++++++-- apps/demo/main.ts | 6 +++++- llms-full.txt | 4 +++- packages/skin/ui/src/tabs.ts | 4 +++- packages/skin/ui/src/types.ts | 1 + packages/skin/ui/ua.manifest.json | 8 +++++++- packages/skin/ui/ui.css | 20 ++++++++++++++++++++ 8 files changed, 55 insertions(+), 6 deletions(-) diff --git a/.ua/backlog.json b/.ua/backlog.json index b3f0435..a85f946 100644 --- a/.ua/backlog.json +++ b/.ua/backlog.json @@ -1500,6 +1500,14 @@ "acceptance": "space 新增 split:仅在 2 个以上子元素间插入分隔符,分隔符 aria-hidden、弱化色、不可选中;文档与演示同步;npm run check 全绿", "notes": "自补:既有组件可用性细节", "status": "done" + }, + { + "id": "g143", + "title": "页签栏支持右侧操作区 extra", + "motivation": "「新建 / 设置」这类页签级操作只能塞进页签数组或浮在页签栏外,垂直不对齐、分隔线断掉;调用方还得自己包一层 flex", + "acceptance": "tabs 新增 extra:与页签同一行、共用一条分隔线,不传时 DOM 结构不变(纯增量);文档 props/steps 与演示同步;npm run check 全绿", + "notes": "自补:既有组件可用性细节", + "status": "open" } ] } diff --git a/.ua/index.json b/.ua/index.json index 5a3a372..f39ecb6 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T07:37:18.841Z", + "generatedAt": "2026-10-26T07:38:33.907Z", "repoRoot": ".", "packages": [ { @@ -1385,6 +1385,11 @@ "k": 1, "d": "关闭页签回调:组件不自行移除,凭 value 从数据源里摘掉后重绘" }, + { + "n": "extra", + "t": "unknown", + "d": "页签栏右侧操作区内容(按钮 / 链接):与页签同一行、共用一条分隔线;缺省不渲染且页签栏结构不变" + }, { "n": "closable", "t": "boolean", @@ -1397,7 +1402,8 @@ "tabs 只渲染页签头;页签内容用响应式函数按信号切换,如 () => tab() === 'a' ? panelA : panelB", "点击或方向键(←→ 环形)、Home/End(直达首/末页签)切换,滑动指示条自动跟随;disabled: true 的页签置灰不可点", "需要可关闭页签时给该项加 closable: true,× 或聚焦后按 Delete 触发 onClose(value);组件不改数据源,调用方从数组里摘掉该项再重绘", - "键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动,Home/End 跳首个/末个启用页签" + "键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动,Home/End 跳首个/末个启用页签", + "页签栏右侧要放「新建 / 设置」这类操作就传 extra(按钮或链接):它与页签同一行共用一条分隔线,不传时 DOM 结构保持不变" ] }, { diff --git a/apps/demo/main.ts b/apps/demo/main.ts index 5dcab94..1c84405 100644 --- a/apps/demo/main.ts +++ b/apps/demo/main.ts @@ -522,7 +522,11 @@ const content = h( 'sec-tabs-modal', '标签页与弹窗', 'tabs 滑动指示条 + 方向键切换(←→),禁用页签置灰,closable 页签带 ×(聚焦后 Delete 也能关,关闭只回调、由数据源摘除后重绘);modal 支持 Esc / 遮罩 / × 关闭(closeOnOverlay: false 时点遮罩不关、防填一半误触),弹窗内的下拉展开时 Esc 先收下拉、再按才关弹窗(逐层关闭)。', - tabs({ tabs: [{ value: 'a', label: '概览' }, { value: 'b', label: '明细' }, { value: 'c', label: '设置' }, { value: 'd', label: '已停用', disabled: true }], active: activeTab }), + tabs({ + tabs: [{ value: 'a', label: '概览' }, { value: 'b', label: '明细' }, { value: 'c', label: '设置' }, { value: 'd', label: '已停用', disabled: true }], + active: activeTab, + extra: button({ label: '新建页签', variant: 'ghost', onClick: () => toast.info('右侧操作区与页签同一行') }), // extra 放页签栏右侧 + }), h('span', { class: 'out' }, () => `当前页签:${activeTab()}`), renderList(h('div', { class: 'row' }), () => { const items = closableTabs(); diff --git a/llms-full.txt b/llms-full.txt index 9313343..11d4155 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T07:37:18.841Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T07:38:33.907Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -691,6 +691,7 @@ const pct = signal(0); progress({ value: pct }); setInterval(() => pct((pct() + - active:Signal —— 当前激活页签 value 信号,双向绑定 - onChange(回调):(value: string) => void —— 切换回调 - onClose(回调):(value: string) => void —— 关闭页签回调:组件不自行移除,凭 value 从数据源里摘掉后重绘 +- extra:unknown —— 页签栏右侧操作区内容(按钮 / 链接):与页签同一行、共用一条分隔线;缺省不渲染且页签栏结构不变 - closable:boolean —— 页签项上的开关:true 时渲染关闭按钮(×),关闭按钮不进 Tab 序但可用鼠标点;缺省不可关 示例: @@ -706,6 +707,7 @@ const tab = signal('a'); tabs({ tabs: [{ value: 'a', label: '概览', closable: 3. 点击或方向键(←→ 环形)、Home/End(直达首/末页签)切换,滑动指示条自动跟随;disabled: true 的页签置灰不可点 4. 需要可关闭页签时给该项加 closable: true,× 或聚焦后按 Delete 触发 onClose(value);组件不改数据源,调用方从数组里摘掉该项再重绘 5. 键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动,Home/End 跳首个/末个启用页签 +6. 页签栏右侧要放「新建 / 设置」这类操作就传 extra(按钮或链接):它与页签同一行共用一条分隔线,不传时 DOM 结构保持不变 现场演示:apps/docs/demo.html#sec-tabs-modal diff --git a/packages/skin/ui/src/tabs.ts b/packages/skin/ui/src/tabs.ts index 446ac76..63baecc 100644 --- a/packages/skin/ui/src/tabs.ts +++ b/packages/skin/ui/src/tabs.ts @@ -64,7 +64,9 @@ export function tabs(props: TabsProps): HTMLElement { next?.click(); }); - const root = h('div', { class: 'ua-tabs' }, head); + const extra = props.extra ? h('div', { class: 'ua-tabs-extra' }, props.extra) : null; // 右侧操作区:与页签同一行 + const bar = extra ? h('div', { class: 'ua-tabs-bar' }, head, extra) : head; // 有操作区才包一层,无操作区结构不变 + const root = h('div', { class: 'ua-tabs' }, bar); effect(sync); requestAnimationFrame(sync); // 挂载后再量一次布局,否则指示条宽度为 0 trackSize(root, sync); // 容器变宽 / 窗口缩放后重算,指示条不会停在旧宽度 diff --git a/packages/skin/ui/src/types.ts b/packages/skin/ui/src/types.ts index 68bea5e..72c7eff 100644 --- a/packages/skin/ui/src/types.ts +++ b/packages/skin/ui/src/types.ts @@ -347,6 +347,7 @@ export interface TabsProps { active?: Signal; // 当前激活页签的 value 信号,双向绑定 onChange?: (value: string) => void; // 切换回调 onClose?: (value: string) => void; // 关闭页签回调:组件不自行移除,凭 value 从数据源里摘掉 + extra?: unknown; // 页签栏右侧操作区内容(按钮 / 链接);缺省不渲染,页签栏结构不变 } /*** 弹窗入参 ***/ diff --git a/packages/skin/ui/ua.manifest.json b/packages/skin/ui/ua.manifest.json index c96242d..c0dc17c 100644 --- a/packages/skin/ui/ua.manifest.json +++ b/packages/skin/ui/ua.manifest.json @@ -1256,6 +1256,11 @@ "k": 1, "d": "关闭页签回调:组件不自行移除,凭 value 从数据源里摘掉后重绘" }, + { + "n": "extra", + "t": "unknown", + "d": "页签栏右侧操作区内容(按钮 / 链接):与页签同一行、共用一条分隔线;缺省不渲染且页签栏结构不变" + }, { "n": "closable", "t": "boolean", @@ -1268,7 +1273,8 @@ "tabs 只渲染页签头;页签内容用响应式函数按信号切换,如 () => tab() === 'a' ? panelA : panelB", "点击或方向键(←→ 环形)、Home/End(直达首/末页签)切换,滑动指示条自动跟随;disabled: true 的页签置灰不可点", "需要可关闭页签时给该项加 closable: true,× 或聚焦后按 Delete 触发 onClose(value);组件不改数据源,调用方从数组里摘掉该项再重绘", - "键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动,Home/End 跳首个/末个启用页签" + "键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动,Home/End 跳首个/末个启用页签", + "页签栏右侧要放「新建 / 设置」这类操作就传 extra(按钮或链接):它与页签同一行共用一条分隔线,不传时 DOM 结构保持不变" ] }, { diff --git a/packages/skin/ui/ui.css b/packages/skin/ui/ui.css index 31a55ce..50d014e 100644 --- a/packages/skin/ui/ui.css +++ b/packages/skin/ui/ui.css @@ -4419,3 +4419,23 @@ h5.ua-type-title { font-size: var(--ua-font-size-md); } font-size: var(--ua-font-size-sm); user-select: none; } + +/* —— 页签栏右侧操作区:与页签同一行,分隔线由整条 bar 承担 —— */ +.ua-tabs-bar { + display: flex; + align-items: flex-end; + justify-content: space-between; + gap: var(--ua-space-3); + border-bottom: 1px solid var(--ua-color-border); +} +.ua-tabs-bar .ua-tabs-head { + flex: 1 1 auto; + border-bottom: 0; /* 线移到 bar 上,操作区也和页签栏同一条线 */ +} +.ua-tabs-extra { + display: flex; + flex: 0 0 auto; + align-items: center; + gap: var(--ua-space-2); + padding-bottom: var(--ua-space-1); +}