Files
e-tib.com/components/blocks/CompanyTimeline.tsx
2026-05-07 10:43:20 +02:00

107 lines
3.9 KiB
TypeScript

'use client';
import * as React from 'react';
import { motion, useScroll, useTransform } from 'framer-motion';
const defaultMilestones = [
{
date: '2015',
title: 'Gründung der E-TIB GmbH',
desc: 'Gründung im brandenburgischen Guben mit Fokus auf Tiefbauarbeiten und Kabelmontagen.',
},
{
date: 'Wachstum',
title: 'Erweiterung der Kompetenzen',
desc: 'Konsequenter Ausbau der Leistungen um Horizontalspülbohrungen und Kabelpflugarbeiten.',
},
{
date: 'Unternehmensgruppe',
title: 'Zusammenschluss',
desc: 'Bündelung der Fachbereiche mit der NEMO GmbH und der E-TIB Ingenieurgesellschaft mbH.',
},
{
date: 'Heute',
title: 'Die E-TIB Gruppe',
desc: 'Ein starker Verbund mit über 50 Mitarbeitern für bundesweite Infrastrukturprojekte.',
},
];
interface Milestone {
date: string;
title: string;
desc: string;
}
interface CompanyTimelineProps {
badge?: string;
title?: string;
milestones?: Milestone[];
}
export function CompanyTimeline({
badge = 'Unsere Geschichte',
title = 'Meilensteine der Entwicklung',
milestones = defaultMilestones
}: CompanyTimelineProps) {
const containerRef = React.useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({
target: containerRef,
offset: ["start center", "end center"]
});
const lineHeight = useTransform(scrollYProgress, [0, 1], ["0%", "100%"]);
return (
<section className="py-24 bg-white relative">
<div className="container max-w-4xl">
<div className="text-center mb-16">
<h2 className="text-primary font-bold tracking-wider uppercase text-sm mb-3">{badge}</h2>
<h3 className="font-heading text-4xl font-extrabold text-neutral-dark">{title}</h3>
</div>
<div ref={containerRef} className="relative">
{/* Central Line */}
<div className="absolute left-4 md:left-1/2 top-0 bottom-0 w-1 bg-neutral-200 -translate-x-1/2 rounded-full overflow-hidden">
<motion.div
className="w-full bg-primary"
style={{ height: lineHeight }}
/>
</div>
<div className="space-y-12 md:space-y-0">
{milestones.map((milestone, i) => {
const isEven = i % 2 === 0;
// isEven (0, 2): Left side on desktop
// !isEven (1, 3): Right side on desktop
return (
<motion.div
key={i}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.6 }}
className="relative flex flex-col w-full"
>
{/* Timeline Dot */}
<div className="absolute left-4 md:left-1/2 top-8 md:top-1/2 w-6 h-6 rounded-full bg-white border-4 border-primary z-10 -translate-x-1/2 md:-translate-y-1/2 shadow-lg" />
{/* Content Box */}
<div className={`w-full md:w-[calc(50%-2.5rem)] pl-16 md:pl-0 ${isEven ? 'md:mr-auto md:text-right' : 'md:ml-auto md:text-left'}`}>
<div className="bg-neutral-50 p-6 md:p-8 rounded-2xl shadow-sm border border-neutral-100 hover:shadow-md transition-shadow relative">
<span className="inline-block py-1.5 px-4 rounded-full bg-primary/10 text-primary font-bold text-sm mb-4">
{milestone.date}
</span>
<h4 className="font-heading font-bold text-2xl md:text-3xl mb-3 text-neutral-dark leading-tight">{milestone.title}</h4>
<p className="text-text-secondary leading-relaxed">{milestone.desc}</p>
</div>
</div>
</motion.div>
);
})}
</div>
</div>
</div>
</section>
);
}