diff --git a/.sync/log/64b9f7dd93863370ada09dc3be31bb05a8a5a4ce.md b/.sync/log/64b9f7dd93863370ada09dc3be31bb05a8a5a4ce.md new file mode 100644 index 000000000..da4140f0d --- /dev/null +++ b/.sync/log/64b9f7dd93863370ada09dc3be31bb05a8a5a4ce.md @@ -0,0 +1,52 @@ +# Port: feat(ContentToc): scroll list independently and center active link (#6697) + +**Upstream:** `64b9f7dd93863370ada09dc3be31bb05a8a5a4ce` (nuxt/ui) +**Decision:** port (adapted to b24ui's TOC layout) + +## Upstream change +On desktop the ContentToc list becomes independently scrollable (the outer +sticky wrapper stops scrolling — `lg:overflow-hidden` — and the inner content +list scrolls with `lg:overflow-y-auto`), and the active link is kept centered: +an `activeIndex` computed is extracted from `indicatorStyle`, and a +`watch(activeIndex)` scrolls the content container (not the page) to center the +active link on change. A scroll shadow (`useScrollShadow`) is applied to the +content. Theme adds `flex flex-col` + `overflow` handling on root, `shrink-0` +on the fixed rows, `min-h-0` on the flexing ones, and `overflow-y-auto` on the +content. `[...slug].vue` additionally enables `highlight`/`circuit`. + +## b24ui port — adapted +b24ui's ContentToc already diverges (no indicator/highlight machinery — those +are `@memo not supported`), and its sticky/`max-h`/`overflow-y-auto` wrapper +styling lives on the docs `class` prop, not the theme `root` (which was empty). +The independent-scroll + centering feature is orthogonal to the indicator, so it +ports cleanly: + +- `src/runtime/components/content/ContentToc.vue` — added `useScrollShadow` + import, `contentRef` + `scrollShadowStyle`, the `activeIndex` computed, and the + centering `watch` (verbatim; b24ui links already carry `data-slot="link"`). + The desktop content `
` gets `ref="contentRef"` + `:style="scrollShadowStyle"`. +- `src/theme/content/content-toc.ts` — `root` → `flex flex-col lg:overflow-hidden` + (b24ui's docs `class` keeps the sticky/`max-h`/mobile `overflow-y-auto`); + `container` +`lg:min-h-0`; `top`/`bottom`/`trigger` +`lg:shrink-0`; `content` + +`lg:min-h-0 lg:overflow-y-auto`. + +### Deviation — scrollbar utility +Upstream hides the list scrollbar with `lg:scrollbar-none`. b24ui has no +`scrollbar-none` utility — its scrollbar helpers (`air-design-tokens/components/ +scrollbar.css`) are `scrollbar-thin` / `scrollbar-transparent`. Used +`lg:scrollbar-thin lg:scrollbar-transparent` (b24ui's idiom, matching the sidebar +and the docs ContentToc wrapper) instead. + +### Not ported +`docs/app/pages/docs/[...slug].vue` — the only hunk adds `highlight` +`highlight-variant="circuit"`, which b24ui explicitly does not support. No change. + +## Tests +No component spec changes upstream. 16 ContentToc snapshots updated — class-only +(root gains `flex flex-col lg:overflow-hidden`; content gains the `lg:` overflow/ +scrollbar classes; rows gain `lg:shrink-0`/`lg:min-h-0`). `scrollShadowStyle` is +`undefined` when not overflowing, so no inline style appears in snapshots. Suite +5309 passed / 6 skipped. + +## Verify (CI=true) +`dev:prepare` · `lint` · `typecheck` · `test` · `build` — all green. diff --git a/.sync/nuxt-ui.json b/.sync/nuxt-ui.json index e59305059..0e480c9e5 100644 --- a/.sync/nuxt-ui.json +++ b/.sync/nuxt-ui.json @@ -2,7 +2,7 @@ "upstream": "nuxt/ui", "branch": "v4", "sync_enabled": false, - "cursor": "1a3a9dc35b6a4e7a3aea57d93532b155de51c0ec", + "cursor": "64b9f7dd93863370ada09dc3be31bb05a8a5a4ce", "_cursor_note": "cursor = last upstream commit ported into b24ui (oldest-first, manual cadence). sync_enabled stays false until Phase 2 (porter workflow #67 + CLAUDE_CODE_OAUTH_TOKEN) is wired and trusted. `processed` is maintained per port from now on (backfilled #68-#72 on 2026-06-09).", "stats": { "queue_depth": 0, @@ -947,10 +947,16 @@ "summary": "fix(inertia): make useRoute().fullPath reactive across navigations (#6696) — inertia useRoute stub returned fullPath: page.url (captured once, stale across navigations). Change to getter get fullPath() { return page.url }. b24ui: src/runtime/vue/stubs/inertia.ts matched, applied verbatim. Direct 1:1. Runtime stub, no snapshot churn. Tests 5289" }, "1a3a9dc35b6a4e7a3aea57d93532b155de51c0ec": { + "pr": 257, + "b24ui_sha": "5f789029ecb613c900b1b33bc6dcac332eab8b71", + "decision": "port", + "summary": "feat(ChatTool): add actions prop for tool approval (#6699) — ChatTool gains actions?: ButtonProps[] rendering a button row below the trigger + actions slot, auto-opens once when actions appear (uncontrolled, respects defaultOpen). Theme: actions slot (inline/card), chevron.leading->'' with group-hover:opacity-0 moved into alone.false.leadingIcon. ai.ts: isToolApprovalPending() + isToolStreaming treats approval-requested as paused (pure string helpers, harmless on v6). Ported component/theme/util/docs/playgrounds/tests. DEFERRED the v7 tool-approval flow (chat.md, chat.vue, chat.post.ts, ChatToolApprovalExample.vue — toolApproval/addToolApprovalResponse). Skipped chat-message.ts body:w-full (b24ui has no naked variant). Tests 5309." + }, + "64b9f7dd93863370ada09dc3be31bb05a8a5a4ce": { "pr": null, "b24ui_sha": "pending-merge", "decision": "port", - "summary": "feat(ChatTool): add actions prop for tool approval (#6699) — ChatTool gains actions?: ButtonProps[] rendering a button row below the trigger + actions slot, auto-opens once when actions appear (uncontrolled, respects defaultOpen). Theme: actions slot (inline/card), chevron.leading->'' with group-hover:opacity-0 moved into alone.false.leadingIcon. ai.ts: isToolApprovalPending() + isToolStreaming treats approval-requested as paused (pure string helpers, harmless on v6). Ported component/theme/util/docs/playgrounds/tests. DEFERRED the v7 tool-approval flow (chat.md, chat.vue, chat.post.ts, ChatToolApprovalExample.vue — toolApproval/addToolApprovalResponse). Skipped chat-message.ts body:w-full (b24ui has no naked variant). Tests 5309." + "summary": "feat(ContentToc): scroll list independently and center active link (#6697) — desktop TOC list scrolls independently (root lg:overflow-hidden + content lg:overflow-y-auto) and active link is centered via activeIndex computed + watch scrolling contentRef; useScrollShadow on content. b24ui adapted: sticky/max-h stays on docs class prop; theme root flex flex-col lg:overflow-hidden, container/top/bottom/trigger get min-h-0/shrink-0, content lg:overflow-y-auto. Deviation: no scrollbar-none in b24ui -> lg:scrollbar-thin lg:scrollbar-transparent. Not ported: [...slug].vue highlight/circuit (b24ui unsupported). 16 snapshots class-only. Tests 5309." } } } diff --git a/src/runtime/components/content/ContentToc.vue b/src/runtime/components/content/ContentToc.vue index bd0486ef5..68df89fe7 100644 --- a/src/runtime/components/content/ContentToc.vue +++ b/src/runtime/components/content/ContentToc.vue @@ -58,13 +58,14 @@ export interface ContentTocSlots {