Skip to content

fix(website): close the docs shell's nav-height and column-measure defects - #942

Merged
blove merged 1 commit into
mainfrom
blove/docs-single-pane-polish
Sep 1, 2026
Merged

fix(website): close the docs shell's nav-height and column-measure defects#942
blove merged 1 commit into
mainfrom
blove/docs-single-pane-polish

Conversation

@blove

@blove blove commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Polish pass over the /docs single-pane reading experience, picking up where the footer removal in #932 left off. I audited the shell end to end across 360–1920px before changing anything; three of the things I found are real defects, one is a parity gap, and several suspicions turned out to be fine and are left alone.

--nav-h was wrong by 15px from 768px to 1023px

The nav has three heights, not two. Padding steps at md (768px), but the tall hidden lg:flex link row only appears at lg (1024px), leaving a 66px nav in between:

viewport real nav --nav-h (before) error
360–767 58px 58px 0
768–1023 66px 81px +15px
1024+ 81px 81px 0

Everything that offsets against the nav reads this one variable, so the whole tablet band overshot: dead space above the docs column, and the mobile drawer (top: calc(var(--nav-h) - 1px)) hanging 14px below the nav it is supposed to attach to — measured at 900px wide, nav bottom 66px, drawer top 80px.

This is the nav-height coupling that the migration comment in pages.css deferred to "a later project". It turned out to live in chrome.css, not in the docs shell, and it is site-wide rather than docs-only.

After: the breadcrumb moves from y=105 to y=90 at 900px, and the drawer sits flush.

overflow-x-hidden on the article: removed, not relocated

The fear behind keeping it is already covered — global.css sets body { overflow-x: clip }, with a comment explaining that hidden was rejected there precisely because it creates a scroll container and kills sticky descendants. The article's hidden made that same mistake locally: overflow-x: hidden computes overflow-y: auto, so every docs article was a scroll container (verified: computed overflow-y was auto with the class, visible without).

Before trusting the removal I swept all 123 docs URLs at 375px with the class removed — zero horizontal overflow. Wide code blocks and tables scroll inside their own overflow-x: auto containers, which is where the containment belongs.

The other half of that stale comment is also updated: the paddingTop: 80 hardcode was already replaced with var(--nav-h), and min-h-screen + padding-top don't stack under the global box-sizing: border-box.

One column edge

The breadcrumb/page-header block had no max-width while the article and prev/next rail both sat at max-w-3xl, so PageActions floated ~500px right of the column it belongs to (header right edge 1648 vs prose 1096 at 1920px). It now shares the same measure — header and prev/next right edges both land on 1048.

/docs/choosing-an-adapter gains the TOC rail

It carries as many headings as any library page (7 H2s plus H3s) but had no rail. It stays library-neutral, so it takes no breadcrumb or page header — both are keyed to a library it deliberately has not picked.

Audited and left alone

  • Sticky behaviour is correct. The control plane and TOC both hold at top: --nav-h through a full 7723px scroll; align-self: flex-start intact; the sidebar pane scrolls internally (1335 vs 819).
  • Page endings read deliberate. Articles: 48px gap → prev/next → 47px tail. The index ends flush on a tinted band.
  • The TOC scroll-spy works. It looked dead under instrumentation, but that was the harness — a hidden browser pane suspends requestAnimationFrame, so the rAF-gated update never ran, and window.scrollTo there moves scrollY without emitting a scroll event at all. In a real browser it tracks correctly, and there is now a test proving it.
  • .docs-index-body is a marker class with no CSS; the spec pinning it is untouched.

Tests

e2e/nav-height.spec.ts pins --nav-h to the rendered nav at all six breakpoint edges — jsdom cannot measure layout, so a real browser is the only place these two can be compared. e2e/docs-shell.spec.ts covers the TOC rail (which had no tests at all) and the shared column edge.

The existing horizontal-overflow guard in website.spec.ts was vacuous: it measured documentElement.scrollWidth, which the global body clip pins to the viewport width, so its 24 assertions could never fail — that is the test that supposedly protected the class removed here. It now measures whether content escapes its own column, exempting content inside its own horizontal scroller.

Every new and rewritten guard was mutation-tested against the defect it describes: reverting --nav-h fails 4 tablet-band tests; injecting a 2000px element fails the overflow guard by name; dropping the measure fails the column-edge test.

Verification

  • npx vitest run447 passed / 59 files (unchanged from baseline)
  • npx nx e2e website72 passed (59 pre-existing + 13 new)
  • npx nx lint website0 errors, 27 pre-existing warnings
  • npx nx build website — succeeds, production bundle budgets included

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadplane Ready Ready Preview Sep 1, 2026 11:18pm UTC

Request Review

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

…fects

Polish pass over the /docs single-pane reading experience, following the
footer removal in #932. Three real defects, each measured rather than
inferred, plus the parity gap on the one route that wore no chrome.

--nav-h was wrong by 15px from 768px to 1023px. The nav has three heights,
not two: padding steps at md (768) but the tall `hidden lg:flex` link row
only appears at lg (1024), leaving a 66px nav in between. The variable
jumped straight to 81px at md, so every offset in that band overshot —
dead space above the docs column, and the mobile drawer (top: nav-h - 1px)
hanging 14px below the nav it attaches to. This is the nav-height coupling
the migration comment in pages.css deferred; it lived in chrome.css, not
in the docs shell, and it is site-wide.

The article's `overflow-x-hidden` is removed rather than relocated. It was
redundant — global.css already clips the body — and it was the very
mistake that rule's own comment warns about: `overflow-x: hidden` computes
`overflow-y: auto`, so it made every docs article a scroll container. All
123 docs URLs were swept at 375px with it removed; none overflow.

The breadcrumb/page-header block now shares the article's md:max-w-3xl
measure, which the article and the prev/next rail already used. It had
stretched to the full content width, floating PageActions ~500px right of
its column (1272px against 768px at 1920).

/docs/choosing-an-adapter gains the TOC rail. It carries as many headings
as any library page but had no rail. It stays library-neutral, so it takes
no breadcrumb or page header — both are keyed to a library it deliberately
has not picked.

Tests: e2e/nav-height.spec.ts pins --nav-h to the rendered nav at all six
breakpoint edges (jsdom cannot measure layout, so a real browser is the
only place these can be compared). e2e/docs-shell.spec.ts covers the TOC
rail, which had no tests at all, and the shared column edge.

The existing horizontal-overflow guard in website.spec.ts was vacuous:
it measured documentElement.scrollWidth, which the global body clip pins
to the viewport, so its 24 assertions could never fail. It now measures
whether content escapes its own column, exempting content inside its own
horizontal scroller. Every new and rewritten guard was mutation-tested
against the defect it describes.

Verified: 447 unit tests pass (unchanged), 72 e2e pass (59 pre-existing +
13 new), lint 0 errors, production build succeeds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@blove
blove force-pushed the blove/docs-single-pane-polish branch from dd0fe38 to c1dde39 Compare September 1, 2026 23:15
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove merged commit 5af3d9f into main Sep 1, 2026
29 checks passed
@blove
blove deleted the blove/docs-single-pane-polish branch September 1, 2026 23:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant