wip
This commit is contained in:
@@ -276,9 +276,10 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex flex-col lg:flex-row relative items-start">
|
<div className="relative">
|
||||||
|
<div className="space-y-20">
|
||||||
{/* Sidebar on Mobile (Above Content) */}
|
{/* Sidebar on Mobile (Above Content) */}
|
||||||
<div className="w-full lg:hidden mb-20">
|
<div className="w-full lg:hidden">
|
||||||
<div className="space-y-10">
|
<div className="space-y-10">
|
||||||
{/* Request Quote Form */}
|
{/* Request Quote Form */}
|
||||||
<div className="bg-white rounded-[40px] shadow-[0_32px_64px_-12px_rgba(0,0,0,0.08)] border border-neutral-dark/5 overflow-hidden">
|
<div className="bg-white rounded-[40px] shadow-[0_32px_64px_-12px_rgba(0,0,0,0.08)] border border-neutral-dark/5 overflow-hidden">
|
||||||
@@ -316,7 +317,7 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1 w-full">
|
<div className="w-full">
|
||||||
{/* Main Content Area */}
|
{/* Main Content Area */}
|
||||||
<div className="max-w-none">
|
<div className="max-w-none">
|
||||||
<MDXRemote source={product.content} components={components} />
|
<MDXRemote source={product.content} components={components} />
|
||||||
@@ -347,6 +348,7 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ProductSidebar
|
<ProductSidebar
|
||||||
productName={product.frontmatter.title}
|
productName={product.frontmatter.title}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import RequestQuoteForm from '@/components/RequestQuoteForm';
|
import RequestQuoteForm from '@/components/RequestQuoteForm';
|
||||||
@@ -13,30 +13,62 @@ interface ProductSidebarProps {
|
|||||||
|
|
||||||
export default function ProductSidebar({ productName, productImage, datasheetPath }: ProductSidebarProps) {
|
export default function ProductSidebar({ productName, productImage, datasheetPath }: ProductSidebarProps) {
|
||||||
const t = useTranslations('Products');
|
const t = useTranslations('Products');
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const sidebarRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleScroll = () => {
|
const handleScroll = () => {
|
||||||
// Show sidebar after scrolling down 400px (approx height of hero)
|
if (!sidebarRef.current) return;
|
||||||
if (window.scrollY > 400) {
|
const sidebar = sidebarRef.current;
|
||||||
setIsVisible(true);
|
const container = sidebar.parentElement;
|
||||||
} else {
|
if (!container) return;
|
||||||
setIsVisible(false);
|
|
||||||
|
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);
|
let rafId: number;
|
||||||
// Check initial scroll position
|
const onScroll = () => {
|
||||||
|
rafId = requestAnimationFrame(handleScroll);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('scroll', onScroll, { passive: true });
|
||||||
|
window.addEventListener('resize', handleScroll);
|
||||||
|
|
||||||
|
// Initial call
|
||||||
handleScroll();
|
handleScroll();
|
||||||
|
|
||||||
return () => window.removeEventListener('scroll', handleScroll);
|
return () => {
|
||||||
|
window.removeEventListener('scroll', onScroll);
|
||||||
|
window.removeEventListener('resize', handleScroll);
|
||||||
|
cancelAnimationFrame(rafId);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`hidden lg:block fixed top-32 right-8 z-50 w-[350px] xl:w-[400px] transition-all duration-700 transform ${
|
ref={sidebarRef}
|
||||||
isVisible ? 'translate-x-0 opacity-100' : 'translate-x-[120%] opacity-0'
|
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">
|
<div className="space-y-6">
|
||||||
{/* Request Quote Form */}
|
{/* Request Quote Form */}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user