fix(route): track 580 + 140px scroll-container padding — no more clipping
The route was clipping at three places: top and bottom of hovered cards (the track was only 460 tall) and at the left/right viewport edges (first card half-off-screen at scrollLeft 0, last card off the right at scrollEnd). Track height: default trackHeight in roadmap-layout 460 → 580; .rr-track inline-style and the SVG height matched. midY now 290. Path centreline stays in the visual centre and gains 60px breathing room above + 60px below — which is exactly the room a hovered card needs to expand into. Scroll-container padding: .rr-scroll gains 140px of horizontal padding plus matching scroll-padding-left/right so snap-stops land cleanly. The 140 figure is 220px card-width / 2 + 30px buffer, so the first and last cards have a full card-width of clear space inside the viewport at the scroll extremes. Layout helper test verifies midY === 290. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
33a21735e6
commit
fde07b1f11
3 changed files with 10 additions and 4 deletions
|
|
@ -83,8 +83,8 @@ const initialShippingX = lastShippingIndex >= 0 ? itemXByIndex[lastShippingIndex
|
||||||
<!-- The route — desktop horizontal -->
|
<!-- The route — desktop horizontal -->
|
||||||
<div class="rr-wrap rr-desktop">
|
<div class="rr-wrap rr-desktop">
|
||||||
<div class="rr-scroll" id="rr-scroll">
|
<div class="rr-scroll" id="rr-scroll">
|
||||||
<div class="rr-track" style={`width: ${layout.trackWidth}px; height: 460px;`}>
|
<div class="rr-track" style={`width: ${layout.trackWidth}px; height: 580px;`}>
|
||||||
<svg class="rr-path" width={layout.trackWidth} height="460" aria-hidden="true">
|
<svg class="rr-path" width={layout.trackWidth} height="580" aria-hidden="true">
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="rr-path-gradient" x1="0" y1="0" x2="1" y2="0">
|
<linearGradient id="rr-path-gradient" x1="0" y1="0" x2="1" y2="0">
|
||||||
<stop offset="0" stop-color="#2a2520" stop-opacity="0.55"/>
|
<stop offset="0" stop-color="#2a2520" stop-opacity="0.55"/>
|
||||||
|
|
@ -289,7 +289,12 @@ const initialShippingX = lastShippingIndex >= 0 ? itemXByIndex[lastShippingIndex
|
||||||
scroll-snap-type: x mandatory;
|
scroll-snap-type: x mandatory;
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
padding-bottom: 8px;
|
/* Card-half (110px) + breathing buffer (30px) so first/last dots
|
||||||
|
have a card-width of clear space inside the viewport when scrolled
|
||||||
|
to the extremes. scroll-padding makes snap-stops land cleanly. */
|
||||||
|
padding: 0 140px 8px;
|
||||||
|
scroll-padding-left: 140px;
|
||||||
|
scroll-padding-right: 140px;
|
||||||
}
|
}
|
||||||
.rr-scroll::-webkit-scrollbar { display: none; }
|
.rr-scroll::-webkit-scrollbar { display: none; }
|
||||||
.rr-track { position: relative; }
|
.rr-track { position: relative; }
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export interface LayoutResult {
|
||||||
|
|
||||||
export function computeRouteLayout(opts: LayoutOpts): LayoutResult {
|
export function computeRouteLayout(opts: LayoutOpts): LayoutResult {
|
||||||
const minSpacing = opts.minSpacingX ?? 320;
|
const minSpacing = opts.minSpacingX ?? 320;
|
||||||
const trackHeight = opts.trackHeight ?? 460;
|
const trackHeight = opts.trackHeight ?? 580;
|
||||||
const amplitude = opts.amplitude ?? 120;
|
const amplitude = opts.amplitude ?? 120;
|
||||||
const padding = opts.paddingX ?? 60;
|
const padding = opts.paddingX ?? 60;
|
||||||
const midY = trackHeight / 2;
|
const midY = trackHeight / 2;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ describe('computeRouteLayout', () => {
|
||||||
it('1 item — produces a valid single-point M path on the centreline', () => {
|
it('1 item — produces a valid single-point M path on the centreline', () => {
|
||||||
const out = computeRouteLayout({ itemCount: 1, viewportWidth: 1000 });
|
const out = computeRouteLayout({ itemCount: 1, viewportWidth: 1000 });
|
||||||
expect(out.itemX).toHaveLength(1);
|
expect(out.itemX).toHaveLength(1);
|
||||||
|
expect(out.midY).toBe(290); // trackHeight 580 / 2
|
||||||
expect(out.itemY).toEqual([out.midY]);
|
expect(out.itemY).toEqual([out.midY]);
|
||||||
expect(out.cardSide).toEqual(['below']);
|
expect(out.cardSide).toEqual(['below']);
|
||||||
expect(out.pathD.startsWith('M ')).toBe(true);
|
expect(out.pathD.startsWith('M ')).toBe(true);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue