fix(ecommerce): CTA fijo de mobile ya no sigue hasta el footer
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 32s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 10m5s

La barra de "Añadir al carrito" quedaba pegada abajo en mobile hasta
el final de la página (incluso sobre el footer), mucho después de que
el usuario ya pasó "También te puede gustar". Se agrega un tercer
sentinel (#recommendations-section) observado por IntersectionObserver:
una vez que su borde superior cruza el tope del viewport, la barra se
oculta y no vuelve a aparecer bajando más.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
This commit is contained in:
devopsandClaude Sonnet 5 committed 2026-09-14 01:09:52 +00:00
1 parent af9576f45d
commit cd72962fa4
2 files changed
+21 -3

No files matched your search

@@ -10,7 +10,7 @@ const SCROLL_THRESHOLD_PX = 80;
// Antes esta barra quedaba fija desde el primer render en mobile,
// tapando permanentemente parte de la imagen del producto solo para
// duplicar un boton que ya está visible más abajo. Ahora combina dos
// duplicar un boton que ya está visible más abajo. Ahora combina tres
// condiciones, igual que el "Buy Now" sticky de Amazon:
// - scrolled: recien aparece despues de que el usuario empieza a
// scrollear (nunca sobre la vista inicial de la imagen/hero).
@@ -18,9 +18,16 @@ const SCROLL_THRESHOLD_PX = 80;
// ProductPurchase, visible tambien en mobile) no esta en pantalla --
// ya sea porque todavia no se llego a el, o porque se scrolleo mas
// alla.
// - !pastRecommendations: una vez que se llega a "También te puede
// gustar" (#recommendations-section en app/product/[slug]/page.tsx)
// la barra se oculta y ya no vuelve a aparecer bajando mas -- pedido
// explicito del usuario (antes quedaba pegada hasta el footer, sin
// sentido una vez que el contenido principal del producto ya quedó
// atrás).
export function MobileAddToCart({ product }: { product: Product }) {
const addItem = useCartStore((state) => state.addItem);
const [buttonVisible, setButtonVisible] = useState(true);
const [pastRecommendations, setPastRecommendations] = useState(false);
const [scrolled, setScrolled] = useState(false);
const outOfStock = product.variants[0]?.available === false;
@@ -35,6 +42,17 @@ export function MobileAddToCart({ product }: { product: Product }) {
return () => observer.disconnect();
}, []);
useEffect(() => {
const target = document.getElementById("recommendations-section");
if (!target) return;
const observer = new IntersectionObserver((entries) => {
const entry = entries[0];
if (entry) setPastRecommendations(entry.boundingClientRect.top <= 0);
}, { threshold: 0 });
observer.observe(target);
return () => observer.disconnect();
}, []);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > SCROLL_THRESHOLD_PX);
onScroll();
@@ -42,7 +60,7 @@ export function MobileAddToCart({ product }: { product: Product }) {
return () => window.removeEventListener("scroll", onScroll);
}, []);
const visible = scrolled && !buttonVisible;
const visible = scrolled && !buttonVisible && !pastRecommendations;
return (
<div