🐛 Fix homepage hero scroll arrow landing position - #4967
Closed
designbyalex wants to merge 2 commits into
Closed
Conversation
Contributor
Coverage report
Test suite run success19 tests passing in 2 suites. Report generated by 🧪jest coverage report action from fe2c772 |
The scroll arrow aimed at itself: it scrolled so the button sat 10% of the
viewport height from the top of the screen. That is a proxy for, not the same
as, the start of the next section, so a slice of hero stayed on screen and the
next section was pushed down and cut off. Because the offset was a fraction of
viewport height, the landing spot also drifted with screen size.
It now aims at the next block. V2ComponentWrapper marks its inner content
section with data-block-content, so the target is declared rather than guessed
at by walking the DOM: decorative layers (bleed image, redGlow, gridOverlay)
render outside that marker and can no longer be mistaken for content, and
wrapper padding is skipped by reading the content container directly.
findNextBlock steps over blocks that render nothing, are hidden at the current
breakpoint, or are decorative. Spacer now carries aria-hidden on whichever
element it renders outermost — previously only its undecorated branch had it,
so a decorated spacer or one with hideOn set could become the scroll target.
Also honours prefers-reduced-motion ("instant" rather than "auto", since auto
defers to the global scroll-smooth in styles.css), and moves focus to the
landed section so screen readers and the keyboard follow the viewport.
Verified in Chrome at 1440x900 and 390x844: the next block's content lands at
the top of the viewport, where the old code stopped 261px and 255px short.
Fixed #4928
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
designbyalex
force-pushed
the
fix/4928-hero-scroll-arrow
branch
from
August 6, 2026 03:49
b011420 to
6e785d6
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (1)
lib/scrollToBlock.ts:47
ScrollToOptions.behavioronly standardizes "auto" and "smooth"; "instant" is non-standard and may be ignored on some browsers, which would make the reduced-motion path still animate due to the globalscroll-smoothCSS. To reliably honorprefers-reduced-motion, forcescroll-behavior: autoon the root element for the duration of the scroll and usebehavior: "auto".
window.scrollTo({
top: getBlockContentTop(blockRoot),
// "instant" not "auto" — auto defers to the global scroll-smooth CSS.
behavior: prefersReducedMotion() ? "instant" : "smooth",
});
This was referenced Aug 6, 2026
Member
Author
|
Closed and superseded by #4969 |
designbyalex
added a commit
that referenced
this pull request
Aug 6, 2026
The arrow landed 10% of viewport height *below* the top of the screen, leaving a slice of hero on view. Negating the offset lands it 10% *above* instead, so the hero clears the viewport. ```diff - top: window.scrollY + top - window.innerHeight * 0.1, + top: window.scrollY + top + window.innerHeight * 0.1, ``` - Affected routes: `/` - Closes #4928 > [!NOTE] > Overlaps with #4967, which rewrites the same handler. Merge one, not both. ## Testing Chrome DevTools, homepage, checking the service cards section is fully in view after the scroll settles: | Viewport | Result | |---|---| | 768 × 1024, 1440 × 900, 1920 × 1080 | ✅ | | 390 × 844, 1280 × 800, 1366 × 768 |⚠️ cards clipped 64–110 px | | 375 × 667 | ❌ cards clipped 326 px | Heading is always visible. Remaining clipping is because the formula aims at the button, not the section — and at 375 × 667 and 1366 × 768 the content is taller than the viewport, so no scroll offset fits it. Those need `py-24` or the card graphic shrunk. --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The scroll arrow aimed at itself — it scrolled so the button sat 10% of the viewport height from the top, which isn't where the next section starts. A slice of hero stayed on screen, and because the offset was a fraction of viewport height, the landing spot drifted with screen size.
Now it aims at the next block: skips its wrapper padding and scrolls to its first content element.
Affected routes:
/Closes 🐛 Bug - Homepage scroll arrow does not align to next section #4928
Also moves focus to the landed section for screen readers, and respects
prefers-reduced-motion("instant"not"auto"—autodefers to the globalscroll-smoothCSS), plus a one-line comment fix inv2ComponentWrapper.tsx:scroll-mt-24isn't a sticky-header offset, the header isn't sticky.Verified in Chrome, desktop and mobile. No automated test — jsdom has no layout engine, so Jest can't assert scroll positions.
Desktop Before
Desktop After
Mobile Before
Mobile After
🤖 Generated with Claude Code