This commit is contained in:
2026-01-19 17:43:23 +01:00
parent 40c553d6f6
commit 1f624f3d7f
3 changed files with 115 additions and 81 deletions

View File

@@ -1,6 +1,6 @@
'use client';
import { useState, useEffect } from 'react';
import { useEffect, useRef } from 'react';
import Image from 'next/image';
import { useTranslations } from 'next-intl';
import RequestQuoteForm from '@/components/RequestQuoteForm';
@@ -13,30 +13,62 @@ interface ProductSidebarProps {
export default function ProductSidebar({ productName, productImage, datasheetPath }: ProductSidebarProps) {
const t = useTranslations('Products');
const [isVisible, setIsVisible] = useState(false);
const sidebarRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleScroll = () => {
// Show sidebar after scrolling down 400px (approx height of hero)
if (window.scrollY > 400) {
setIsVisible(true);
} else {
setIsVisible(false);
if (!sidebarRef.current) return;
const sidebar = sidebarRef.current;
const container = sidebar.parentElement;
if (!container) return;
const containerRect = container.getBoundingClientRect();
const sidebarHeight = sidebar.offsetHeight;
// Offset from top of viewport when sticky
const stickyOffset = 128; // 8rem = top-32
let translateY = 0;
// If the top of the container has scrolled past our sticky offset
if (containerRect.top < stickyOffset) {
translateY = stickyOffset - containerRect.top;
}
// Don't let it go past the bottom of the container
const maxTranslateY = containerRect.height - sidebarHeight;
if (translateY > maxTranslateY) {
translateY = maxTranslateY;
}
// Ensure translateY is never negative
if (translateY < 0) translateY = 0;
sidebar.style.transform = `translateY(${translateY}px)`;
};
window.addEventListener('scroll', handleScroll);
// Check initial scroll position
handleScroll();
let rafId: number;
const onScroll = () => {
rafId = requestAnimationFrame(handleScroll);
};
window.addEventListener('scroll', onScroll, { passive: true });
window.addEventListener('resize', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
// Initial call
handleScroll();
return () => {
window.removeEventListener('scroll', onScroll);
window.removeEventListener('resize', handleScroll);
cancelAnimationFrame(rafId);
};
}, []);
return (
<div
className={`hidden lg:block fixed top-32 right-8 z-50 w-[350px] xl:w-[400px] transition-all duration-700 transform ${
isVisible ? 'translate-x-0 opacity-100' : 'translate-x-[120%] opacity-0'
}`}
ref={sidebarRef}
className="hidden lg:block absolute left-full ml-12 top-0 w-[350px] xl:w-[400px] z-30 will-change-transform"
>
<div className="space-y-6">
{/* Request Quote Form */}