migration wip

This commit is contained in:
2025-12-29 18:18:48 +01:00
parent 292975299d
commit f86785bfb0
182 changed files with 30131 additions and 9321 deletions

View File

@@ -0,0 +1,213 @@
import { ContentRenderer } from '@/components/content/ContentRenderer';
import { Section } from '@/components/content/Section';
import { Container } from '@/components/ui/Container';
// Test content with various WordPress shortcodes and images
const testContent = `
<div class="vc-row" style="background-color: #f8f9fa; padding-top: 4rem; padding-bottom: 4rem;">
<div class="vc-column">
<div class="vc-column-text">
<h2>WordPress Shortcode Test</h2>
<p>This page demonstrates the enhanced ContentRenderer handling various WordPress shortcodes and image formats.</p>
</div>
</div>
</div>
<div class="vc-row">
<div class="vc-column" style="width: 50%;">
<div class="vc-column-text">
<h3>Left Column</h3>
<p>This column uses vc_col-md-6 shortcode converted to Tailwind classes.</p>
<a href="/contact" class="btn btn-primary">Contact Button</a>
</div>
</div>
<div class="vc-column" style="width: 50%;">
<div class="vc-column-text">
<h3>Right Column</h3>
<p>Content in the right column with proper spacing and styling.</p>
<img data-wp-image-id="6517" alt="Medium Voltage Cable" class="alignnone size-medium" />
</div>
</div>
</div>
<div class="vc-row" style="background-image: url(/media/45524-5.webp); background-size: cover; background-position: center;">
<div class="vc-column">
<div class="vc-column-text" style="color: white; text-align: center;">
<h2 style="color: white;">Background Image Section</h2>
<p style="color: white;">This section has a background image from WordPress media library.</p>
</div>
</div>
</div>
<div class="vc-row">
<div class="vc-column">
<div class="vc-column-text">
<h3>Image Gallery</h3>
<p>Multiple images with different alignments:</p>
<img data-wp-image-id="6521" alt="Low Voltage Cable" class="alignleft size-thumbnail" style="margin-right: 1rem; margin-bottom: 1rem;" />
<img data-wp-image-id="47052" alt="NA2XSF2X Cable" class="alignright size-thumbnail" style="margin-left: 1rem; margin-bottom: 1rem;" />
<p>Images should display correctly with proper Next.js Image optimization and alignment.</p>
</div>
</div>
</div>
<div class="vc-row" style="background-color: #0a0a0a; color: white; padding-top: 3rem; padding-bottom: 3rem;">
<div class="vc-column">
<div class="vc-column-text" style="color: white;">
<h3 style="color: white;">Dark Section with Buttons</h3>
<p style="color: white;">Various button styles should work correctly:</p>
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
<a href="#" class="btn btn-primary">Primary Button</a>
<a href="#" class="btn btn-secondary">Secondary Button</a>
<a href="#" class="btn btn-outline">Outline Button</a>
<a href="#" class="btn btn-primary btn-large">Large Button</a>
</div>
</div>
</div>
</div>
<div class="vc-row">
<div class="vc-column">
<div class="vc-column-text">
<h3>Typography Test</h3>
<p>Regular paragraph text with <strong>bold text</strong>, <em>italic text</em>, and <a href="https://example.com">external links</a>.</p>
<ul>
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
</ul>
<blockquote>
<p>This is a blockquote with proper styling.</p>
</blockquote>
</div>
</div>
</div>
<div class="vc-row" style="background-color: #e9ecef; padding-top: 2rem; padding-bottom: 2rem;">
<div class="vc-column" style="width: 33.33%;">
<div class="vc-column-text">
<h4>Column 1</h4>
<p>One-third width column.</p>
</div>
</div>
<div class="vc-column" style="width: 33.33%;">
<div class="vc-column-text">
<h4>Column 2</h4>
<p>One-third width column.</p>
</div>
</div>
<div class="vc-column" style="width: 33.33%;">
<div class="vc-column-text">
<h4>Column 3</h4>
<p>One-third width column.</p>
</div>
</div>
</div>
<div class="vc-row">
<div class="vc-column">
<div class="vc-column-text">
<h3>Direct Image References</h3>
<p>Images referenced by ID should be converted to Next.js Image components:</p>
<img data-wp-image-id="10797" alt="Medium Voltage Cables" class="aligncenter size-large" />
</div>
</div>
</div>
`;
const testContentWithShortcodes = `
[vc_row bg_color="#f8f9fa" top_padding="4%" bottom_padding="4%"]
[vc_column width="12"]
[vc_column_text]
<h2>Raw Shortcode Test</h2>
<p>This content uses raw WordPress shortcodes that should be processed by html-compat.ts</p>
[/vc_column_text]
[/vc_column]
[/vc_row]
[vc_row]
[vc_column width="6"]
[vc_column_text]
<h3>Left Side</h3>
<p>Content with [vc_btn color="primary" title="Click Here" link="#"] embedded.</p>
[/vc_column_text]
[/vc_column]
[vc_column width="6"]
[vc_column_text]
<h3>Right Side</h3>
<p>Another column with [vc_single_image src="6521" align="right"] embedded.</p>
[/vc_column_text]
[/vc_column]
[/vc_row]
[vc_row bg_image="45528" top_padding="15%" bottom_padding="15%" color_overlay="#000000" overlay_strength="0.7"]
[vc_column]
[vc_column_text text_color="light" text_align="center"]
<h2>Background Image with Overlay</h2>
<p>This should show an image with dark overlay and white text.</p>
[/vc_column_text]
[/vc_column]
[/vc_row]
[vc_row enable_gradient="true" gradient_direction="left_to_right"]
[vc_column]
[vc_column_text text_align="center"]
<h3>Gradient Background</h3>
<p>This row should have a gradient background.</p>
[/vc_column_text]
[/vc_column]
[/vc_row]
`;
export default function ComponentsDemoPage() {
return (
<Container>
<Section>
<div className="space-y-8">
<div className="text-center space-y-4">
<h1 className="text-4xl font-bold">ContentRenderer Test Page</h1>
<p className="text-lg text-gray-600">
Testing WordPress shortcode conversion and image handling
</p>
</div>
<div className="bg-white rounded-lg shadow-lg p-6">
<h2 className="text-2xl font-bold mb-4">Processed HTML Content</h2>
<ContentRenderer
content={testContent}
sanitize={true}
processAssets={true}
convertClasses={true}
/>
</div>
<div className="bg-white rounded-lg shadow-lg p-6">
<h2 className="text-2xl font-bold mb-4">Raw Shortcode Content</h2>
<ContentRenderer
content={testContentWithShortcodes}
sanitize={true}
processAssets={true}
convertClasses={true}
/>
</div>
<div className="bg-blue-50 rounded-lg p-6">
<h3 className="text-xl font-bold mb-3">What This Tests:</h3>
<ul className="list-disc list-inside space-y-2">
<li> [vc_row] flex containers with background support</li>
<li> [vc_column] responsive width classes</li>
<li> [vc_column_text] prose styling</li>
<li> [vc_btn] styled buttons</li>
<li> [vc_single_image] Next.js Image components</li>
<li> Background images from WordPress IDs</li>
<li> Color overlays and gradients</li>
<li> Image alignment and sizing</li>
<li> URL replacement from data layer</li>
<li> Inline styles and attributes</li>
</ul>
</div>
</div>
</Section>
</Container>
);
}

