wip
This commit is contained in:
@@ -6,6 +6,7 @@ import ProductTechnicalData from '@/components/ProductTechnicalData';
|
||||
import ProductTabs from '@/components/ProductTabs';
|
||||
import RequestQuoteForm from '@/components/RequestQuoteForm';
|
||||
import RelatedProducts from '@/components/RelatedProducts';
|
||||
import ProductSidebar from '@/components/ProductSidebar';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
@@ -65,28 +66,34 @@ export async function generateMetadata({ params }: ProductPageProps): Promise<Me
|
||||
const components = {
|
||||
ProductTechnicalData,
|
||||
ProductTabs,
|
||||
p: (props: any) => <p {...props} className="text-lg md:text-xl text-text-secondary leading-relaxed mb-8" />,
|
||||
p: (props: any) => <p {...props} className="text-lg md:text-xl text-text-secondary leading-relaxed mb-8 font-medium" />,
|
||||
h2: (props: any) => (
|
||||
<div className="relative mt-20 mb-10">
|
||||
<h2 {...props} className="text-3xl md:text-4xl lg:text-5xl font-extrabold text-primary tracking-tight" />
|
||||
<div className="absolute -bottom-4 left-0 w-24 h-1.5 bg-accent rounded-full" />
|
||||
<div className="relative mt-24 mb-12">
|
||||
<h2 {...props} className="text-4xl md:text-5xl font-black text-primary tracking-tighter uppercase" />
|
||||
<div className="mt-4 w-20 h-1.5 bg-accent rounded-full" />
|
||||
</div>
|
||||
),
|
||||
h3: (props: any) => <h3 {...props} className="text-2xl md:text-3xl lg:text-4xl font-bold text-primary mt-16 mb-6 tracking-tight" />,
|
||||
ul: (props: any) => <ul {...props} className="list-disc pl-8 mb-10 space-y-4 text-text-secondary text-lg md:text-xl" />,
|
||||
li: (props: any) => <li {...props} className="pl-2 marker:text-accent marker:font-bold" />,
|
||||
h3: (props: any) => <h3 {...props} className="text-2xl md:text-3xl font-black text-primary mt-16 mb-6 tracking-tight uppercase" />,
|
||||
ul: (props: any) => <ul {...props} className="list-none pl-0 mb-12 space-y-4" />,
|
||||
li: (props: any) => (
|
||||
<li className="flex items-start gap-4 group">
|
||||
<div className="mt-2.5 w-2 h-2 rounded-full bg-accent flex-shrink-0 group-hover:scale-125 transition-transform" />
|
||||
<span {...props} className="text-lg md:text-xl text-text-secondary leading-relaxed font-medium" />
|
||||
</li>
|
||||
),
|
||||
strong: (props: any) => <strong {...props} className="font-black text-primary" />,
|
||||
table: (props: any) => (
|
||||
<div className="overflow-x-auto my-16 rounded-3xl border border-neutral-dark/10 shadow-xl bg-white p-1">
|
||||
<div className="overflow-x-auto my-16 rounded-[32px] border border-neutral-dark/10 shadow-xl bg-white p-1">
|
||||
<table {...props} className="min-w-full divide-y divide-neutral-dark/10" />
|
||||
</div>
|
||||
),
|
||||
th: (props: any) => <th {...props} className="px-8 py-6 bg-neutral-light/50 text-left text-xs font-black uppercase tracking-[0.25em] text-primary/60" />,
|
||||
td: (props: any) => <td {...props} className="px-8 py-6 text-text-secondary border-t border-neutral-dark/5 text-lg md:text-xl" />,
|
||||
th: (props: any) => <th {...props} className="px-8 py-6 bg-neutral-light/50 text-left text-[10px] font-black uppercase tracking-[0.25em] text-primary/60" />,
|
||||
td: (props: any) => <td {...props} className="px-8 py-6 text-text-secondary border-t border-neutral-dark/5 text-lg md:text-xl font-medium" />,
|
||||
hr: () => <hr className="my-20 border-t-2 border-neutral-dark/5" />,
|
||||
blockquote: (props: any) => (
|
||||
<div className="my-12 p-8 md:p-12 bg-primary-dark rounded-3xl relative overflow-hidden group">
|
||||
<div className="absolute top-0 right-0 w-48 h-48 bg-accent/10 rounded-full -translate-y-1/2 translate-x-1/2 blur-3xl group-hover:bg-accent/20 transition-colors duration-700" />
|
||||
<div className="relative z-10 italic text-2xl md:text-3xl text-white/90 leading-relaxed font-medium" {...props} />
|
||||
<div className="my-16 p-10 md:p-16 bg-primary-dark rounded-[40px] relative overflow-hidden group">
|
||||
<div className="absolute top-0 right-0 w-64 h-64 bg-accent/10 rounded-full -translate-y-1/2 translate-x-1/2 blur-3xl group-hover:bg-accent/20 transition-colors duration-700" />
|
||||
<div className="relative z-10 italic text-2xl md:text-4xl text-white/90 leading-relaxed font-black tracking-tight" {...props} />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
@@ -194,49 +201,56 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
||||
const categoryTitle = t(`categories.${categoryKey}.title`);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen bg-neutral-light">
|
||||
<div className="flex flex-col min-h-screen bg-white relative">
|
||||
{/* Product Hero */}
|
||||
<section className="relative pt-40 pb-32 overflow-hidden bg-primary-dark">
|
||||
<section className="relative pt-40 pb-24 overflow-hidden bg-primary-dark">
|
||||
{/* Background Decorative Elements */}
|
||||
<div className="absolute top-0 right-0 w-1/2 h-full bg-gradient-to-l from-accent/5 to-transparent pointer-events-none" />
|
||||
<div className="absolute -top-24 -right-24 w-96 h-96 bg-accent/10 rounded-full blur-3xl pointer-events-none" />
|
||||
|
||||
<Container className="relative z-10">
|
||||
<div className="max-w-5xl animate-slide-up">
|
||||
<nav className="flex items-center mb-8 text-white/40 text-sm font-bold uppercase tracking-widest">
|
||||
<div className="max-w-4xl animate-slide-up">
|
||||
<nav className="flex items-center mb-12 text-white/40 text-[10px] font-black uppercase tracking-[0.2em]">
|
||||
<Link href={`/${locale}/products`} className="hover:text-accent transition-colors">{t('title')}</Link>
|
||||
<span className="mx-3 opacity-30">/</span>
|
||||
<span className="mx-4 opacity-20">/</span>
|
||||
<Link href={`/${locale}/products/${categorySlug}`} className="hover:text-accent transition-colors">{categoryTitle}</Link>
|
||||
<span className="mx-3 opacity-30">/</span>
|
||||
<span className="mx-4 opacity-20">/</span>
|
||||
<span className="text-white/90">{product.frontmatter.title}</span>
|
||||
</nav>
|
||||
|
||||
<div className="flex flex-col lg:flex-row lg:items-end justify-between gap-12">
|
||||
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-12">
|
||||
<div className="flex-1">
|
||||
{isFallback && (
|
||||
<div className="mb-6 inline-flex items-center px-3 py-1 rounded-md bg-accent/10 border border-accent/20 text-accent text-[10px] font-bold uppercase tracking-widest">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-accent mr-2 animate-pulse" />
|
||||
<div className="mb-8 inline-flex items-center px-4 py-2 rounded-full bg-accent/10 border border-accent/20 text-accent text-[10px] font-black uppercase tracking-[0.2em] backdrop-blur-md">
|
||||
<span className="w-2 h-2 rounded-full bg-accent mr-3 animate-pulse" />
|
||||
{t('englishVersion')}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-wrap gap-3 mb-8">
|
||||
{product.frontmatter.categories.map((cat, idx) => (
|
||||
<Badge key={idx} variant="accent" className="bg-white/10 text-white/90 border-white/10 backdrop-blur-md px-4 py-1.5">
|
||||
<Badge key={idx} variant="accent" className="bg-white/5 text-white/80 border-white/10 backdrop-blur-md px-5 py-2 text-[10px] font-black tracking-[0.15em]">
|
||||
{cat}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
<h1 className="text-5xl md:text-7xl lg:text-8xl font-extrabold text-white mb-0 tracking-tight leading-[1.05]">
|
||||
<h1 className="text-6xl md:text-8xl lg:text-9xl font-black text-white mb-8 tracking-tighter leading-[0.9] uppercase">
|
||||
{product.frontmatter.title}
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-white/60 max-w-2xl leading-relaxed font-medium">
|
||||
{product.frontmatter.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</section>
|
||||
|
||||
<Section className="bg-neutral-light relative z-20 -mt-16 pt-0">
|
||||
<Container>
|
||||
<Section className="bg-white relative z-20 -mt-12 pt-0 rounded-t-[48px] md:rounded-t-[64px]">
|
||||
<Container className="relative">
|
||||
{/* Large Product Image Section */}
|
||||
{product.frontmatter.images && product.frontmatter.images.length > 0 && (
|
||||
<div className="relative -mt-24 mb-24 animate-slide-up" style={{ animationDelay: '200ms' }}>
|
||||
<div className="bg-white shadow-2xl border border-neutral-dark/5 overflow-hidden p-10 md:p-16 lg:p-20">
|
||||
<div className="relative -mt-32 mb-32 animate-slide-up" style={{ animationDelay: '200ms' }}>
|
||||
<div className="bg-white shadow-[0_32px_64px_-12px_rgba(0,0,0,0.1)] rounded-[48px] border border-neutral-dark/5 overflow-hidden p-12 md:p-20 lg:p-24">
|
||||
<div className="relative w-full aspect-[21/9]">
|
||||
<Image
|
||||
src={product.frontmatter.images[0]}
|
||||
@@ -250,10 +264,10 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
||||
</div>
|
||||
|
||||
{product.frontmatter.images.length > 1 && (
|
||||
<div className="flex justify-center gap-6 mt-16">
|
||||
<div className="flex justify-center gap-8 mt-20">
|
||||
{product.frontmatter.images.slice(0, 5).map((img, idx) => (
|
||||
<div key={idx} className="relative w-24 h-24 md:w-32 md:h-32 border-2 border-neutral-dark/10 rounded-xl overflow-hidden bg-neutral-light/20 hover:border-accent transition-all duration-300 cursor-pointer group">
|
||||
<Image src={img} alt="" fill className="object-cover transition-transform duration-500 group-hover:scale-110" />
|
||||
<div key={idx} className="relative w-24 h-24 md:w-32 md:h-32 border-2 border-neutral-dark/5 rounded-3xl overflow-hidden bg-neutral-light/30 hover:border-accent transition-all duration-500 cursor-pointer group p-4">
|
||||
<Image src={img} alt="" fill className="object-contain p-4 transition-transform duration-700 group-hover:scale-110" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -262,10 +276,49 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col lg:flex-row gap-16 lg:gap-24 relative items-start overflow-visible">
|
||||
<div className="flex flex-col lg:flex-row relative items-start">
|
||||
{/* Sidebar on Mobile (Above Content) */}
|
||||
<div className="w-full lg:hidden mb-20">
|
||||
<div className="space-y-10">
|
||||
{/* 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-primary-dark p-8 md:p-10 text-white relative overflow-hidden">
|
||||
<div className="absolute top-0 right-0 w-48 h-48 bg-accent/10 rounded-full -translate-y-1/2 translate-x-1/2 blur-3xl" />
|
||||
<h3 className="text-2xl md:text-3xl font-black mb-3 relative z-10 tracking-tight uppercase">{t('requestQuote')}</h3>
|
||||
<p className="text-white/50 text-base relative z-10 leading-relaxed font-medium">{t('requestQuoteDesc')}</p>
|
||||
</div>
|
||||
<div className="p-8 md:p-10">
|
||||
<RequestQuoteForm productName={product.frontmatter.title} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Datasheet Download */}
|
||||
{datasheetPath && (
|
||||
<a
|
||||
href={datasheetPath}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="block bg-neutral-light/30 rounded-[40px] border border-neutral-dark/5 overflow-hidden group hover:bg-white hover:shadow-2xl transition-all duration-700"
|
||||
>
|
||||
<div className="p-8 md:p-10 flex items-center gap-8">
|
||||
<div className="w-20 h-20 rounded-3xl bg-white shadow-sm flex items-center justify-center flex-shrink-0 group-hover:bg-accent group-hover:text-white transition-all duration-700 text-accent">
|
||||
<svg className="w-10 h-10" 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-xl font-black text-primary mb-2 uppercase tracking-tight">{t('downloadDatasheet')}</h3>
|
||||
<p className="text-text-secondary text-sm font-medium leading-relaxed">{t('downloadDatasheetDesc')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 w-full">
|
||||
{/* Main Content Area */}
|
||||
<div className="prose prose-lg md:prose-xl prose-slate max-w-none prose-headings:text-primary prose-headings:font-extrabold prose-a:text-primary prose-strong:text-primary prose-img:rounded-3xl prose-img:shadow-2xl">
|
||||
<div className="max-w-none">
|
||||
<MDXRemote source={product.content} components={components} />
|
||||
</div>
|
||||
|
||||
@@ -293,71 +346,22 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Related Products */}
|
||||
<RelatedProducts
|
||||
currentSlug={productSlug}
|
||||
categories={product.frontmatter.categories}
|
||||
locale={locale}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="w-full lg:w-[450px] xl:w-[500px] lg:sticky lg:top-32">
|
||||
<div className="lg:translate-x-12 xl:translate-x-20">
|
||||
{/* Request Quote Form */}
|
||||
<div className="bg-white rounded-3xl shadow-2xl border border-neutral-dark/5 overflow-hidden">
|
||||
<div className="bg-primary-dark p-6 md:p-8 text-white relative overflow-hidden">
|
||||
<div className="absolute top-0 right-0 w-40 h-40 bg-accent/10 rounded-full -translate-y-1/2 translate-x-1/2 blur-3xl" />
|
||||
|
||||
{/* Product Thumbnail for Sticky State */}
|
||||
{product.frontmatter.images?.[0] && (
|
||||
<div className="relative w-full aspect-[16/9] mb-6 rounded-xl overflow-hidden bg-white/10 backdrop-blur-md p-3 border border-white/10 z-10">
|
||||
<Image
|
||||
src={product.frontmatter.images[0]}
|
||||
alt=""
|
||||
fill
|
||||
className="object-contain p-1"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<ProductSidebar
|
||||
productName={product.frontmatter.title}
|
||||
productImage={product.frontmatter.images?.[0]}
|
||||
datasheetPath={datasheetPath}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3 className="text-xl md:text-2xl font-extrabold mb-2 relative z-10 tracking-tight">{t('requestQuote')}</h3>
|
||||
<p className="text-white/60 text-sm relative z-10 leading-relaxed">{t('requestQuoteDesc')}</p>
|
||||
</div>
|
||||
<div className="p-6 md:p-8">
|
||||
<RequestQuoteForm productName={product.frontmatter.title} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Datasheet Download */}
|
||||
{datasheetPath && (
|
||||
<div className="mt-8 bg-white rounded-3xl shadow-xl border border-neutral-dark/5 overflow-hidden group hover:shadow-2xl transition-all duration-500">
|
||||
<div className="p-6 md:p-8 flex items-center gap-6">
|
||||
<div className="w-16 h-16 rounded-2xl bg-accent/10 flex items-center justify-center flex-shrink-0 group-hover:bg-accent group-hover:text-white transition-colors duration-500 text-accent">
|
||||
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} 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-bold text-primary mb-1">{t('downloadDatasheet')}</h3>
|
||||
<p className="text-text-secondary text-sm mb-4">{t('downloadDatasheetDesc')}</p>
|
||||
<a
|
||||
href={datasheetPath}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center text-accent font-bold hover:text-accent-dark transition-colors"
|
||||
>
|
||||
<span>{t('downloadDatasheet')}</span>
|
||||
<svg className="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* Related Products Section */}
|
||||
<div className="mt-32 pt-32">
|
||||
<RelatedProducts
|
||||
currentSlug={productSlug}
|
||||
categories={product.frontmatter.categories}
|
||||
locale={locale}
|
||||
/>
|
||||
</div>
|
||||
</Container>
|
||||
</Section>
|
||||
|
||||
91
components/ProductSidebar.tsx
Normal file
91
components/ProductSidebar.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } 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 [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
// Show sidebar after scrolling down 400px (approx height of hero)
|
||||
if (window.scrollY > 400) {
|
||||
setIsVisible(true);
|
||||
} else {
|
||||
setIsVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
// Check initial scroll position
|
||||
handleScroll();
|
||||
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, []);
|
||||
|
||||
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'
|
||||
}`}
|
||||
>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
@@ -7,14 +7,17 @@ interface ProductTabsProps {
|
||||
|
||||
export default function ProductTabs({ children, technicalData }: ProductTabsProps) {
|
||||
return (
|
||||
<div className="space-y-12">
|
||||
<div className="prose max-w-none">
|
||||
<div className="space-y-24">
|
||||
<div className="max-w-none">
|
||||
{children}
|
||||
</div>
|
||||
|
||||
{technicalData && (
|
||||
<div className="pt-8 border-t border-neutral-dark">
|
||||
<h2 className="text-2xl font-bold text-primary-dark mb-6">Technical Specifications</h2>
|
||||
<div className="pt-24 border-t-2 border-neutral-dark/5">
|
||||
<div className="mb-16">
|
||||
<h2 className="text-4xl md:text-5xl font-black text-primary tracking-tighter uppercase mb-4">Technical Specifications</h2>
|
||||
<div className="h-1.5 w-24 bg-accent rounded-full" />
|
||||
</div>
|
||||
<div className="not-prose">
|
||||
{technicalData}
|
||||
</div>
|
||||
|
||||
@@ -25,16 +25,19 @@ export default function ProductTechnicalData({ data }: ProductTechnicalDataProps
|
||||
const { technicalItems = [], voltageTables = [] } = data;
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-16">
|
||||
{technicalItems.length > 0 && (
|
||||
<div className="bg-neutral-light p-6 rounded-lg shadow-sm">
|
||||
<h3 className="text-xl font-semibold mb-4">General Data</h3>
|
||||
<dl className="grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-4">
|
||||
<div className="bg-white p-8 md:p-12 rounded-[32px] shadow-sm border border-neutral-dark/5">
|
||||
<h3 className="text-2xl font-bold text-primary mb-8 flex items-center gap-3">
|
||||
<div className="w-2 h-8 bg-accent rounded-full" />
|
||||
General Data
|
||||
</h3>
|
||||
<dl className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-x-12 gap-y-8">
|
||||
{technicalItems.map((item, idx) => (
|
||||
<div key={idx} className="flex flex-col border-b border-neutral-dark pb-2 last:border-0">
|
||||
<dt className="text-sm text-text-secondary">{item.label}</dt>
|
||||
<dd className="text-base font-medium text-text-primary">
|
||||
{item.value} {item.unit && <span className="text-sm text-text-secondary ml-1">{item.unit}</span>}
|
||||
<div key={idx} className="flex flex-col group">
|
||||
<dt className="text-sm font-bold uppercase tracking-widest text-primary/40 mb-2 group-hover:text-accent transition-colors">{item.label}</dt>
|
||||
<dd className="text-lg font-semibold text-text-primary">
|
||||
{item.value} {item.unit && <span className="text-sm font-normal text-text-secondary ml-1">{item.unit}</span>}
|
||||
</dd>
|
||||
</div>
|
||||
))}
|
||||
@@ -43,46 +46,47 @@ export default function ProductTechnicalData({ data }: ProductTechnicalDataProps
|
||||
)}
|
||||
|
||||
{voltageTables.map((table, idx) => (
|
||||
<div key={idx} className="bg-neutral-light p-6 rounded-lg shadow-sm overflow-hidden">
|
||||
<h3 className="text-xl font-semibold mb-4">
|
||||
<div key={idx} className="bg-white p-8 md:p-12 rounded-[32px] shadow-sm border border-neutral-dark/5 overflow-hidden">
|
||||
<h3 className="text-2xl font-bold text-primary mb-8 flex items-center gap-3">
|
||||
<div className="w-2 h-8 bg-accent rounded-full" />
|
||||
{table.voltageLabel !== 'Voltage unknown' && table.voltageLabel !== 'Spannung unbekannt'
|
||||
? table.voltageLabel
|
||||
: 'Technical Specifications'}
|
||||
</h3>
|
||||
|
||||
{table.metaItems.length > 0 && (
|
||||
<dl className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 mb-6 bg-neutral p-4 rounded">
|
||||
<dl className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-8 mb-12 bg-neutral-light/50 p-8 rounded-2xl border border-neutral-dark/5">
|
||||
{table.metaItems.map((item, mIdx) => (
|
||||
<div key={mIdx}>
|
||||
<dt className="text-xs text-text-secondary uppercase tracking-wider">{item.label}</dt>
|
||||
<dd className="font-medium">{item.value} {item.unit}</dd>
|
||||
<dt className="text-[10px] font-black uppercase tracking-[0.2em] text-primary/40 mb-1">{item.label}</dt>
|
||||
<dd className="font-bold text-primary">{item.value} {item.unit}</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
)}
|
||||
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full divide-y divide-neutral-dark">
|
||||
<thead className="bg-neutral">
|
||||
<div className="overflow-x-auto -mx-8 md:-mx-12 px-8 md:px-12">
|
||||
<table className="min-w-full border-separate border-spacing-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" className="px-3 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider sticky left-0 bg-neutral z-10">
|
||||
Configuration
|
||||
<th scope="col" className="px-3 py-3 text-left text-[10px] font-black text-primary/40 uppercase tracking-[0.2em] sticky left-0 bg-white z-10 border-b border-neutral-dark/10">
|
||||
Config.
|
||||
</th>
|
||||
{table.columns.map((col, cIdx) => (
|
||||
<th key={cIdx} scope="col" className="px-3 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider whitespace-nowrap">
|
||||
<th key={cIdx} scope="col" className="px-3 py-3 text-left text-[10px] font-black text-primary/40 uppercase tracking-[0.2em] whitespace-nowrap border-b border-neutral-dark/10">
|
||||
{col.label}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-neutral-dark">
|
||||
<tbody className="divide-y divide-neutral-dark/5">
|
||||
{table.rows.map((row, rIdx) => (
|
||||
<tr key={rIdx} className="hover:bg-neutral-light transition-colors">
|
||||
<td className="px-3 py-3 text-sm font-medium text-text-primary sticky left-0 bg-white z-10 whitespace-nowrap">
|
||||
<tr key={rIdx} className="hover:bg-neutral-light/50 transition-colors group">
|
||||
<td className="px-3 py-2 text-xs font-bold text-primary sticky left-0 bg-white group-hover:bg-neutral-light/50 z-10 whitespace-nowrap">
|
||||
{row.configuration}
|
||||
</td>
|
||||
{row.cells.map((cell, cellIdx) => (
|
||||
<td key={cellIdx} className="px-3 py-3 text-sm text-text-secondary whitespace-nowrap">
|
||||
<td key={cellIdx} className="px-3 py-2 text-xs text-text-secondary whitespace-nowrap">
|
||||
{cell}
|
||||
</td>
|
||||
))}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user