124 lines
4.7 KiB
TypeScript
124 lines
4.7 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useRef } from 'react';
|
|
import Image from 'next/image';
|
|
import { useTranslations } from 'next-intl';
|
|
import RequestQuoteForm from '@/components/RequestQuoteForm';
|
|
|
|
interface ProductSidebarProps {
|
|
productName: string;
|
|
productImage?: string;
|
|
datasheetPath?: string | null;
|
|
}
|
|
|
|
export default function ProductSidebar({ productName, productImage, datasheetPath }: ProductSidebarProps) {
|
|
const t = useTranslations('Products');
|
|
const sidebarRef = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
const handleScroll = () => {
|
|
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)`;
|
|
};
|
|
|
|
let rafId: number;
|
|
const onScroll = () => {
|
|
rafId = requestAnimationFrame(handleScroll);
|
|
};
|
|
|
|
window.addEventListener('scroll', onScroll, { passive: true });
|
|
window.addEventListener('resize', handleScroll);
|
|
|
|
// Initial call
|
|
handleScroll();
|
|
|
|
return () => {
|
|
window.removeEventListener('scroll', onScroll);
|
|
window.removeEventListener('resize', handleScroll);
|
|
cancelAnimationFrame(rafId);
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<div
|
|
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 */}
|
|
<div className="bg-white rounded-[32px] shadow-2xl border border-neutral-dark/5 overflow-hidden">
|
|
<div className="bg-primary-dark p-6 text-white relative overflow-hidden">
|
|
<div className="absolute top-0 right-0 w-32 h-32 bg-accent/10 rounded-full -translate-y-1/2 translate-x-1/2 blur-2xl" />
|
|
|
|
{/* Product Thumbnail */}
|
|
{productImage && (
|
|
<div className="relative w-full aspect-[21/9] mb-4 rounded-2xl overflow-hidden bg-white/5 backdrop-blur-xl p-4 border border-white/10 z-10">
|
|
<Image
|
|
src={productImage}
|
|
alt=""
|
|
fill
|
|
className="object-contain p-1"
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
<h3 className="text-xl font-black mb-2 relative z-10 tracking-tight uppercase">{t('requestQuote')}</h3>
|
|
<p className="text-white/50 text-sm relative z-10 leading-relaxed font-medium">{t('requestQuoteDesc')}</p>
|
|
</div>
|
|
<div className="p-6">
|
|
<RequestQuoteForm productName={productName} />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Datasheet Download */}
|
|
{datasheetPath && (
|
|
<a
|
|
href={datasheetPath}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="block bg-white/90 backdrop-blur-md rounded-[32px] border border-neutral-dark/5 overflow-hidden group hover:bg-white hover:shadow-xl transition-all duration-500 shadow-lg"
|
|
>
|
|
<div className="p-6 flex items-center gap-6">
|
|
<div className="w-14 h-14 rounded-2xl bg-neutral-light shadow-sm flex items-center justify-center flex-shrink-0 group-hover:bg-accent group-hover:text-white transition-all duration-500 text-accent">
|
|
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
</svg>
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className="text-lg font-black text-primary mb-1 uppercase tracking-tight">{t('downloadDatasheet')}</h3>
|
|
<p className="text-text-secondary text-xs font-medium leading-relaxed">{t('downloadDatasheetDesc')}</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|