From 1a4b2c1fed9568a371ce321d479575d5527cd267 Mon Sep 17 00:00:00 2001 From: ui-arch-bot Date: Fri, 23 Oct 2026 16:52:28 +0800 Subject: [PATCH] =?UTF-8?q?iter:=20d08=20=E6=BC=94=E7=A4=BA=E9=A1=B5?= =?UTF-8?q?=E4=BE=A7=E8=BE=B9=E7=9B=AE=E5=BD=95=20+=20=E6=BB=9A=E5=8A=A8?= =?UTF-8?q?=E9=AB=98=E4=BA=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ua/backlog.json | 8 ++++++++ .ua/index.json | 2 +- .ua/iterations.log | 1 + apps/demo/build.mjs | 11 ++++++++++- apps/demo/main.ts | 27 ++++++++++++++++++++++++++- llms-full.txt | 2 +- 6 files changed, 47 insertions(+), 4 deletions(-) diff --git a/.ua/backlog.json b/.ua/backlog.json index 2be99cf..65589cb 100644 --- a/.ua/backlog.json +++ b/.ua/backlog.json @@ -112,6 +112,14 @@ "acceptance": "新增 popover.ts:popover(props, trigger) 包裹式,默认点击开合,trigger:'hover' 走延迟出场,点外部 / Esc 收起(Esc 回焦触发器),content 支持任意 DOM 且内部点击不误关,onOpenChange 回调;aria-haspopup/aria-expanded 正确;只消费 --ua-* 令牌 + reduced-motion 兜底;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿", "status": "done", "notes": "触发器 click 内 stopPropagation,避免刚开就被 document 的外部点击关掉;aria-expanded 用 effect 写回(setAttribute 不吃函数值);弹层点击已阻止冒泡;demo 新增 sec-popover(含 checkbox+button 的筛选面板与 hover 触发示例)" + }, + { + "id": "d08", + "title": "演示页加侧边目录与滚动高亮", + "motivation": "演示页已 14 个区块,长页滚动找区块靠手滑;目录同时给文档站 iframe 外的直接访问提供导航", + "acceptance": "demo 页改为 shell 双栏布局(左 sticky 目录 + 右内容),目录项挂载后从 .sec 自动反推(不手写清单),IntersectionObserver 高亮当前区块,窄屏(≤820px)隐藏目录,reduced-motion 下关平滑滚动;npm run check 全绿、demo 可正常构建", + "status": "done", + "notes": "目录由 buildToc 在 mount 后扫描 section.sec 生成(id + h2 文案),新增区块自动入目录无需维护;rootMargin -10%/-80% 让高亮更跟手;.page 去掉 max-width 由 .shell 统一控宽 1160" } ] } diff --git a/.ua/index.json b/.ua/index.json index 04f2aee..f17ec1c 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-23T08:51:47.072Z", + "generatedAt": "2026-10-23T08:52:28.012Z", "repoRoot": ".", "packages": [ { diff --git a/.ua/iterations.log b/.ua/iterations.log index 425294a..b387e17 100644 --- a/.ua/iterations.log +++ b/.ua/iterations.log @@ -12,3 +12,4 @@ {"time": "2026-10-23T16:49:45+08:00", "id": "d05", "result": "done", "summary": "新增面包屑 breadcrumb:nav/ol 语义结构 + 末项 aria-current,href 走 、无 href 走 onNavigate,分隔符可配;manifest/llms/demo 同步,check 全绿(中途被 style 门禁拦下多行注释,已改单行)"} {"time": "2026-10-23T16:50:49+08:00", "id": "d06", "result": "done", "summary": "新增 ua verify 门禁:清单 id/exports/props/steps/example 与 demo 锚点一致性,纳入 npm run check;顺带补齐 badge/alert/spinner 手把手第三条,check 全绿"} {"time": "2026-10-23T16:51:48+08:00", "id": "d07", "result": "done", "summary": "新增可交互气泡卡片 popover:点击/hover 触发、点外部与 Esc 收起、内容可交互且内部点击不误关;manifest/llms/demo 同步,check 全绿"} +{"time": "2026-10-23T16:52:28+08:00", "id": "d08", "result": "done", "summary": "演示页改双栏 shell:sticky 侧边目录由 .sec 自动反推 + IntersectionObserver 滚动高亮,窄屏隐藏、reduced-motion 关平滑滚动;check 全绿"} diff --git a/apps/demo/build.mjs b/apps/demo/build.mjs index 7d93abc..9f07ffe 100644 --- a/apps/demo/build.mjs +++ b/apps/demo/build.mjs @@ -45,7 +45,16 @@ ${css} @media (prefers-color-scheme:dark){:root{--page-bg:#101216;--page-text:#e7e9ec;--page-muted:#888780;--page-border:rgba(255,255,255,.15)}} *{box-sizing:border-box} body{margin:0;background:var(--page-bg);color:var(--page-text);font:14px/1.7 -apple-system,"Segoe UI","Microsoft YaHei",sans-serif} -.page{max-width:880px;margin:0 auto;padding:36px 20px 80px} +.shell{max-width:1160px;margin:0 auto;padding:36px 20px 80px;display:grid;grid-template-columns:190px minmax(0,1fr);gap:36px} +.page{max-width:900px;margin:0;padding:0} +.toc{position:sticky;top:24px;align-self:start;max-height:calc(100vh - 48px);overflow:auto;font-size:13px} +.toc-title{color:var(--page-muted);font-size:11px;letter-spacing:.08em;margin-bottom:8px} +.toc-link{display:block;padding:3px 8px;border-left:2px solid transparent;border-radius:0 4px 4px 0;color:var(--page-muted);text-decoration:none;transition:color .15s,background .15s,border-color .15s} +.toc-link:hover{color:var(--page-text);background:rgba(127,127,127,.08)} +.toc-link.is-active{color:var(--ua-color-accent);border-left-color:var(--ua-color-accent);background:color-mix(in srgb,var(--ua-color-accent) 10%,transparent)} +@media (max-width:820px){.shell{grid-template-columns:1fr;gap:0}.toc{display:none}} +html{scroll-behavior:smooth} +@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}} header{margin-bottom:30px} h1{font-size:20px;font-weight:500;margin:0} .sub{color:var(--page-muted);font-size:13px;margin:8px 0 0} diff --git a/apps/demo/main.ts b/apps/demo/main.ts index 5b167d1..a0f9bca 100644 --- a/apps/demo/main.ts +++ b/apps/demo/main.ts @@ -27,6 +27,27 @@ import { tooltip, } from '@ui-arch/ui'; +/*** 侧边目录:挂载后从 .sec 反推锚点,IntersectionObserver 高亮视口内区块(清单改动自动跟随) ***/ +function buildToc(toc: HTMLElement, content: HTMLElement): void { + const secs = Array.from(content.querySelectorAll('section.sec')); + if (!secs.length) return; // 卫语句:无区块不建目录 + const links = secs.map((sec) => + h('a', { class: 'toc-link', href: `#${sec.id}`, 'data-for': sec.id }, sec.querySelector('h2')?.textContent ?? sec.id), + ); + toc.append(...links); + const io = new IntersectionObserver( + (entries) => { + for (const en of entries) { + if (!en.isIntersecting) continue; // 只处理刚进入视口的区块 + const id = (en.target as HTMLElement).id; + for (const link of links) link.classList.toggle('is-active', link.getAttribute('data-for') === id); + } + }, + { rootMargin: '-10% 0px -80% 0px' }, // 顶部窄条判定,滚动时高亮更跟手 + ); + for (const sec of secs) io.observe(sec); +} + /*** 生成演示区块;id 供文档站 iframe 锚点定位 ***/ function section(id: string, title: string, desc: string, ...body: unknown[]): HTMLElement { return h( @@ -84,7 +105,7 @@ const menuPick = signal(''); // —— 禁用态演示:开关信号同时绑定 switch 的 checked 与 checkbox 的 disabled —— const locked = signal(true); -const app = h( +const content = h( 'div', { class: 'page' }, h( @@ -322,4 +343,8 @@ const app = h( ), ); +const toc = h('aside', { class: 'toc' }, h('div', { class: 'toc-title' }, '目录')); // 目录项由 buildToc 填充 +const app = h('div', { class: 'shell' }, toc, content); + mount('#app', () => app); +buildToc(toc, content); diff --git a/llms-full.txt b/llms-full.txt index b6611c2..150a540 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-23T08:51:47.072Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-23T08:52:28.012Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手