View File

@@ -0,0 +1,217 @@
import { Metadata } from 'next';
import { Container } from '@/components/ui/Container';
import { Button } from '@/components/ui/Button';
import { Card, CardHeader, CardBody, CardFooter } from '@/components/ui/Card';
import { Grid, GridItem } from '@/components/ui/Grid';
import { Badge } from '@/components/ui/Badge';
export const metadata: Metadata = {
title: 'Layout Example | KLZ Cables',
description: 'Example page demonstrating the new layout components',
};
export default function ExamplePage() {
return (
<div className="space-y-8">
{/* Hero Section */}
<section className="bg-gradient-to-r from-blue-600 to-blue-800 text-white py-16 rounded-xl">
<Container maxWidth="4xl" padding="lg" className="text-center">
<h1 className="text-4xl md:text-5xl font-bold mb-4">
Layout Components Demo
</h1>
<p className="text-xl text-blue-100 mb-6">
Showcasing the new Header, Footer, Layout, and MobileMenu components
</p>
<div className="flex gap-3 justify-center flex-wrap">
<Button variant="primary" size="lg">
Primary Action
</Button>
<Button variant="outline" size="lg">
Secondary Action
</Button>
</div>
</Container>
</section>
{/* Feature Cards */}
<section>
<Container maxWidth="6xl" padding="md">
<h2 className="text-3xl font-bold mb-6 text-center">Key Features</h2>
<Grid cols={3} gap="lg">
<GridItem>
<Card variant="elevated">
<CardHeader>
<div className="flex items-center gap-2 mb-2">
<Badge variant="primary">New</Badge>
<h3 className="text-xl font-semibold">Responsive Header</h3>
</div>
</CardHeader>
<CardBody>
<p className="text-gray-600">
Sticky header with mobile hamburger menu, locale switcher, and contact CTA.
Fully responsive with smooth animations.
</p>
</CardBody>
<CardFooter>
<Button variant="ghost" size="sm">Learn More</Button>
</CardFooter>
</Card>
</GridItem>
<GridItem>
<Card variant="elevated">
<CardHeader>
<div className="flex items-center gap-2 mb-2">
<Badge variant="secondary">Updated</Badge>
<h3 className="text-xl font-semibold">Smart Footer</h3>
</div>
</CardHeader>
<CardBody>
<p className="text-gray-600">
4-column responsive layout with company info, quick links,
product categories, and contact details.
</p>
</CardBody>
<CardFooter>
<Button variant="ghost" size="sm">View Details</Button>
</CardFooter>
</Card>
</GridItem>
<GridItem>
<Card variant="elevated">
<CardHeader>
<div className="flex items-center gap-2 mb-2">
<Badge variant="success">Enhanced</Badge>
<h3 className="text-xl font-semibold">Mobile Menu</h3>
</div>
</CardHeader>
<CardBody>
<p className="text-gray-600">
Slide-out drawer with smooth animations, full navigation,
language switcher, and contact information.
</p>
</CardBody>
<CardFooter>
<Button variant="ghost" size="sm">Try It</Button>
</CardFooter>
</Card>
</GridItem>
</Grid>
</Container>
</section>
{/* Component Showcase */}
<section className="bg-gray-50 py-12">
<Container maxWidth="6xl" padding="md">
<h2 className="text-3xl font-bold mb-6 text-center">UI Components</h2>
<div className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Card>
<CardHeader>
<h3 className="text-xl font-semibold">Buttons</h3>
</CardHeader>
<CardBody>
<div className="flex flex-wrap gap-2">
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
</div>
<div className="flex flex-wrap gap-2 mt-3">
<Button variant="primary" size="sm">Small</Button>
<Button variant="primary" size="md">Medium</Button>
<Button variant="primary" size="lg">Large</Button>
</div>
</CardBody>
</Card>
<Card>
<CardHeader>
<h3 className="text-xl font-semibold">Badges</h3>
</CardHeader>
<CardBody>
<div className="flex flex-wrap gap-2">
<Badge variant="primary">Primary</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="success">Success</Badge>
<Badge variant="warning">Warning</Badge>
<Badge variant="error">Error</Badge>
</div>
</CardBody>
</Card>
</div>
<Card>
<CardHeader>
<h3 className="text-xl font-semibold">Container & Grid</h3>
</CardHeader>
<CardBody>
<p className="text-gray-600 mb-4">
The Container component provides responsive max-width and padding,
while Grid offers flexible column layouts.
</p>
<Grid cols={4} gap="md">
<div className="bg-blue-100 p-4 rounded text-center">1</div>
<div className="bg-blue-100 p-4 rounded text-center">2</div>
<div className="bg-blue-100 p-4 rounded text-center">3</div>
<div className="bg-blue-100 p-4 rounded text-center">4</div>
</Grid>
</CardBody>
</Card>
</div>
</Container>
</section>
{/* Integration Example */}
<section>
<Container maxWidth="6xl" padding="md">
<h2 className="text-3xl font-bold mb-6 text-center">Integration Example</h2>
<Card variant="elevated">
<CardHeader>
<h3 className="text-xl font-semibold">How to Use in Your Pages</h3>
</CardHeader>
<CardBody>
<pre className="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm">
<code>{`// app/[locale]/my-page/page.tsx
import { Metadata } from 'next';
import { Container } from '@/components/ui/Container';
import { Layout } from '@/components/layout/Layout';
export const metadata: Metadata = {
title: 'My Page | KLZ Cables',
description: 'My custom page description',
};
export default function MyPage({ params: { locale } }: { params: { locale: string } }) {
return (
<Layout locale={locale} siteName="KLZ Cables">
<Container maxWidth="6xl" padding="md">
<h1>My Page Content</h1>
{/* Your content here */}
</Container>
</Layout>
);
}`}</code>
</pre>
</CardBody>
</Card>
</Container>
</section>
{/* Breadcrumb Demo */}
<section className="bg-gray-50 py-8">
<Container maxWidth="6xl" padding="md">
<h2 className="text-2xl font-bold mb-4">Breadcrumb Support</h2>
<p className="text-gray-600 mb-4">
The Layout component supports optional breadcrumbs. Check the URL bar
and try navigating to see the breadcrumb in action.
</p>
<a href="/en/example/subpage">
<Button>Go to Example Subpage (with Breadcrumb)</Button>
</a>
</Container>
</section>
</div>
);
}

