Files
Webklar/src/components/Process.tsx
T
rootandClaude Opus 5.5 5cc8b5f66b Performance: Animationen pausieren, Footer-Raster entschärft, WebGL nachladen
- Footer-Schriftzug (FlickeringGrid): Textmaske einmal pro Größe statt
  ~14.500 getImageData-Aufrufe pro Frame, nur flackernde Quadrate neu
  zeichnen (69–86 ms -> 0,1–0,2 ms pro Frame, Darstellung pixelgleich)
- PixelBlast: WebGL erst in Viewport-Nähe anlegen, unsichtbar pausieren
  (autoPauseOffscreen war nie angeschlossen), Shader asynchron kompilieren,
  beim Unmount aufräumen (Render-Schleifen liefen nach Seitenwechsel
  weiter); kein MSAA, keine erzwungene High-Performance-GPU
- Silk (Hero): nur rendern, solange sichtbar; DPR max. 1,5
- LightRays: keine verwaiste Render-Schleife mehr bei schnellem Vorbeiscrollen
- BorderGlow (Kontaktkarte): Sweep nur, solange die Karte sichtbar ist
- Silk, PixelBlast, LightRays als eigene Chunks (React.lazy):
  Haupt-Bundle 1,6 MB -> 646 KB (gzip 470 -> 207 KB)
- backgroud_effect und Emailsorter-Vorschaubild als WebP
  (974 KB -> 15 KB, 1,2 MB -> 11 KB), Projekt-Vorschaubilder lazy

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 21:47:17 +00:00

115 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { lazy, Suspense } from "react";
import CountUp from "@/components/CountUp";
import { TextHoverEffect } from "@/components/ui/text-hover-effect";
// WebGL-Effekte als eigene Chunks laden, damit der Text nicht auf three.js/ogl warten muss
const PixelBlast = lazy(() => import("@/components/PixelBlast"));
const Process = () => {
const steps = [
{
number: 1,
title: "Potenzialanalyse",
description: "15 Minuten, unverbindlich: Wir verstehen Ziele, Engpässe und Tools – und nennen die größten Hebel.",
},
{
number: 2,
title: "Konzept & Design",
description: "Sie erhalten einen klaren Plan: Struktur, Design und Integrationen – abgestimmt auf Ihr Team.",
},
{
number: 3,
title: "Umsetzung",
description: "Website, Automationen und Anbindungen – in Etappen, mit Zwischenständen, die Sie testen können.",
},
{
number: 4,
title: "Launch & Betreuung",
description: "Go-live mit Tests und Übergabe. Danach Updates, wenn sich Ihr Unternehmen weiterentwickelt.",
},
];
return (
<section id="process" className="pt-8 pb-24 md:pt-12 md:pb-32 bg-secondary/20 relative">
{/* PixelBlast animated background */}
<div className="absolute inset-0 z-0 w-full h-full">
<Suspense fallback={null}>
<PixelBlast
variant="circle"
pixelSize={3}
color="#5b5b5b"
patternScale={7.75}
patternDensity={0.7}
pixelSizeJitter={2}
enableRipples={false}
rippleSpeed={0.4}
rippleThickness={0.12}
rippleIntensityScale={1.5}
liquid={false}
liquidStrength={0.12}
liquidRadius={1.2}
liquidWobbleSpeed={5}
speed={0.3}
edgeFade={0.5}
transparent
/>
</Suspense>
</div>
{/* TextHoverEffect */}
<div className="h-[14rem] flex items-center justify-center -mb-4 relative z-10">
<TextHoverEffect text="Ablauf" />
</div>
<div className="container mx-auto px-6 relative z-10">
{/* Section Header */}
<div className="mb-4">
<div className="label-tag mb-4">So arbeiten wir</div>
<p className="text-muted-foreground max-w-2xl mb-8 leading-relaxed">
Transparent in vier Schritten – ohne Überraschungen bei Scope oder Kosten.
</p>
</div>
<div className="max-w-4xl">
{steps.map((step, index) => (
<div
key={step.number}
className="group flex gap-8 md:gap-12 pb-16 last:pb-0 border-l border-border pl-8 md:pl-12 relative"
>
{/* Line dot */}
<div className="absolute -left-[5px] top-0 w-[10px] h-[10px] rounded-full bg-background border-2 border-border group-hover:border-foreground transition-colors" />
{/* Number */}
<div className="hidden md:block">
<span className="stat-number text-6xl text-border group-hover:text-muted-foreground/30 transition-colors">
<CountUp
from={0}
to={step.number}
direction="up"
duration={1}
padMinLength={2}
startWhen={true}
/>
</span>
</div>
{/* Content */}
<div className="flex-1">
<span className="md:hidden label-tag mb-2 block">
<CountUp from={0} to={step.number} duration={1} padMinLength={2} startWhen={true} />
</span>
<h3 className="text-2xl md:text-3xl font-display font-medium text-foreground mb-4 uppercase tracking-tight">
{step.title}
</h3>
<p className="text-muted-foreground leading-relaxed max-w-lg">
{step.description}
</p>
</div>
</div>
))}
</div>
</div>
</section>
);
};
export default Process;