iter(g212): 页签溢出时自动把激活页签拉回可视区
This commit is contained in:
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "ui-arch-registry-index/0.1",
|
||||
"generatedAt": "2026-10-26T11:20:15.456Z",
|
||||
"generatedAt": "2026-10-26T11:50:16.380Z",
|
||||
"repoRoot": ".",
|
||||
"packages": [
|
||||
{
|
||||
@@ -1472,6 +1472,7 @@
|
||||
"创建信号 tab = signal('a'),初值为默认页签",
|
||||
"tabs 只渲染页签头;页签内容用响应式函数按信号切换,如 () => tab() === 'a' ? panelA : panelB",
|
||||
"点击或方向键(←→ 环形)、Home/End(直达首/末页签)切换,滑动指示条自动跟随;disabled: true 的页签置灰不可点",
|
||||
"页签多到一屏放不下(页签条横向溢出)时,切到被裁掉的页签会自动滚回可视区:只滚页签条本身、不带动页面,系统开启「减弱动效」时直接跳位;已完整可见则不动,不打断用户手动滚动",
|
||||
"需要可关闭页签时给该项加 closable: true,× 或聚焦后按 Delete 触发 onClose(value);组件不改数据源,调用方从数组里摘掉该项再重绘",
|
||||
"键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动,Home/End 跳首个/末个启用页签",
|
||||
"页签栏右侧要放「新建 / 设置」这类操作就传 extra(按钮或链接):它与页签同一行共用一条分隔线,不传时 DOM 结构保持不变"
|
||||
|
||||
@@ -181,6 +181,8 @@ const closableTabs = signal([
|
||||
{ value: 'n3', label: '订单 #1026', closable: true },
|
||||
]);
|
||||
const closableActive = signal('n1');
|
||||
// —— 溢出页签:容器装不下时,切到被裁掉的页签应自动拉回可视区 ——
|
||||
const wideTab = signal('t0');
|
||||
const modalOpen = signal(false);
|
||||
const modalPick = signal('a'); // 弹窗内下拉的取值,用于演示 Esc 逐层关闭
|
||||
|
||||
@@ -583,6 +585,11 @@ const content = h(
|
||||
},
|
||||
})];
|
||||
}),
|
||||
h('div', { style: 'max-width:320px;width:100%' }, tabs({
|
||||
tabs: Array.from({ length: 8 }, (_, i) => ({ value: `t${i}`, label: `选项 ${i + 1}` })), // 八个页签必然溢出,用来验证自动回拉
|
||||
active: wideTab,
|
||||
})),
|
||||
h('span', { class: 'out' }, () => `溢出演示当前页签:${wideTab()}(点最右侧的页签,标题条会自动滚过去)`),
|
||||
button({ label: '打开弹窗', onClick: () => modalOpen(true) }),
|
||||
button({ label: '打开防误关弹窗', variant: 'ghost', onClick: () => stickyOpen(true) }),
|
||||
modal(
|
||||
|
||||
+5
-4
@@ -1,6 +1,6 @@
|
||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||
|
||||
> 自动生成于 2026-10-26T11:20:15.456Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||
> 自动生成于 2026-10-26T11:50:16.380Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||
|
||||
## 快速上手
|
||||
@@ -724,9 +724,10 @@ const tab = signal('a'); tabs({ tabs: [{ value: 'a', label: '概览', closable:
|
||||
1. 创建信号 tab = signal('a'),初值为默认页签
|
||||
2. tabs 只渲染页签头;页签内容用响应式函数按信号切换,如 () => tab() === 'a' ? panelA : panelB
|
||||
3. 点击或方向键(←→ 环形)、Home/End(直达首/末页签)切换,滑动指示条自动跟随;disabled: true 的页签置灰不可点
|
||||
4. 需要可关闭页签时给该项加 closable: true,× 或聚焦后按 Delete 触发 onClose(value);组件不改数据源,调用方从数组里摘掉该项再重绘
|
||||
5. 键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动,Home/End 跳首个/末个启用页签
|
||||
6. 页签栏右侧要放「新建 / 设置」这类操作就传 extra(按钮或链接):它与页签同一行共用一条分隔线,不传时 DOM 结构保持不变
|
||||
4. 页签多到一屏放不下(页签条横向溢出)时,切到被裁掉的页签会自动滚回可视区:只滚页签条本身、不带动页面,系统开启「减弱动效」时直接跳位;已完整可见则不动,不打断用户手动滚动
|
||||
5. 需要可关闭页签时给该项加 closable: true,× 或聚焦后按 Delete 触发 onClose(value);组件不改数据源,调用方从数组里摘掉该项再重绘
|
||||
6. 键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动,Home/End 跳首个/末个启用页签
|
||||
7. 页签栏右侧要放「新建 / 设置」这类操作就传 extra(按钮或链接):它与页签同一行共用一条分隔线,不传时 DOM 结构保持不变
|
||||
|
||||
现场演示:apps/docs/demo.html#sec-tabs-modal
|
||||
|
||||
|
||||
@@ -9,6 +9,20 @@ export function tabs(props: TabsProps): HTMLElement {
|
||||
const indicator = h('span', { class: 'ua-tabs-indicator' });
|
||||
const head = h('div', { class: 'ua-tabs-head', role: 'tablist', 'aria-label': '标签页' }, indicator);
|
||||
|
||||
/*** 把激活页签滚进可视区:页签条溢出时只滚它自己这一层,不动页面与其它祖先容器 ***/
|
||||
const revealActive = (wrap: HTMLElement) => {
|
||||
const pad = 8; // 两侧留白:贴边时激活页签的外框不至于被裁一半
|
||||
const max = head.scrollWidth - head.clientWidth;
|
||||
if (max <= 0) return; // 卫语句:没有溢出(页签条放得下),不需要滚动
|
||||
const left = wrap.offsetLeft;
|
||||
const right = left + wrap.offsetWidth;
|
||||
const viewLeft = head.scrollLeft;
|
||||
if (left >= viewLeft && right <= viewLeft + head.clientWidth) return; // 卫语句:已完整可见,不打断用户的手动滚动
|
||||
const target = left < viewLeft ? left - pad : right - head.clientWidth + pad; // 就近对齐:只补被裁掉的那一段,不做居中
|
||||
const smooth = !window.matchMedia('(prefers-reduced-motion: reduce)').matches; // 尊重减弱动效偏好:直接跳位
|
||||
head.scrollTo({ left: Math.max(0, Math.min(max, target)), behavior: smooth ? 'smooth' : 'auto' });
|
||||
};
|
||||
|
||||
/*** 同步激活态与指示条几何位置:量外壳而非按钮,可关闭页签的指示条才会盖住关闭按钮 ***/
|
||||
const sync = () => {
|
||||
const value = props.active?.();
|
||||
@@ -21,6 +35,7 @@ export function tabs(props: TabsProps): HTMLElement {
|
||||
const wrap = btn.parentElement ?? btn;
|
||||
indicator.style.left = `${wrap.offsetLeft}px`;
|
||||
indicator.style.width = `${wrap.offsetWidth}px`;
|
||||
revealActive(wrap); // 激活项被滚出视口时拉回可见区(页签多到溢出才会真的动)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1343,6 +1343,7 @@
|
||||
"创建信号 tab = signal('a'),初值为默认页签",
|
||||
"tabs 只渲染页签头;页签内容用响应式函数按信号切换,如 () => tab() === 'a' ? panelA : panelB",
|
||||
"点击或方向键(←→ 环形)、Home/End(直达首/末页签)切换,滑动指示条自动跟随;disabled: true 的页签置灰不可点",
|
||||
"页签多到一屏放不下(页签条横向溢出)时,切到被裁掉的页签会自动滚回可视区:只滚页签条本身、不带动页面,系统开启「减弱动效」时直接跳位;已完整可见则不动,不打断用户手动滚动",
|
||||
"需要可关闭页签时给该项加 closable: true,× 或聚焦后按 Delete 触发 onClose(value);组件不改数据源,调用方从数组里摘掉该项再重绘",
|
||||
"键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动,Home/End 跳首个/末个启用页签",
|
||||
"页签栏右侧要放「新建 / 设置」这类操作就传 extra(按钮或链接):它与页签同一行共用一条分隔线,不传时 DOM 结构保持不变"
|
||||
|
||||
Reference in New Issue
Block a user