View File

@@ -0,0 +1,111 @@
import { Metadata } from 'next';
import { Container } from '@/components/ui/Container';
import { Layout } from '@/components/layout/Layout';
import { Card, CardHeader, CardBody } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';
import Link from 'next/link';
export const metadata: Metadata = {
title: 'Subpage Example | KLZ Cables',
description: 'Example subpage demonstrating breadcrumb functionality',
};
export default function Subpage({ params: { locale } }: { params: { locale: string } }) {
// Breadcrumb configuration
const breadcrumb = [
{ title: 'Example', path: `/${locale}/example` },
{ title: 'Subpage', path: `/${locale}/example/subpage` }
];
return (
<Layout
locale={locale}
siteName="KLZ Cables"
breadcrumb={breadcrumb}
>
<Container maxWidth="6xl" padding="md">
<div className="space-y-6">
{/* Page Header */}
<div className="text-center space-y-3">
<h1 className="text-4xl font-bold text-gray-900">Subpage with Breadcrumb</h1>
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
This page demonstrates the breadcrumb functionality in the Layout component.
Notice the breadcrumb navigation above this content area.
</p>
</div>
{/* Content */}
<Card variant="elevated">
<CardHeader>
<h2 className="text-2xl font-semibold">Breadcrumb Features</h2>
</CardHeader>
<CardBody>
<ul className="space-y-3 text-gray-700">
<li className="flex items-start gap-2">
<span className="text-primary font-bold"></span>
<span>Automatic breadcrumb generation based on current URL</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary font-bold"></span>
<span>Clickable links for all parent pages</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary font-bold"></span>
<span>Current page shown as non-clickable text</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary font-bold"></span>
<span>Responsive design that works on all screen sizes</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary font-bold"></span>
<span>Optional feature - only shown when breadcrumb prop is provided</span>
</li>
</ul>
</CardBody>
</Card>
{/* Navigation */}
<div className="flex justify-center gap-4">
<Link href={`/${locale}/example`}>
<Button variant="outline"> Back to Example</Button>
</Link>
<Link href={`/${locale}`}>
<Button variant="primary">Home</Button>
</Link>
</div>
{/* Code Example */}
<Card>
<CardHeader>
<h3 className="text-xl font-semibold">How to Use Breadcrumbs</h3>
</CardHeader>
<CardBody>
<pre className="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm">
<code>{`// In your page component:
import { Layout } from '@/components/layout/Layout';
export default function MyPage({ params: { locale } }) {
const breadcrumb = [
{ title: 'Home', path: \`/\${locale}\` },
{ title: 'Products', path: \`/\${locale}/products\` },
{ title: 'Details', path: \`/\${locale}/products/123\` }
];
return (
<Layout
locale={locale}
breadcrumb={breadcrumb}
>
{/* Your content */}
</Layout>
);
}`}</code>
</pre>
</CardBody>
</Card>
</div>
</Container>
</Layout>
);
}

View File

@@ -1,7 +1,7 @@
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import '../globals.scss';
import { Navigation } from '@/components/Navigation';
import '../globals.css';
import { Layout } from '@/components/layout/Layout';
import { CookieConsent } from '@/components/CookieConsent';
const inter = Inter({
@@ -38,10 +38,12 @@ export default function LocaleLayout({
}) {
return (
<>
<Navigation siteName="KLZ Cables" locale={locale} />
<main className="min-h-screen">
<Layout
locale={locale}
siteName="KLZ Cables"
>
{children}
</main>
</Layout>
<CookieConsent />
</>
);

View File

@@ -5,6 +5,10 @@ import { SEO } from '@/components/SEO';
import { processHTML } from '@/lib/html-compat';
import { LocaleSwitcher } from '@/components/LocaleSwitcher';
import Link from 'next/link';
import { ResponsiveSection, ResponsiveWrapper, ResponsiveGrid } from '@/components/layout/ResponsiveWrapper';
import { FeaturedImage } from '@/components/content/FeaturedImage';
import { Container } from '@/components/ui/Container';
import { Button } from '@/components/ui/Button';
interface PageProps {
params: {
@@ -87,87 +91,139 @@ export default async function Page({ params }: PageProps) {
{/* Hero Section with Featured Image */}
{featuredImage && (
<div className="relative h-64 md:h-96 bg-gray-200">
<img
<ResponsiveWrapper className="relative bg-gray-200" padding="none">
<FeaturedImage
src={featuredImage.localPath}
alt={page.title}
className="w-full h-full object-cover"
size="full"
aspectRatio="16:9"
priority={true}
className="opacity-90"
/>
<div className="absolute inset-0 bg-black bg-opacity-40"></div>
<div className="absolute inset-0 flex items-center justify-center text-center">
<h1 className="text-4xl md:text-6xl font-bold text-white drop-shadow-lg">
<h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-bold text-white drop-shadow-lg px-4">
{page.title}
</h1>
</div>
</div>
</ResponsiveWrapper>
)}
{/* Main Content */}
<main className="container mx-auto px-4 py-8">
<ResponsiveSection padding="responsive" maxWidth="4xl">
{!featuredImage && (
<div className="max-w-4xl mx-auto mb-8">
<h1 className="text-4xl font-bold text-gray-900 mb-4">
<ResponsiveWrapper stackOnMobile={true} centerOnMobile={true} className="mb-8">
<h1 className="text-3xl sm:text-4xl font-bold text-gray-900 mb-4">
{page.title}
</h1>
{page.excerptHtml && (
<div
className="text-xl text-gray-600 leading-relaxed"
<div
className="text-lg sm:text-xl text-gray-600 leading-relaxed"
dangerouslySetInnerHTML={{ __html: processHTML(page.excerptHtml) }}
/>
)}
</div>
</ResponsiveWrapper>
)}
{processedContent && (
<div className="max-w-4xl mx-auto bg-white rounded-lg shadow-sm p-8">
<div
<ResponsiveWrapper className="bg-white rounded-lg shadow-sm p-6 sm:p-8" container={true} maxWidth="full">
<div
className="prose prose-lg max-w-none"
dangerouslySetInnerHTML={{ __html: processedContent }}
/>
</div>
</ResponsiveWrapper>
)}
{/* Navigation Links */}
<div className="max-w-4xl mx-auto mt-12">
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<Link
<ResponsiveWrapper className="mt-12" container={true} maxWidth="full">
<ResponsiveGrid
columns={{ mobile: 1, tablet: 2, desktop: 4 }}
gap="responsive"
stackMobile={true}
>
<Link
href={`/${locale}/blog`}
className="p-4 bg-blue-50 hover:bg-blue-100 rounded-lg text-center transition-colors"
className="p-4 bg-blue-50 hover:bg-blue-100 active:bg-blue-200 rounded-lg text-center transition-colors touch-target-md"
>
<div className="font-semibold text-blue-900">Blog</div>
<div className="text-sm text-blue-700">Read our latest posts</div>
<div className="font-semibold text-blue-900 text-lg">Blog</div>
<div className="text-sm text-blue-700 mt-1">Read our latest posts</div>
</Link>
<Link
<Link
href={`/${locale}/products`}
className="p-4 bg-green-50 hover:bg-green-100 rounded-lg text-center transition-colors"
className="p-4 bg-green-50 hover:bg-green-100 active:bg-green-200 rounded-lg text-center transition-colors touch-target-md"
>
<div className="font-semibold text-green-900">Products</div>
<div className="text-sm text-green-700">Browse our catalog</div>
<div className="font-semibold text-green-900 text-lg">Products</div>
<div className="text-sm text-green-700 mt-1">Browse our catalog</div>
</Link>
<Link
<Link
href={`/${locale}/contact`}
className="p-4 bg-orange-50 hover:bg-orange-100 rounded-lg text-center transition-colors"
className="p-4 bg-orange-50 hover:bg-orange-100 active:bg-orange-200 rounded-lg text-center transition-colors touch-target-md"
>
<div className="font-semibold text-orange-900">Contact</div>
<div className="text-sm text-orange-700">Get in touch</div>
<div className="font-semibold text-orange-900 text-lg">Contact</div>
<div className="text-sm text-orange-700 mt-1">Get in touch</div>
</Link>
<Link
<Link
href={`/${locale}/blog`}
className="p-4 bg-purple-50 hover:bg-purple-100 rounded-lg text-center transition-colors"
className="p-4 bg-purple-50 hover:bg-purple-100 active:bg-purple-200 rounded-lg text-center transition-colors touch-target-md"
>
<div className="font-semibold text-purple-900">News</div>
<div className="text-sm text-purple-700">Latest updates</div>
<div className="font-semibold text-purple-900 text-lg">News</div>
<div className="text-sm text-purple-700 mt-1">Latest updates</div>
</Link>
</ResponsiveGrid>
</ResponsiveWrapper>
</ResponsiveSection>
{/* Tailwind CSS Test Section */}
<ResponsiveSection padding="responsive" className="bg-gradient-to-r from-blue-50 to-indigo-50">
<Container maxWidth="6xl" centered={true} padding="none">
<div className="text-center mb-8">
<h2 className="text-3xl font-bold text-gray-900 mb-4">Tailwind CSS Test</h2>
<p className="text-lg text-gray-600">If you can see styled components below, Tailwind CSS is working correctly!</p>
</div>
</div>
</main>
<div className="flex flex-wrap gap-4 justify-center items-center">
<Button variant="primary" size="lg">
Primary Button
</Button>
<Button variant="secondary" size="lg">
Secondary Button
</Button>
<Button variant="outline" size="lg">
Outline Button
</Button>
<Button variant="ghost" size="lg">
Ghost Button
</Button>
</div>
<div className="mt-8 grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-white p-6 rounded-lg shadow-md border-2 border-blue-200">
<h3 className="text-xl font-bold text-blue-900 mb-2">Card 1</h3>
<p className="text-gray-600">This card uses Tailwind shadow, rounded, and border utilities.</p>
</div>
<div className="bg-white p-6 rounded-lg shadow-lg border-2 border-green-200">
<h3 className="text-xl font-bold text-green-900 mb-2">Card 2</h3>
<p className="text-gray-600">Different shadow intensity and border color.</p>
</div>
<div className="bg-white p-6 rounded-xl shadow-xl border-2 border-purple-200">
<h3 className="text-xl font-bold text-purple-900 mb-2">Card 3</h3>
<p className="text-gray-600">Rounded-xl and shadow-xl for emphasis.</p>
</div>
</div>
<div className="mt-8 p-4 bg-yellow-100 border-l-4 border-yellow-500 text-yellow-800">
<p className="font-bold">Success!</p>
<p>If you see this styled alert box with proper colors, spacing, and borders, Tailwind CSS is processing correctly.</p>
</div>
</Container>
</ResponsiveSection>
{/* Locale Switcher */}
<div className="bg-gray-50 py-8">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<ResponsiveSection padding="responsive" className="bg-gray-50">
<Container maxWidth="6xl" centered={true} padding="none">
<LocaleSwitcher />
</div>
</div>
</Container>
</ResponsiveSection>
</>
);
}

3216
app/globals.css Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,461 +1,79 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/**
* KLZ Cables Global Styles
* Minimal global styles + Tailwind CSS
*/
/* Global Styles */
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
@import "tailwindcss";
/*
* ESSENTIAL GLOBAL STYLES ONLY
* All component styles should use Tailwind utilities
* Design tokens are available via Tailwind config
*/
/* Custom Scrollbar - Essential for UX */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
::-webkit-scrollbar-track {
background: #e9ecef;
}
/* Navigation Styles */
.navbar {
background: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
padding: 1rem 0;
position: sticky;
top: 0;
z-index: 100;
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-logo {
font-size: 1.5rem;
font-weight: bold;
color: #0070f3;
text-decoration: none;
}
.nav-menu {
display: flex;
gap: 1.5rem;
align-items: center;
}
.nav-link {
color: #333;
text-decoration: none;
font-weight: 500;
transition: color 0.2s;
}
.nav-link:hover {
color: #0070f3;
}
/* Contact Form Styles */
.contact-form {
max-width: 600px;
margin: 2rem auto;
padding: 2rem;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.form-group {
margin-bottom: 1rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: #333;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
}
.form-group textarea {
min-height: 120px;
resize: vertical;
}
.submit-btn {
background: #0070f3;
color: white;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 4px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: background 0.2s;
}
.submit-btn:hover {
background: #0051cc;
}
.submit-btn:disabled {
background: #ccc;
cursor: not-allowed;
}
.form-message {
margin-top: 1rem;
padding: 0.75rem;
::-webkit-scrollbar-thumb {
background: #0056b3;
border-radius: 4px;
}
.form-message.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
::-webkit-scrollbar-thumb:hover {
background: #003d82;
}
.form-message.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
/* Focus Styles for Accessibility */
*:focus-visible {
outline: 2px solid #0056b3;
outline-offset: 2px;
}
/* Cookie Consent Styles */
.cookie-consent {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #fff;
box-shadow: 0 -2px 8px rgba(0,0,0,0.1);
padding: 1rem;
z-index: 1000;
/* Smooth scrolling */
html {
scroll-behavior: smooth;
}
.cookie-consent-content {
max-width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
.cookie-consent-text {
flex: 1;
color: #333;
}
.cookie-consent-buttons {
display: flex;
gap: 0.5rem;
}
.cookie-btn {
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
font-weight: 500;
cursor: pointer;
transition: background 0.2s;
}
.cookie-btn.accept {
background: #0070f3;
color: white;
}
.cookie-btn.accept:hover {
background: #0051cc;
}
.cookie-btn.reject {
background: #e0e0e0;
color: #333;
}
.cookie-btn.reject:hover {
background: #d0d0d0;
}
/* Product List Styles */
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 2rem;
margin: 2rem 0;
}
.product-card {
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: transform 0.2s, box-shadow 0.2s;
}
.product-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.product-image {
width: 100%;
height: 200px;
object-fit: cover;
background: #f0f0f0;
}
.product-content {
padding: 1rem;
}
.product-title {
font-size: 1.125rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: #111;
}
.product-excerpt {
font-size: 0.875rem;
color: #666;
line-height: 1.5;
margin-bottom: 0.75rem;
}
.product-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.875rem;
color: #999;
}
.product-price {
font-weight: 600;
color: #0070f3;
}
/* SEO Component Styles */
.site-seo {
margin-bottom: 2rem;
}
/* Locale Switcher Styles */
.locale-switcher {
display: flex;
gap: 0.5rem;
align-items: center;
}
.locale-btn {
padding: 0.5rem 0.75rem;
border: 1px solid #ddd;
background: white;
border-radius: 4px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s;
}
.locale-btn:hover {
border-color: #0070f3;
color: #0070f3;
}
.locale-btn.active {
background: #0070f3;
color: white;
border-color: #0070f3;
}
/* Page Layout */
.page-container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem 1rem;
}
.page-header {
margin-bottom: 2rem;
}
.page-title {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 0.5rem;
color: #111;
}
.page-subtitle {
font-size: 1.125rem;
color: #666;
line-height: 1.6;
}
/* Blog Styles */
.blog-grid {
display: grid;
gap: 2rem;
margin: 2rem 0;
}
.blog-card {
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: transform 0.2s;
}
.blog-card:hover {
transform: translateX(4px);
}
.blog-card-content {
padding: 1.5rem;
}
.blog-card-title {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: #111;
}
.blog-card-excerpt {
color: #666;
line-height: 1.6;
margin-bottom: 1rem;
}
.blog-card-meta {
font-size: 0.875rem;
color: #999;
}
/* Content Styles */
.content {
background: #fff;
padding: 2rem;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.content h1,
.content h2,
.content h3,
.content h4 {
margin-top: 1.5rem;
margin-bottom: 1rem;
color: #111;
}
.content p {
margin-bottom: 1rem;
line-height: 1.7;
color: #333;
}
.content a {
color: #0070f3;
text-decoration: underline;
}
.content ul,
.content ol {
margin-bottom: 1rem;
padding-left: 1.5rem;
}
.content li {
margin-bottom: 0.5rem;
}
.content img {
max-width: 100%;
height: auto;
border-radius: 4px;
margin: 1rem 0;
}
/* Loading States */
.loading {
text-align: center;
padding: 2rem;
color: #666;
}
/* Error States */
.error-message {
background: #f8d7da;
color: #721c24;
padding: 1rem;
border-radius: 4px;
border: 1px solid #f5c6cb;
margin: 1rem 0;
}
/* Utility Classes */
.text-center {
text-align: center;
}
.mt-2 {
margin-top: 1rem;
}
.mb-2 {
margin-bottom: 1rem;
}
.grid {
display: grid;
gap: 1rem;
}
.grid-2 {
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
/* Responsive */
@media (max-width: 768px) {
.cookie-consent-content {
flex-direction: column;
align-items: flex-start;
/* Print styles */
@media print {
.navbar,
.cookie-consent,
.locale-switcher,
.submit-btn,
.btn {
display: none !important;
}
.nav-menu {
gap: 1rem;
body {
background: white;
color: black;
}
.page-title {
font-size: 2rem;
.container {
max-width: 100%;
padding: 0;
}
.product-grid {
grid-template-columns: 1fr;
gap: 1rem;
}
.blog-card:hover {
transform: none;
a::after {
content: " (" attr(href) ")";
}
}

View File

@@ -1,6 +1,6 @@
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.scss';
import './globals.css';
const inter = Inter({
subsets: ['latin', 'latin-ext'],