Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR Analysis Report
The exact-head preview is not available yet. Generated by PR Enrichment workflow | View current CI run |
|
Thanks for finishing the desktop half of #5392. The separate rails, rail-relative Before merging, could you please make three changes?
After the rebase, please rerun CI and verify the preview. The current Vercel and visual failures appear to be preview/infrastructure issues rather than evidence of a problem with the sticky-rail approach. |
Contain the desktop-pinned hero layers so the app-global `overscroll-behavior-y: none` can be deleted outright instead of gated to desktop widths: macOS trackpads get their native rubber-band back. A `fixed` layer is not part of the document, so when the document rubber-bands past its own edge the layer sits in the exposed gap. A `sticky` layer lifts with the document and cannot paint past its containing block. Each pinned layer (aurora backdrop, overlap cards, hero text) now rides its own `absolute; inset: 0` rail, a direct child of heroScope spanning hero band + showcase and placed ahead of the showcase overlay, as a `position: sticky` box at >=1024px. Centering moves from `left: 50%` + `translateX(-50%)` to auto margins inside the full-width rail, and the 1200px box is capped to the rail's width rather than 100vw: with a classic scrollbar 100vw is wider than the rail, which zeroes the auto margins and shoves the box left. A rail inside the 760px band alone would release the layer after ~48px, which is why the rails span the showcase too. HeroReelProvider is context-only now; its hover/focus/touch surface is the new HeroReelSwipeArea, which page.tsx uses as the hero text's rail so the band still pauses the reel and the mobile collage still swipes. Also records on LayoutContent why `overflow: clip` must stay `clip`: `hidden` or `auto` there would silently un-pin the landing page. A source-invariant test (the docsite suite is node-only) guards the rule's absence, the three layers never going back to `fixed`, the rails' order and containment, and the AppShell/LayoutContent links that keep the main area a non-scroll container. Verified against untouched main with Playwright + pixelmatch at six viewports x ten scroll offsets: 0 px at the default threshold, identical layer geometry, `overscroll-behavior-y: auto` everywhere, no fixed element reaching the viewport bottom (was 2-3), 11/11 hover/focus/swipe checks passing on both trees, resize-while-scrolled and theme-swap mid-scroll 0 px. Safari and a real rubber-band are not verified here. Step 2 of meta#5392. Fixes meta#5470. Supersedes the zero-height-pin approach in meta#5431 and folds in the backdropGlow comment correction from meta#5467.
…core Review: the comment-only change to packages/core/src/Layout/LayoutContent.tsx made a docsite fix look like a core change and pulled in the core CI path. The note on why AppShell's main area must stay overflow: clip now lives on the rail style in HeroThemeReel.tsx; home-hero-overscroll.test.ts still enforces it in LayoutContent.
Review: the guard rejected every non-auto overscroll-behavior declaration in globals.css, which would also reject a legitimate contain on a nested scroller. It now reports a declaration only when its selector subject is html, body, :root or * (case-insensitive, :is() and :where() looked through, enclosing at-rules named), and only real declarations, so an @supports (overscroll-behavior: none) prelude cannot swallow the rule inside it. The guard has its own fixtures; the page-level rule this change deletes still fails it inside any at-rule.
a6b5968 to
eef4fd2
Compare
|
Done, thanks. Rebased onto current main and resolved HeroThemeReel.tsx keeping #5467's causal chain, with its tail updated for the deleted rule. Dropped the LayoutContent change; the clip note now sits on the hero's rail style and the test still enforces it in core. The globals.css guard now only reports overscroll-behavior on html, :root, body or * (looking through :is() and :where()), with its own fixtures, so a contain on a nested scroller passes. |
There was a problem hiding this comment.
Thanks for finishing this — the sticky-rail approach is the right structural fix: bounding the glow, cards, and hero text inside full-height rails preserves the pinned hero while letting the root overscroll rule be deleted instead of narrowed again. The provider/swipe-surface split and the rail ordering also look sound in static review, and the hosted docsite tests pass.
One focused change is needed before this is ready:
- Fix the selector classifier in
home-hero-overscroll.test.ts.isPageWidecurrently treats any final*as page-wide, so legitimate nested rules such asbody .dialog *or.dialog *withoverscroll-behavior: containwould be rejected. It also only unwraps:is()/:where()when the wrapper is the whole selector compound, so composed root rules such as:is(html, body).modeor:is(html, body):hoverwould be missed and could bring back the site-wide overscroll suppression undetected. Please classify the actual root/body subject, handle wrappers with following class or pseudo-class suffixes, and add fixtures for both directions.
Safari/WebKit and a real trackpad rubber-band gesture remain unverified, as noted in the PR; please keep that manual check in view, but it is not the reason for this request. No change to the sticky hero runtime is being requested for this finding.
[Automated review]
…sely Review (astracat-bot): isPageWide flagged any trailing `*` and only unwrapped :is()/:where() when the wrapper was the whole subject, so it both rejected legitimate nested rules and missed composed root rules. Test-only; no change to the sticky hero runtime. F1: a trailing `*` now counts as page-wide only on its own or as a child or descendant of a first compound that can be the root (html, :root or *, bare or wrapped): `*`, `*:hover`, `html *`, `:root > *`, `* > *` stay reported; `.dialog *`, `body .dialog *`, `.sheet > *` and `.dialog * *` with `contain` pass. Red before the change: those four were reported as offenders. F2: the splitter now keeps (), [] and quoted strings whole, and the subject compound is split into simple selectors, so html, body or :root counts anywhere in it and :is()/:where() are looked through wherever they sit; :not()/:has() arguments are not. `:is(html, body).mode`, `:is(html, body):hover`, `:where(html)[data-hero-dark]`, `[data-x]:where(html)`, `html[class~='dark']` and `body[data-mode='a b']` are now reported. Red before the change: the guard returned [] for all six. home-hero-overscroll.test.ts: 20/20 (16 existing, 4 new), including the real globals.css assertion.
…oll guard Review (astracat-bot), F1 follow-up: 16d7e27 counted a `*` subject only on its own or under a root-capable first compound via ` ` or `>`, so it silently allowed sibling selectors that land on body, which always follows head: `* + *`, `* ~ *`, `head + *`, `head ~ *`, `:root > * + *`, `html > head ~ *`. eef4fd2 reported all of them. The `*` subject is now walked through a model of the page's top (html holds head, then body): each compound must name the element it lands on (its tag, `:root` for html, or `*`, bare or inside :is()/:where()), and ` `/`>` step to the parent while `+`/`~` step to the previous sibling. So `* + *`, `head + *` and `:root > * + *` are reported; `html ~ *` and `html + *` (html has no siblings) and nested owl selectors like `.stack > * + *` are not. canBeRoot is folded into the same walk. Red before the change, on the new fixtures: `expected [ …(5) ] to deeply equal [ …(9) ]`, missing `* + *`, `* ~ *`, `head + *` and `:root > * + *`. home-hero-overscroll.test.ts: 21/21 after, including the real globals.css assertion. F2's fixtures are unchanged and still pass. Test-only.
|
Thanks, both directions reproduced on eef4fd2. I pushed two test-only commits. The sticky hero runtime is unchanged.
Left out on purpose: CSS nesting isn't resolved, because globals.css doesn't nest. A The Safari/WebKit trackpad rubber-band check is still manual, and I haven't done it yet. |
There was a problem hiding this comment.
This looks ready to merge: the sticky rails keep the home hero pixel-identical at rest and while scrolling, release the pinned layers before the footer at the page end, and so let the root overscroll-behavior-y: none rule go, and the new guard fails without the fix and passes with it. Before landing, please do the Safari trackpad pass you flagged at both ends of the home page, including a pull at the very top on a non-default slide: navBackdrop is still position: fixed, and a simulated 40px pull leaves its tint at the top while the nav slides over the white page canvas. The branch merges cleanly with current main and the guard passes on that merge, but CI has not run against today's AppShell, so a fresh CI run on the updated branch is worth having.
[Automated review]
There was a problem hiding this comment.
The sticky rails keep the home hero pixel-identical at rest and while scrolling, release the pinned layers before the footer, and the new guard fails without the fix and passes with it, so no code change is requested. Approval now waits on a maintainer decision: no current spec covers the docsite root's overscroll, so a maintainer needs to provide or identify the governing spec for restoring native overscroll on every docsite route at 1024px and wider (for example a claim in spec:AST-033), or explicitly accept it without one. The Safari trackpad pass you flagged is still worth doing at both ends of the home page, including a pull at the very top, where the still-fixed navBackdrop may stay behind while the nav moves.
[Automated review]
Step 2 of #5392. Fixes #5470.
What this does
Keeps the home page hero pinned exactly as it is today, but without the CSS rule that switched off the browser's native overscroll. On a Mac trackpad the page rubber-bands again at the top and bottom, like every other page on the web. Nothing changes visually.
Why
The hero's three pinned layers (the aurora glow, the floating cards and the headline block) were
position: fixed. A fixed layer is glued to the screen rather than to the page, so when the page rubber-bands past its own end the layer sits in the gap that opens up. #3032 hid that by turning overscroll off for the whole site, and #5415 narrowed the rule to desktop widths to give mobile its pull-to-refresh back. This finishes the job: the layers are nowposition: stickyinside full-height rails, so they lift with the page and physically cannot paint past its end. That is structural, which is why the rule can be deleted instead of narrowed further.What changed
position: absolute; inset: 0box that is a direct child ofheroScope, spans the hero band and the showcase, and sits ahead of the showcase overlay so tree order still equals paint order (backdrop, cards, hero text, then the showcase covering them). A rail inside the 760px band alone releases its layer after about 48px, which is the trap the issue calls out.backdropGlow, the cardsstageandheroContentgofixed->sticky; top: var(--appshell-header-height)at 1024px and up. Narrow widths are untouched: the glow stays absolute and the hero text stays in flow.left: 50%+translateX(-50%)to auto margins in the full-width rail (on a sticky boxleftis an inset, not an offset). The 1200px box is capped to the rail's width rather than100vw: with a classic scrollbar100vwis wider than the rail, which zeroes the auto margins and shoves the box left.HeroReelProviderrenders no DOM any more. Its hover / focus / touch surface is the newHeroReelSwipeArea, whichpage.tsxuses as the hero text's rail, so the band and its gutters still pause the reel and the phone collage still swipes.HeroReelCardsis split intoHeroReelBackdrop(fills + glow) andHeroReelCards(stage).@media (min-width: 1024px) { html { overscroll-behavior-y: none } }block is deleted fromglobals.css.overflow: clipinLayoutContent;hiddenorautothere would silently un-pin the landing page). That is recorded on the hero's rail style and enforced by the test below; core is untouched.home-hero-overscroll.test.ts. The docsite suite is node-only with StyleX untransformed, so these are source invariants in the shape ofcomponent-preview-theme.test.ts:globals.cssnever setsoverscroll-behavioronhtml,:root,bodyor*away fromauto, at any width (acontainon a nested scroller is fine; the guard has its own fixtures for@mediaand@supportswrappers,:is()/:where()and upper-case selectors); none of the three layers is everfixedin any media arm; the rails are bounded byheroScopeand precede the showcase; the boxes are sized against the rail, not100vw; and the AppShell / LayoutContent links that keep the main area a non-scroll container (overflow: clip,isScrollable={isFill}, the landing layout'sheight="auto") hold. It is red onmaintoday, and single-line mutations (afixedbehind a trailing comment, double quotes, a computed[BREAKPOINT]key, anoverflowYlonghand,isScrollableunconditional,height="fill", the width back to100vw,heroScopestatic, a rail moved after the showcase, the old@mediaroot rule,:root { overscroll-behavior: contain }, an upper-caseHTMLrule, a minified root rule, a root rule inside@supports) each turn it red again.How to see it
Nothing should look different; that is the point. Run the docsite with the canary banner off so the header is the production 48px (
NEXT_PUBLIC_DOCS_TARGET=latest pnpm -F @astryxdesign/docsite dev), open the home page on a Mac and rubber-band at the bottom: the page bounces and the footer stays clean. The Vercel preview on this PR shows the same page.Measured against an untouched
maincheckout with Playwright + pixelmatch, both served with the banner hidden,prefers-reduced-motion: reduceso the reel holds its first slide, and transitions frozen, at ten scroll offsets per viewport (0, 100, 200, 400, 712, 760, 800, 1400, 2200, max):mainoverscroll-behavior-ynone->autonone->autonone->autonone->autoauto->autoauto->autoLayer geometry matches
fixedat every offset (hero text at y=48 and 712px tall, glow and stage at x=40 and 1200px wide at 1280) until max scroll, where sticky releases behind the opaque showcase. Document height is unchanged (3540px).elementFromPointon the "Get started" button still returns the button.Also checked on both trees: hover in the gutter, on the CTA and over the pinned hero while scrolled pauses the reel, hover on the showcase does not, keyboard focus on a dot pauses and blur resumes, a phone swipe steps the reel left and right and a vertical drag does not (11 checks, identical results before and after); resize while scrolled (1280 -> 1440 -> 1100 at scroll 400) and a theme swap mid-scroll with transitions running, 0 pixels differing; and a forced 15px classic scrollbar, where the old
fixedbox sat at x=-7.5 overflowing both sides and the new one sits centered inside the rail.pnpm -F @astryxdesign/docsite test(29 files, 434 tests),tsc --noEmit, strict eslint and prettier are green.Not verified here
Safari and WebKit, and a real rubber-band gesture, which cannot be driven headlessly. That is the careful visual pass the issue budgets for.
Related
backdropGlowcomment's causal chain; this branch carries that wording and updates its tail for the deleted rule.