feat: implement industrial optimizations, hybrid dev workflow, and simplified reveal animations
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 11s
Build & Deploy / 🧪 QA (push) Successful in 4m5s
Build & Deploy / 🏗️ Build (push) Successful in 9m26s
Build & Deploy / 🚀 Deploy (push) Successful in 25s
Build & Deploy / 🩺 Health Check (push) Failing after 12s
Build & Deploy / 🔔 Notify (push) Successful in 2s
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 11s
Build & Deploy / 🧪 QA (push) Successful in 4m5s
Build & Deploy / 🏗️ Build (push) Successful in 9m26s
Build & Deploy / 🚀 Deploy (push) Successful in 25s
Build & Deploy / 🩺 Health Check (push) Failing after 12s
Build & Deploy / 🔔 Notify (push) Successful in 2s
This commit is contained in:
@@ -537,8 +537,8 @@ export function ContactForm({
|
||||
Anfrage gesendet!
|
||||
</h2>
|
||||
<p className="text-slate-400 text-2xl max-w-2xl mx-auto leading-relaxed">
|
||||
Vielen Dank, {state.name.split(" ")[0]}. Ich melde mich innerhalb
|
||||
von 24 Stunden bei Ihnen.
|
||||
Vielen Dank, {state.name.split(" ")[0]}. Ich melde mich zeitnah bei
|
||||
Ihnen.
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { ArrowRight } from 'lucide-react';
|
||||
import { Reveal } from '../Reveal';
|
||||
import { Label, H3, LeadText } from '../Typography';
|
||||
import * as React from "react";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
import { Reveal } from "../Reveal";
|
||||
import { Label, H3, LeadText } from "../Typography";
|
||||
|
||||
interface ComparisonRowProps {
|
||||
negativeLabel: string;
|
||||
@@ -22,27 +22,27 @@ export const ComparisonRow: React.FC<ComparisonRowProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<Reveal delay={delay}>
|
||||
<div className={`flex flex-col ${reverse ? 'md:flex-row-reverse' : 'md:flex-row'} gap-8 md:gap-12 items-center`}>
|
||||
<div
|
||||
className={`flex flex-col ${reverse ? "md:flex-row-reverse" : "md:flex-row"} gap-8 md:gap-12 items-center`}
|
||||
>
|
||||
<div className="flex-1 p-8 md:p-10 bg-slate-50/50 rounded-2xl text-slate-400 border border-transparent w-full">
|
||||
<Label className="mb-4 line-through decoration-slate-200">
|
||||
<Label className="mb-4 line-through decoration-red-500">
|
||||
{negativeLabel}
|
||||
</Label>
|
||||
<LeadText className="line-through decoration-slate-200 leading-snug">
|
||||
<LeadText className="line-through decoration-red-500 leading-snug">
|
||||
{negativeText}
|
||||
</LeadText>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="shrink-0">
|
||||
<ArrowRight className={`w-6 h-6 text-slate-200 hidden md:block ${reverse ? 'rotate-180' : ''}`} />
|
||||
<ArrowRight
|
||||
className={`w-6 h-6 text-slate-200 hidden md:block ${reverse ? "rotate-180" : ""}`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex-1 p-8 md:p-10 border border-slate-100 rounded-2xl bg-white hover:border-slate-200 transition-all duration-500 hover:shadow-xl hover:shadow-slate-100/50 w-full">
|
||||
<Label className="text-slate-900 mb-4">
|
||||
{positiveLabel}
|
||||
</Label>
|
||||
<H3 className="text-2xl md:text-3xl">
|
||||
{positiveText}
|
||||
</H3>
|
||||
<Label className="text-slate-900 mb-4">{positiveLabel}</Label>
|
||||
<H3 className="text-2xl md:text-3xl">{positiveText}</H3>
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
42
apps/web/src/components/Marker.tsx
Normal file
42
apps/web/src/components/Marker.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
/**
|
||||
* TECHNICAL MARKER COMPONENT
|
||||
* Implements the "hand-drawn marker" effect.
|
||||
* Animates in when entering the viewport.
|
||||
*/
|
||||
interface MarkerProps {
|
||||
children: React.ReactNode;
|
||||
delay?: number;
|
||||
className?: string;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export const Marker: React.FC<MarkerProps> = ({
|
||||
children,
|
||||
delay = 0,
|
||||
className = "",
|
||||
color = "rgba(255,235,59,0.95)",
|
||||
}) => {
|
||||
return (
|
||||
<span className={`relative inline-block px-1 ${className}`}>
|
||||
<motion.span
|
||||
initial={{ scaleX: 0, opacity: 0 }}
|
||||
whileInView={{ scaleX: 1, opacity: 1 }}
|
||||
viewport={{ once: true, margin: "-5%" }}
|
||||
transition={{
|
||||
duration: 1.2,
|
||||
delay: delay + 0.1,
|
||||
ease: [0.23, 1, 0.32, 1],
|
||||
}}
|
||||
className="absolute inset-0 z-[-1] -skew-x-6 rotate-[-1deg] translate-y-1 transform-gpu origin-left"
|
||||
style={{ backgroundColor: color }}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
@@ -1,26 +1,26 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { motion, useInView, useAnimation, Variants } from 'framer-motion';
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { motion, useInView, useAnimation, Variants } from "framer-motion";
|
||||
|
||||
interface RevealProps {
|
||||
children: React.ReactNode;
|
||||
width?: 'fit-content' | '100%';
|
||||
width?: "fit-content" | "100%";
|
||||
delay?: number;
|
||||
className?: string;
|
||||
direction?: 'up' | 'down' | 'left' | 'right' | 'none';
|
||||
direction?: "up" | "down" | "left" | "right" | "none";
|
||||
scale?: number;
|
||||
blur?: boolean;
|
||||
}
|
||||
|
||||
export const Reveal: React.FC<RevealProps> = ({
|
||||
children,
|
||||
width = 'fit-content',
|
||||
width = "fit-content",
|
||||
delay = 0.25,
|
||||
className = "",
|
||||
direction = 'up',
|
||||
direction = "up",
|
||||
scale = 1,
|
||||
blur = false
|
||||
blur = false,
|
||||
}) => {
|
||||
const ref = useRef(null);
|
||||
const isInView = useInView(ref, { once: true, margin: "-10%" });
|
||||
@@ -32,31 +32,18 @@ export const Reveal: React.FC<RevealProps> = ({
|
||||
}
|
||||
}, [isInView, mainControls]);
|
||||
|
||||
const getDirectionOffset = () => {
|
||||
switch (direction) {
|
||||
case 'up': return { y: 20 };
|
||||
case 'down': return { y: -20 };
|
||||
case 'left': return { x: 20 };
|
||||
case 'right': return { x: -20 };
|
||||
default: return {};
|
||||
}
|
||||
};
|
||||
|
||||
const variants: Variants = {
|
||||
hidden: {
|
||||
opacity: 0,
|
||||
...getDirectionOffset(),
|
||||
scale: scale !== 1 ? scale : 0.99,
|
||||
rotateX: direction === 'up' ? 2 : direction === 'down' ? -2 : 0,
|
||||
rotateY: direction === 'left' ? -2 : direction === 'right' ? 2 : 0,
|
||||
y: direction === "up" ? 10 : direction === "down" ? -10 : 0,
|
||||
x: direction === "left" ? 10 : direction === "right" ? -10 : 0,
|
||||
scale: scale !== 1 ? scale : 1,
|
||||
},
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
x: 0,
|
||||
scale: 1,
|
||||
rotateX: 0,
|
||||
rotateY: 0,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -66,7 +53,6 @@ export const Reveal: React.FC<RevealProps> = ({
|
||||
style={{
|
||||
position: "relative",
|
||||
width,
|
||||
perspective: "1000px"
|
||||
}}
|
||||
className={className}
|
||||
>
|
||||
@@ -76,13 +62,13 @@ export const Reveal: React.FC<RevealProps> = ({
|
||||
animate={mainControls}
|
||||
style={{ transformStyle: "preserve-3d" }}
|
||||
transition={{
|
||||
duration: 0.8,
|
||||
duration: 0.4,
|
||||
delay: delay,
|
||||
type: "spring",
|
||||
stiffness: 70,
|
||||
damping: 24,
|
||||
stiffness: 260,
|
||||
damping: 20,
|
||||
mass: 1,
|
||||
opacity: { duration: 0.5, ease: [0.16, 1, 0.3, 1] }
|
||||
opacity: { duration: 0.3, ease: [0.16, 1, 0.3, 1] },
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user