From 174fcb855ad2f1b0d36f11a695f80a69b433cdf3 Mon Sep 17 00:00:00 2001 From: erikgh Date: Fri, 31 Jul 2026 16:11:41 -0600 Subject: [PATCH] =?UTF-8?q?fix(hilo):=20la=20banda=20alargaba=20el=20docum?= =?UTF-8?q?ento=205.800px=20de=20vac=C3=ADo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Un con viewBox es un elemento reemplazado con proporción intrínseca (100:1200). Al dimensionarlo con top-0 + bottom-20 y dejar la altura en auto, el navegador la resolvía desde el ancho — 1152 × 12 = 13.824px — y esa altura ganaba silenciosamente a `bottom`. Consecuencias, todas visibles en el navegador y ninguna en los tests: - 5.840px de blanco vacío scrolleable por debajo del footer. - scrollYProgress repartido sobre 13.901px en vez de 8.061, así que el trazo nunca terminaba sobre contenido real. - la onda estirada 1,8x de más, otra vez casi recta. Altura explícita con h-[calc(100%-5rem)], y test que lo fija: jsdom no hace layout, así que el guardián es la clase. El trazo pasa a completarse a mitad de scroll (FIN 0.85 → 0.5). Con 0.85 la punta se quedaba a media pantalla durante el 42% de la página, que es justo lo que se leía como "sin terminar". Co-Authored-By: Claude Opus 5 --- components/primitives/HiloConductor.tsx | 15 ++++++++++----- .../primitives/__tests__/HiloConductor.test.tsx | 11 +++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/components/primitives/HiloConductor.tsx b/components/primitives/HiloConductor.tsx index 64799e0..99b3574 100644 --- a/components/primitives/HiloConductor.tsx +++ b/components/primitives/HiloConductor.tsx @@ -38,10 +38,11 @@ const TRAZO = Array.from({ length: TRAMOS }, (_, i) => { return `C ${x} ${y + PASO * 0.25}, ${salida} ${y + PASO * 0.75}, 50 ${y + PASO}`; }).reduce((d, tramo) => `${d} ${tramo}`, 'M50 0'); -// The draw finishes at 85% of the document instead of at the very bottom: -// scrollYProgress only reaches 1 past the footer, so tying the thread to it -// left the tip trailing in mid-screen and the ending never seen. -const FIN = 0.85; +// The draw finishes halfway down the document. Tied to raw scrollYProgress the +// leading tip sat in mid-viewport for most of the page, reading as an amputated +// stub — the "unfinished" complaint. Finishing early lets the tip outrun the +// reader within the hero and leaves a complete spine for everything after. +const FIN = 0.5; export function HiloConductor({ className = '' }: { className?: string }) { const reduced = usePrefersReducedMotion(); @@ -87,8 +88,12 @@ export function HiloConductor({ className = '' }: { className?: string }) { {/* Mirrors Container's own centring (`mx-auto max-w-content`) so the thread is measured from the real column edge and stays centred in it. */}
+ {/* Explicit height, never a top+bottom pair: an carrying a viewBox + is a replaced element with an intrinsic 100:1200 ratio, so `height: + auto` resolves from the width (1152 → 13824px) and silently wins + over `bottom`, adding ~6000px of blank scroll below the footer. */} ', () => { expect(container.querySelector('path')).toHaveAttribute('vector-effect', 'non-scaling-stroke'); }); + it('sizes the band with an explicit height, never a top+bottom pair', () => { + const { container } = render(); + const cls = container.querySelector('svg')?.getAttribute('class') ?? ''; + // An carrying a viewBox is a replaced element with an intrinsic + // ratio, so `height: auto` resolves from the width and silently beats + // `bottom` — which stretched this one to 13824px and hung ~6000px of blank + // scroll below the footer. jsdom has no layout, so the class is the guard. + expect(cls).toMatch(/\bh-\[/); + expect(cls).not.toMatch(/\bbottom-/); + }); + it('reads as a band, not as a hairline', () => { const { container } = render(); const grosor = Number(container.querySelector('path')?.getAttribute('stroke-width'));