managarten/packages/shared-landing-ui/src/sections/TimelineSection.astro
Till-JS 264149a913 feat(shared-landing-ui): unify landing pages with shared components
Add new reusable components to shared-landing-ui package:
- AppScrollerSection, TimelineSection, MasonryGridSection, PrinciplesSection
- LegalPageTemplate for privacy/terms/cookies/imprint pages
- Navigation component with mobile menu and language switcher
- GradientText and LanguageSwitcher atoms
- i18n system with getLangFromUrl, useTranslations, localizePath
- Theme files for picture (indigo), chat (blue), zitare (teal)

Add legal pages to ManaDeck and Chat landing pages:
- privacy, terms, cookies, imprint pages using shared template
- Updated footers with cookies link
2026-01-23 15:45:47 +01:00

286 lines
5.5 KiB
Text

---
/**
* TimelineSection - Alternating timeline layout
*
* Usage:
* ```astro
* <TimelineSection
* title="Our Journey"
* subtitle="From vision to reality"
* items={[
* { badge: 'Mission', title: 'Democratizing AI', text: 'Breaking barriers...' },
* { badge: 'Vision', title: 'A connected future', text: 'A world where...' }
* ]}
* />
* ```
*/
export interface TimelineItem {
badge: string;
title: string;
text: string;
}
interface Props {
title: string;
subtitle?: string;
items: TimelineItem[];
class?: string;
}
const { title, subtitle, items, class: className = '' } = Astro.props;
---
<section class:list={['timeline-section', className]}>
<div class="timeline-overlay"></div>
<div class="timeline-container">
<div class="timeline-header">
<h2 class="timeline-main-title">{title}</h2>
{subtitle && <p class="timeline-main-subtitle">{subtitle}</p>}
</div>
<div class="timeline-grid">
{
items.map((item, index) => (
<div class={`timeline-item ${index % 2 === 0 ? 'timeline-left' : 'timeline-right'}`}>
<div class="timeline-dot" />
<div class="timeline-content">
<span class="timeline-badge">{item.badge}</span>
<h4 class="timeline-title">{item.title}</h4>
<p class="timeline-text">{item.text}</p>
</div>
</div>
))
}
</div>
</div>
</section>
<style>
.timeline-section {
position: relative;
background: linear-gradient(
180deg,
var(--color-background-card) 0%,
var(--color-background-page) 100%
);
padding: 160px 0;
overflow: hidden;
}
.timeline-overlay {
position: absolute;
inset: 0;
background:
radial-gradient(circle at 30% 50%, var(--color-primary-glow) 0%, transparent 50%),
radial-gradient(circle at 70% 50%, var(--color-primary-glow) 0%, transparent 50%);
opacity: 0.3;
pointer-events: none;
}
.timeline-container {
position: relative;
max-width: 1400px;
margin: 0 auto;
padding: 0 80px;
z-index: 10;
}
.timeline-header {
text-align: center;
margin-bottom: 120px;
}
.timeline-main-title {
font-size: clamp(2.5rem, 5vw, 3.5rem);
font-weight: 800;
color: var(--color-text-primary);
margin: 0 0 20px 0;
line-height: 1.1;
letter-spacing: -0.02em;
}
.timeline-main-subtitle {
font-size: clamp(1rem, 2vw, 1.25rem);
color: var(--color-text-muted);
margin: 0;
}
.timeline-grid {
position: relative;
display: flex;
flex-direction: column;
gap: 60px;
max-width: 1000px;
margin: 0 auto;
}
.timeline-grid::before {
content: '';
position: absolute;
left: 50%;
top: 0;
bottom: 0;
width: 2px;
background: linear-gradient(
180deg,
transparent 0%,
var(--color-primary) 10%,
var(--color-primary) 90%,
transparent 100%
);
opacity: 0.5;
transform: translateX(-50%);
}
.timeline-item {
position: relative;
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 40px;
align-items: center;
}
.timeline-left .timeline-content {
grid-column: 1;
text-align: right;
}
.timeline-right .timeline-content {
grid-column: 3;
text-align: left;
}
.timeline-dot {
grid-column: 2;
width: 20px;
height: 20px;
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-hover) 100%);
border-radius: 50%;
box-shadow:
0 0 0 4px var(--color-primary-glow),
0 0 20px var(--color-primary-glow);
z-index: 2;
transition: all 0.3s ease;
}
.timeline-item:hover .timeline-dot {
box-shadow:
0 0 0 6px var(--color-primary-glow),
0 0 30px var(--color-primary);
transform: scale(1.2);
}
.timeline-content {
background: linear-gradient(
135deg,
var(--color-background-card) 0%,
var(--color-background-page) 100%
);
border: 1px solid var(--color-border);
border-radius: 16px;
padding: 30px;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.timeline-content::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, transparent 0%, var(--color-primary-glow) 100%);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.timeline-item:hover .timeline-content {
border-color: var(--color-primary);
transform: scale(1.02);
box-shadow:
0 10px 30px -10px rgba(0, 0, 0, 0.5),
0 0 0 1px var(--color-primary-glow);
}
.timeline-item:hover .timeline-content::before {
opacity: 0.1;
}
.timeline-badge {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
color: var(--color-primary);
text-transform: uppercase;
letter-spacing: 0.1em;
margin-bottom: 10px;
}
.timeline-title {
font-size: 1.25rem;
font-weight: 700;
color: var(--color-text-primary);
margin: 0 0 10px 0;
line-height: 1.3;
}
.timeline-text {
font-size: 0.9375rem;
line-height: 1.6;
color: var(--color-text-secondary);
margin: 0;
}
/* Mobile: Switch to left-aligned layout */
@media (max-width: 768px) {
.timeline-section {
padding: 120px 0;
}
.timeline-container {
padding: 0 40px;
}
.timeline-header {
margin-bottom: 80px;
}
.timeline-grid::before {
left: 20px;
}
.timeline-item {
grid-template-columns: auto 1fr;
gap: 20px;
}
.timeline-dot {
grid-column: 1;
grid-row: 1;
}
.timeline-left .timeline-content,
.timeline-right .timeline-content {
grid-column: 2;
grid-row: 1;
text-align: left;
}
}
@media (max-width: 640px) {
.timeline-section {
padding: 80px 0;
}
.timeline-container {
padding: 0 40px;
}
.timeline-content {
padding: 20px;
}
}
</style>