Skip to content

dogfood: fix iOS sticky-header flicker in the docs app (mobile header) #647

Description

@vivek7405

Problem

The #610 iOS sticky-header flicker fix (use position: fixed, not position: sticky) was applied to the blog, the website, and the scaffold generator, but the docs app still has a sticky header. It is filed separately because the docs site has a two-layout structure that needs a careful cross-layout change (a rushed edit risks regressing the live docs site).

Design / approach

Mirror the other apps: change the mobile header from sticky to fixed, and offset the content by a --header-h variable. The elegant part: a ResizeObserver measuring the header sets --header-h to 0 on desktop (the mobile header is display:none there, so offsetHeight is 0) and to the real height on mobile, so a single body { padding-top: var(--header-h) } auto-handles both breakpoints. Use a media-query default (--header-h: 0, then ~50px under max-width: 860px) so the mobile first paint is correct before JS runs.

Implementation notes (for the implementing agent)

  • The docs site is TWO layouts:
    • Root docs/app/layout.ts: the :root token block (~L65), the body rule (~L149), and the no-FOUC theme <script> (~L56). Add --header-h (media-query default), body { padding-top: var(--header-h) }, and the ResizeObserver snippet here (measure document.querySelector('header')).
    • Sub docs/app/docs/layout.ts: the MOBILE header at ~L195 <header class="hidden max-[860px]:flex sticky top-0 z-[25] ... backdrop-blur ...">. Change sticky top-0 to fixed inset-x-0 top-0 (KEEP hidden max-[860px]:flex). The grid is ~L213, the <main> ~L236 (max-[860px]:pt-6).
  • Landmines: the root layout's script runs for the docs HOMEPAGE too (which may not have the sub-layout's mobile header), so guard the querySelector('header') (no-op if absent). The DESKTOP sticky SIDEBAR (docs-sidebar, sub-layout ~L216) is desktop-only, so iOS phones never see it: OUT OF SCOPE, do not touch it. The flicker is iOS-WebKit-only and invisible to desktop, headless, and DevTools emulation.
  • Reference the shipped pattern: examples/blog/app/layout.ts and website/app/layout.ts (fixed header + --header-h + ResizeObserver), documented in agent-docs/styling.md.
  • Invariants: the docs app is a .ts app (TS allowed; the no-.ts-in-packages rule is for the framework packages, not this app). No backtick inside an html template body (feat(server): replace esbuild TS stripping with Node 24+ strip-types #9).
  • Tests + docs: manual on-device verification is the headline (the flicker is not reproducible headless). No new doc surface (the pattern is already documented).

Acceptance criteria

  • On a real iOS device, the docs mobile header (below 860px) shows no background flicker on a client-router forward nav
  • Desktop (>=860px) is unchanged (the sidebar layout, no top header, --header-h resolves to 0)
  • Mobile first paint reserves the header height (no content hidden under the fixed header before JS runs)
  • No regression to the desktop sticky sidebar or back/forward scroll restoration

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

  • Status
    Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions