feat: complete migration to static MDX, stabilize local infrastructure and fix i18n issues
Some checks failed
🚀 Build & Deploy / 🔍 Prepare (push) Successful in 4s
🚀 Build & Deploy / 🚀 Deploy (push) Has been cancelled
🚀 Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
🚀 Build & Deploy / 🏗️ Build (push) Has been cancelled
🚀 Build & Deploy / 🔔 Notify (push) Has been cancelled
🚀 Build & Deploy / 🧪 QA (push) Has been cancelled
Some checks failed
🚀 Build & Deploy / 🔍 Prepare (push) Successful in 4s
🚀 Build & Deploy / 🚀 Deploy (push) Has been cancelled
🚀 Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
🚀 Build & Deploy / 🏗️ Build (push) Has been cancelled
🚀 Build & Deploy / 🔔 Notify (push) Has been cancelled
🚀 Build & Deploy / 🧪 QA (push) Has been cancelled
This commit is contained in:
52
components/sections/AboutHero.tsx
Normal file
52
components/sections/AboutHero.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "@/components/Reveal";
|
||||
import { TechBackground } from "@/components/TechBackground";
|
||||
import { Counter } from "@/components/Counter";
|
||||
|
||||
interface AboutHeroProps {
|
||||
tagline: string;
|
||||
title: React.ReactNode;
|
||||
subtitle: string;
|
||||
}
|
||||
|
||||
export function AboutHero({ tagline, title, subtitle }: AboutHeroProps) {
|
||||
return (
|
||||
<section className="relative min-h-[60vh] flex items-center pt-44 pb-20 overflow-hidden">
|
||||
<div className="absolute inset-0 z-0">
|
||||
<Image
|
||||
src="/media/drums/about-hero.jpg"
|
||||
alt="About MB Grid Solutions"
|
||||
fill
|
||||
className="object-cover"
|
||||
priority
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-white via-white/95 to-white/40" />
|
||||
<TechBackground />
|
||||
</div>
|
||||
|
||||
<div className="container-custom relative z-10">
|
||||
<div className="text-left relative">
|
||||
<Counter value={1} className="section-number" />
|
||||
<Reveal delay={0.1}>
|
||||
<span className="text-accent font-bold uppercase tracking-widest text-sm mb-4 block">
|
||||
{tagline}
|
||||
</span>
|
||||
</Reveal>
|
||||
<Reveal delay={0.2}>
|
||||
<h1 className="text-4xl sm:text-5xl md:text-6xl font-extrabold text-primary mb-6 md:mb-8 leading-tight">
|
||||
{title}
|
||||
</h1>
|
||||
</Reveal>
|
||||
<Reveal delay={0.3}>
|
||||
<p className="text-slate-600 text-lg md:text-2xl leading-relaxed mb-8">
|
||||
{subtitle}
|
||||
</p>
|
||||
</Reveal>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
63
components/sections/AboutIntro.tsx
Normal file
63
components/sections/AboutIntro.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Linkedin } from "lucide-react";
|
||||
import { Reveal } from "@/components/Reveal";
|
||||
import { TechBackground } from "@/components/TechBackground";
|
||||
|
||||
interface Person {
|
||||
name: string;
|
||||
role: string;
|
||||
linkedin: string;
|
||||
}
|
||||
|
||||
interface AboutIntroProps {
|
||||
paragraphs: string[];
|
||||
team: Person[];
|
||||
}
|
||||
|
||||
export function AboutIntro({ paragraphs, team }: AboutIntroProps) {
|
||||
return (
|
||||
<section className="bg-white relative overflow-hidden">
|
||||
<TechBackground />
|
||||
<div className="container-custom relative z-10">
|
||||
<div className="section-number">02</div>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||
<Reveal direction="right">
|
||||
<div className="space-y-6 text-lg text-slate-600 leading-relaxed relative">
|
||||
<div className="absolute -left-4 top-0 w-1 h-full bg-accent/10" />
|
||||
{paragraphs.map((p, i) => (
|
||||
<p key={i}>{p}</p>
|
||||
))}
|
||||
</div>
|
||||
</Reveal>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||
{team.map((person, i) => (
|
||||
<Reveal key={i} delay={i * 0.1}>
|
||||
<div className="card-modern !p-6 hover:-translate-y-1 transition-[box-shadow,transform] duration-300 relative overflow-hidden tech-card-border">
|
||||
<div className="flex justify-between items-start mb-4 relative z-10">
|
||||
<h2 className="text-xl font-bold text-primary">
|
||||
{person.name}
|
||||
</h2>
|
||||
<a
|
||||
href={person.linkedin}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-[#0077b5] hover:scale-110 transition-transform"
|
||||
aria-label={`LinkedIn Profile of ${person.name}`}
|
||||
>
|
||||
<Linkedin size={20} />
|
||||
</a>
|
||||
</div>
|
||||
<p className="text-accent text-sm font-bold uppercase tracking-wider relative z-10">
|
||||
{person.role}
|
||||
</p>
|
||||
</div>
|
||||
</Reveal>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,16 +1,30 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { m } from "framer-motion";
|
||||
import { Reveal } from "../Reveal";
|
||||
import { Counter } from "../Counter";
|
||||
import { TechBackground } from "../TechBackground";
|
||||
import { Button } from "../Button";
|
||||
import { motion } from "framer-motion";
|
||||
import { Reveal } from "@/components/Reveal";
|
||||
import { Counter } from "@/components/Counter";
|
||||
import { TechBackground } from "@/components/TechBackground";
|
||||
import { Button } from "@/components/Button";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export const CTASection = () => {
|
||||
interface CTASectionProps {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
buttonText?: string;
|
||||
}
|
||||
|
||||
export const CTASection = ({
|
||||
title,
|
||||
subtitle,
|
||||
buttonText,
|
||||
}: CTASectionProps) => {
|
||||
const t = useTranslations("Index");
|
||||
|
||||
const displayTitle = title || t("cta.title");
|
||||
const displaySubtitle = subtitle || t("cta.subtitle");
|
||||
const displayButtonText = buttonText || t("cta.button");
|
||||
|
||||
return (
|
||||
<section className="bg-white relative overflow-hidden">
|
||||
<TechBackground />
|
||||
@@ -34,7 +48,7 @@ export const CTASection = () => {
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<m.circle
|
||||
<motion.circle
|
||||
animate={{ r: [400, 410, 400], opacity: [0.1, 0.2, 0.1] }}
|
||||
transition={{
|
||||
duration: 5,
|
||||
@@ -47,7 +61,7 @@ export const CTASection = () => {
|
||||
stroke="white"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
<m.circle
|
||||
<motion.circle
|
||||
animate={{ r: [300, 310, 300], opacity: [0.1, 0.2, 0.1] }}
|
||||
transition={{
|
||||
duration: 4,
|
||||
@@ -61,7 +75,7 @@ export const CTASection = () => {
|
||||
stroke="white"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
<m.circle
|
||||
<motion.circle
|
||||
animate={{ r: [200, 210, 200], opacity: [0.1, 0.2, 0.1] }}
|
||||
transition={{
|
||||
duration: 3,
|
||||
@@ -80,10 +94,10 @@ export const CTASection = () => {
|
||||
|
||||
<div className="relative z-10">
|
||||
<h2 className="text-3xl md:text-6xl font-bold text-white mb-6 md:mb-8 leading-tight">
|
||||
{t("cta.title")}
|
||||
{displayTitle}
|
||||
</h2>
|
||||
<p className="text-slate-300 text-lg md:text-xl mb-8 md:mb-12 leading-relaxed">
|
||||
{t("cta.subtitle")}
|
||||
{displaySubtitle}
|
||||
</p>
|
||||
<Button
|
||||
href="/kontakt"
|
||||
@@ -91,7 +105,7 @@ export const CTASection = () => {
|
||||
showArrow
|
||||
className="w-full sm:w-auto !px-10 !py-5 text-lg"
|
||||
>
|
||||
{t("cta.button")}
|
||||
{displayButtonText}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,14 +3,31 @@
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import { CheckCircle2 } from "lucide-react";
|
||||
import { Reveal } from "../Reveal";
|
||||
import { Counter } from "../Counter";
|
||||
import { TechBackground } from "../TechBackground";
|
||||
import { Reveal } from "@/components/Reveal";
|
||||
import { Counter } from "@/components/Counter";
|
||||
import { TechBackground } from "@/components/TechBackground";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export const ExpertiseSection = () => {
|
||||
interface ExpertiseSectionProps {
|
||||
tag?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
groups?: string[];
|
||||
}
|
||||
|
||||
export const ExpertiseSection = ({
|
||||
tag,
|
||||
title,
|
||||
description,
|
||||
groups,
|
||||
}: ExpertiseSectionProps) => {
|
||||
const t = useTranslations("Index");
|
||||
|
||||
const displayTag = tag || t("expertise.tag");
|
||||
const displayTitle = title || t("expertise.title");
|
||||
const displayDescription = description || t("expertise.description");
|
||||
const displayGroups = groups || t.raw("expertise.groups");
|
||||
|
||||
return (
|
||||
<section className="bg-white relative overflow-hidden">
|
||||
<TechBackground />
|
||||
@@ -34,17 +51,17 @@ export const ExpertiseSection = () => {
|
||||
<div>
|
||||
<Reveal>
|
||||
<span className="text-accent font-bold uppercase tracking-widest text-sm mb-4 block">
|
||||
{t("expertise.tag")}
|
||||
{displayTag}
|
||||
</span>
|
||||
<h2 className="text-3xl md:text-5xl font-bold text-primary mb-6 md:mb-8">
|
||||
{t("expertise.title")}
|
||||
{displayTitle}
|
||||
</h2>
|
||||
<p className="text-slate-600 text-base md:text-xl mb-8 md:mb-12">
|
||||
{t("expertise.description")}
|
||||
{displayDescription}
|
||||
</p>
|
||||
</Reveal>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
{t.raw("expertise.groups").map((item: string, i: number) => (
|
||||
{displayGroups.map((item: string, i: number) => (
|
||||
<Reveal key={i} delay={i * 0.05}>
|
||||
<div className="flex items-center gap-4 p-4 bg-slate-50 rounded-xl border border-slate-100 hover:border-accent/30 transition-colors group relative overflow-hidden">
|
||||
<div className="absolute top-0 left-0 w-1 h-full bg-accent/0 group-hover:bg-accent/100 transition-all duration-300" />
|
||||
|
||||
79
components/sections/Hero.tsx
Normal file
79
components/sections/Hero.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import { Button } from "@/components/Button";
|
||||
import { Counter } from "@/components/Counter";
|
||||
import { Reveal } from "@/components/Reveal";
|
||||
import { TechBackground } from "@/components/TechBackground";
|
||||
|
||||
interface HeroProps {
|
||||
tag: string;
|
||||
title: React.ReactNode;
|
||||
subtitle: string;
|
||||
ctaPrimary: string;
|
||||
ctaSecondary: string;
|
||||
}
|
||||
|
||||
export function Hero({
|
||||
tag,
|
||||
title,
|
||||
subtitle,
|
||||
ctaPrimary,
|
||||
ctaSecondary,
|
||||
}: HeroProps) {
|
||||
return (
|
||||
<section className="relative min-h-[90vh] flex items-center pt-44 pb-20 overflow-hidden">
|
||||
<div className="absolute inset-0 z-0">
|
||||
<Image
|
||||
src="/media/business/hero-bg.jpg"
|
||||
alt="MB Grid Solutions Hero"
|
||||
fill
|
||||
className="object-cover"
|
||||
priority
|
||||
quality={75}
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-slate-100/80 via-white/90 to-white/40 md:to-transparent" />
|
||||
<TechBackground />
|
||||
</div>
|
||||
|
||||
<div className="container-custom relative z-10">
|
||||
<div className="text-left relative">
|
||||
<Counter value={1} className="section-number" />
|
||||
<Reveal delay={0.1}>
|
||||
<span className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-accent/10 text-accent text-xs font-bold uppercase tracking-wider mb-6">
|
||||
<span className="relative flex h-2 w-2">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-accent opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-accent"></span>
|
||||
</span>
|
||||
{tag}
|
||||
</span>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.2}>
|
||||
<h1 className="text-4xl sm:text-5xl md:text-7xl font-extrabold text-primary mb-6 md:mb-8 leading-[1.1]">
|
||||
{title}
|
||||
</h1>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.3}>
|
||||
<p className="text-slate-600 text-lg md:text-2xl leading-relaxed mb-8 md:mb-12 max-w-2xl">
|
||||
{subtitle}
|
||||
</p>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.4}>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<Button href="/kontakt" variant="accent" showArrow>
|
||||
{ctaPrimary}
|
||||
</Button>
|
||||
<Button href="/ueber-uns" variant="ghost">
|
||||
{ctaSecondary}
|
||||
</Button>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
80
components/sections/ManifestSection.tsx
Normal file
80
components/sections/ManifestSection.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
Award,
|
||||
Clock,
|
||||
Lightbulb,
|
||||
Truck,
|
||||
MessageSquare,
|
||||
ShieldCheck,
|
||||
} from "lucide-react";
|
||||
import { Reveal } from "@/components/Reveal";
|
||||
import { TechBackground } from "@/components/TechBackground";
|
||||
import { Counter } from "@/components/Counter";
|
||||
|
||||
const manifestIcons = [
|
||||
Award,
|
||||
Clock,
|
||||
Lightbulb,
|
||||
Truck,
|
||||
MessageSquare,
|
||||
ShieldCheck,
|
||||
];
|
||||
|
||||
interface ManifestItem {
|
||||
title: string;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
interface ManifestSectionProps {
|
||||
tagline: string;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
items: ManifestItem[];
|
||||
}
|
||||
|
||||
export function ManifestSection({
|
||||
tagline,
|
||||
title,
|
||||
subtitle,
|
||||
items,
|
||||
}: ManifestSectionProps) {
|
||||
return (
|
||||
<section className="bg-slate-950 text-accent relative overflow-hidden">
|
||||
<TechBackground />
|
||||
<div className="container-custom relative z-10">
|
||||
<Counter value={3} className="section-number !text-white/5" />
|
||||
<Reveal className="mb-20">
|
||||
<span className="text-accent font-bold uppercase tracking-widest text-sm mb-4 block">
|
||||
{tagline}
|
||||
</span>
|
||||
<h2 className="text-3xl md:text-5xl font-bold text-white mb-6">
|
||||
{title}
|
||||
</h2>
|
||||
<p className="text-slate-400 text-base md:text-lg">{subtitle}</p>
|
||||
</Reveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{items.map((item, i) => {
|
||||
const Icon = manifestIcons[i % manifestIcons.length];
|
||||
return (
|
||||
<Reveal key={i} delay={i * 0.1}>
|
||||
<div className="bg-white/5 p-10 rounded-3xl border border-white/10 group hover:-translate-y-1 transition-[box-shadow,transform] duration-300 h-full motion-fix relative overflow-hidden">
|
||||
<div className="absolute top-0 left-0 w-full h-1 bg-accent/0 group-hover:bg-accent/50 transition-all duration-500" />
|
||||
<div className="text-accent mb-6">
|
||||
<Icon size={32} />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-white mb-4">
|
||||
{i + 1}. {item.title}
|
||||
</h3>
|
||||
<p className="text-slate-400 leading-relaxed">{item.desc}</p>
|
||||
</div>
|
||||
</Reveal>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -3,14 +3,59 @@
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
import { ChevronRight, Zap, Shield, BarChart3 } from "lucide-react";
|
||||
import { Reveal } from "../Reveal";
|
||||
import { Counter } from "../Counter";
|
||||
import { TechBackground } from "../TechBackground";
|
||||
import { Reveal } from "@/components/Reveal";
|
||||
import { Counter } from "@/components/Counter";
|
||||
import { TechBackground } from "@/components/TechBackground";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export const PortfolioSection = () => {
|
||||
interface PortfolioItem {
|
||||
icon: React.ReactNode;
|
||||
title: string;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
interface PortfolioSectionProps {
|
||||
tag?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
linkText?: string;
|
||||
items?: PortfolioItem[];
|
||||
}
|
||||
|
||||
export const PortfolioSection = ({
|
||||
tag,
|
||||
title,
|
||||
description,
|
||||
linkText,
|
||||
items,
|
||||
}: PortfolioSectionProps) => {
|
||||
const t = useTranslations("Index");
|
||||
|
||||
const displayTag = tag || t("portfolio.tag");
|
||||
const displayTitle = title || t("portfolio.title");
|
||||
const displayDescription = description || t("portfolio.description");
|
||||
const displayLinkText = linkText || t("portfolio.link");
|
||||
|
||||
const defaultItems = [
|
||||
{
|
||||
icon: <Zap size={32} />,
|
||||
title: t("portfolio.items.beratung.title"),
|
||||
desc: t("portfolio.items.beratung.desc"),
|
||||
},
|
||||
{
|
||||
icon: <Shield size={32} />,
|
||||
title: t("portfolio.items.begleitung.title"),
|
||||
desc: t("portfolio.items.begleitung.desc"),
|
||||
},
|
||||
{
|
||||
icon: <BarChart3 size={32} />,
|
||||
title: t("portfolio.items.beschaffung.title"),
|
||||
desc: t("portfolio.items.beschaffung.desc"),
|
||||
},
|
||||
];
|
||||
|
||||
const displayItems = items || defaultItems;
|
||||
|
||||
return (
|
||||
<section className="bg-slate-950 text-accent relative overflow-hidden">
|
||||
<TechBackground />
|
||||
@@ -19,20 +64,20 @@ export const PortfolioSection = () => {
|
||||
<Reveal className="flex flex-col md:flex-row md:items-end justify-between gap-8 mb-16">
|
||||
<div>
|
||||
<span className="text-accent font-bold uppercase tracking-widest text-sm mb-4 block">
|
||||
{t("portfolio.tag")}
|
||||
{displayTag}
|
||||
</span>
|
||||
<h2 className="text-3xl md:text-5xl font-bold text-white mb-6">
|
||||
{t("portfolio.title")}
|
||||
{displayTitle}
|
||||
</h2>
|
||||
<p className="text-slate-400 text-base md:text-xl">
|
||||
{t("portfolio.description")}
|
||||
{displayDescription}
|
||||
</p>
|
||||
</div>
|
||||
<Link
|
||||
href="/ueber-uns"
|
||||
className="text-accent font-bold flex items-center gap-2 hover:text-white transition-colors group"
|
||||
>
|
||||
{t("portfolio.link")}{" "}
|
||||
{displayLinkText}{" "}
|
||||
<ChevronRight
|
||||
className="transition-transform group-hover:translate-x-1"
|
||||
size={20}
|
||||
@@ -41,23 +86,7 @@ export const PortfolioSection = () => {
|
||||
</Reveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
{[
|
||||
{
|
||||
icon: <Zap size={32} />,
|
||||
title: t("portfolio.items.beratung.title"),
|
||||
desc: t("portfolio.items.beratung.desc"),
|
||||
},
|
||||
{
|
||||
icon: <Shield size={32} />,
|
||||
title: t("portfolio.items.begleitung.title"),
|
||||
desc: t("portfolio.items.begleitung.desc"),
|
||||
},
|
||||
{
|
||||
icon: <BarChart3 size={32} />,
|
||||
title: t("portfolio.items.beschaffung.title"),
|
||||
desc: t("portfolio.items.beschaffung.desc"),
|
||||
},
|
||||
].map((item, i) => (
|
||||
{displayItems.map((item, i) => (
|
||||
<Reveal key={i} delay={i * 0.1}>
|
||||
<div className="bg-white/5 p-8 rounded-2xl border border-white/10 group hover:-translate-y-2 transition-[box-shadow,transform] duration-300 h-full relative overflow-hidden">
|
||||
<div className="absolute top-0 right-0 w-16 h-16 bg-accent/5 -mr-8 -mt-8 rounded-full group-hover:bg-accent/10 transition-colors" />
|
||||
|
||||
@@ -2,14 +2,53 @@
|
||||
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../Reveal";
|
||||
import { Counter } from "../Counter";
|
||||
import { TechBackground } from "../TechBackground";
|
||||
import { Reveal } from "@/components/Reveal";
|
||||
import { Counter } from "@/components/Counter";
|
||||
import { TechBackground } from "@/components/TechBackground";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export const TechnicalSpecsSection = () => {
|
||||
interface SpecItem {
|
||||
label: string;
|
||||
value: string;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
interface TechnicalSpecsSectionProps {
|
||||
tag?: string;
|
||||
title?: string;
|
||||
items?: SpecItem[];
|
||||
}
|
||||
|
||||
export const TechnicalSpecsSection = ({
|
||||
tag,
|
||||
title,
|
||||
items,
|
||||
}: TechnicalSpecsSectionProps) => {
|
||||
const t = useTranslations("Index");
|
||||
|
||||
const displayTag = tag || t("specs.tag");
|
||||
const displayTitle = title || t("specs.title");
|
||||
|
||||
const defaultItems = [
|
||||
{
|
||||
label: t("specs.items.kabel.label"),
|
||||
value: t("specs.items.kabel.value"),
|
||||
desc: t("specs.items.kabel.desc"),
|
||||
},
|
||||
{
|
||||
label: t("specs.items.spannung.label"),
|
||||
value: t("specs.items.spannung.value"),
|
||||
desc: t("specs.items.spannung.desc"),
|
||||
},
|
||||
{
|
||||
label: t("specs.items.technologie.label"),
|
||||
value: t("specs.items.technologie.value"),
|
||||
desc: t("specs.items.technologie.desc"),
|
||||
},
|
||||
];
|
||||
|
||||
const displayItems = items || defaultItems;
|
||||
|
||||
return (
|
||||
<section className="relative py-24 md:py-32 text-white overflow-hidden bg-slate-900">
|
||||
<div className="absolute inset-0 opacity-20">
|
||||
@@ -31,31 +70,15 @@ export const TechnicalSpecsSection = () => {
|
||||
|
||||
<Reveal className="mb-20">
|
||||
<span className="text-accent font-bold uppercase tracking-widest text-sm mb-4 block">
|
||||
{t("specs.tag")}
|
||||
{displayTag}
|
||||
</span>
|
||||
<h2 className="text-3xl md:text-5xl font-bold text-white mb-6">
|
||||
{t("specs.title")}
|
||||
{displayTitle}
|
||||
</h2>
|
||||
</Reveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 md:gap-8">
|
||||
{[
|
||||
{
|
||||
label: t("specs.items.kabel.label"),
|
||||
value: t("specs.items.kabel.value"),
|
||||
desc: t("specs.items.kabel.desc"),
|
||||
},
|
||||
{
|
||||
label: t("specs.items.spannung.label"),
|
||||
value: t("specs.items.spannung.value"),
|
||||
desc: t("specs.items.spannung.desc"),
|
||||
},
|
||||
{
|
||||
label: t("specs.items.technologie.label"),
|
||||
value: t("specs.items.technologie.value"),
|
||||
desc: t("specs.items.technologie.desc"),
|
||||
},
|
||||
].map((item, i) => (
|
||||
{displayItems.map((item, i) => (
|
||||
<Reveal key={i} delay={i * 0.1}>
|
||||
<div className="p-10 rounded-3xl bg-white/5 border border-white/10 backdrop-blur-sm hover:bg-white/10 transition-colors h-full relative group overflow-hidden">
|
||||
<div className="absolute top-0 left-0 w-full h-1 bg-accent/0 group-hover:bg-accent/50 transition-all duration-500" />
|
||||
|
||||
Reference in New Issue
Block a user