jamulix-homepage/components/system-diagram.tsx
dschlueter aa3d0c4046 Update: 50 Jahre Code Timeline (1976-2026)
- Hero: Jahreszahl auf 1976-2026 (50 Jahre) aktualisiert
- About: Timeline von 1984 auf 1976 erweitert
- About: Neue Einträge für PC/DOS (1984), Web (1995), Server (2000er)
- System-Diagramm: Halbkreis-Layout statt vertikaler Anordnung
- Metadaten: Description angepasst
2026-04-24 22:19:39 +02:00

134 lines
4.9 KiB
TypeScript

'use client'
import { motion } from 'framer-motion'
const nodes = [
// Halbkreis-Layout: folgt der Timeline von links → rechts in sanftem Bogen
// 1970s-80s (oberer linker Bogen)
{ id: 'fortran', label: 'Fortran IV', x: 15, y: 25, era: '1976' },
{ id: 'pc', label: 'PC/DOS', x: 28, y: 18, era: '1984' },
{ id: 'c', label: 'C', x: 42, y: 15, era: '1986' },
{ id: 'asm', label: '68K ASM', x: 58, y: 18, era: '1986' },
// 1990s (oberer rechter Bogen)
{ id: 'unix', label: 'Unix', x: 70, y: 28, era: '1990' },
{ id: 'linux', label: 'Linux', x: 78, y: 42, era: '1992' },
{ id: 'web', label: 'WWW', x: 82, y: 58, era: '1995' },
// 2000s-2020s (unterer Bereich, nach links zurück)
{ id: 'server', label: 'Server', x: 65, y: 75, era: '2000er' },
{ id: 'python', label: 'Python', x: 45, y: 82, era: '2000er' },
{ id: 'rust', label: 'Rust', x: 28, y: 78, era: '2022' },
{ id: 'ai', label: 'KI', x: 18, y: 68, era: '2022' },
]
const connections = [
// Hauptfluss der Timeline (äußerer Ring)
['fortran', 'pc'],
['pc', 'c'],
['c', 'asm'],
['unix', 'linux'],
['linux', 'web'],
['web', 'server'],
['server', 'python'],
['python', 'rust'],
['rust', 'ai'],
// Verbindungslinien (innere Verästelungen)
['c', 'unix'], // C beeinflusst Unix
['python', 'ai'], // Python → KI
]
export function SystemDiagram() {
const getNodePosition = (id: string) => {
const node = nodes.find(n => n.id === id)
return node ? { x: node.x, y: node.y } : { x: 0, y: 0 }
}
return (
<div className="relative aspect-square w-full max-w-md mx-auto">
{/* SVG for connections */}
<svg className="absolute inset-0 w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
<defs>
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stopColor="currentColor" stopOpacity="0.1" />
<stop offset="50%" stopColor="currentColor" stopOpacity="0.3" />
<stop offset="100%" stopColor="currentColor" stopOpacity="0.1" />
</linearGradient>
</defs>
{connections.map(([from, to], index) => {
const start = getNodePosition(from)
const end = getNodePosition(to)
return (
<motion.line
key={`${from}-${to}`}
x1={start.x}
y1={start.y}
x2={end.x}
y2={end.y}
stroke="url(#lineGradient)"
strokeWidth="0.5"
className="text-accent"
initial={{ pathLength: 0, opacity: 0 }}
animate={{ pathLength: 1, opacity: 1 }}
transition={{
duration: 0.8,
delay: 0.5 + index * 0.1,
ease: 'easeOut'
}}
/>
)
})}
</svg>
{/* Nodes */}
{nodes.map((node, index) => (
<motion.div
key={node.id}
className="absolute transform -translate-x-1/2 -translate-y-1/2"
style={{ left: `${node.x}%`, top: `${node.y}%` }}
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
transition={{
duration: 0.4,
delay: 0.3 + index * 0.08,
type: 'spring',
stiffness: 200
}}
>
<div className="group relative">
{/* Node circle */}
<div className="relative">
<div className="size-3 rounded-full bg-accent/20 border border-accent/40 group-hover:bg-accent/30 transition-colors" />
<div className="absolute inset-0 size-3 rounded-full bg-accent/60 animate-ping opacity-0 group-hover:opacity-30" />
</div>
{/* Label */}
<div className="absolute top-full left-1/2 -translate-x-1/2 mt-1.5 whitespace-nowrap">
<span className="font-mono text-[10px] text-muted-foreground group-hover:text-foreground transition-colors">
{node.label}
</span>
</div>
{/* Era tooltip */}
<div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-1.5 opacity-0 group-hover:opacity-100 transition-opacity">
<span className="font-mono text-[9px] text-accent bg-background/80 px-1.5 py-0.5 rounded border border-border/50">
{node.era}
</span>
</div>
</div>
</motion.div>
))}
{/* Decorative elements */}
<div className="absolute inset-0 pointer-events-none">
{/* Corner accents */}
<div className="absolute top-0 left-0 w-8 h-8 border-l border-t border-border/30" />
<div className="absolute top-0 right-0 w-8 h-8 border-r border-t border-border/30" />
<div className="absolute bottom-0 left-0 w-8 h-8 border-l border-b border-border/30" />
<div className="absolute bottom-0 right-0 w-8 h-8 border-r border-b border-border/30" />
</div>
</div>
)
}