Simplify hero backgrounds and add entrance animations

- Replace animated blob/wave/noise backdrop with clean static gradient
  (radial ellipse highlights + linear fade) in hero-motion-backdrop
- Remove all framer-motion from background layer; delete unused CSS
  classes: hero-blob, hero-sheet-glow, hero-sheet-wave, hero-sheet-noise,
  hero-title-shift keyframe, and responsive blob media queries
- Add framer-motion stagger entrance to HeroContentMotion, HeroMotionItem,
  and HeroTitle (slide-up + fade on mount)
- Refactor coming-soon page to use HeroContentMotion/HeroMotionItem
  instead of MotionFade (whileInView unreliable above the fold)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
MOH
2026-03-17 22:48:51 +01:00
co-authored by Claude Sonnet 4.6
parent f490133345
commit 868eb80374
10 changed files with 92 additions and 181 deletions
@@ -1,5 +1,3 @@
"use client";
type HeroMotionBackdropProps = {
compact?: boolean;
};
@@ -8,13 +6,6 @@ export function HeroMotionBackdrop({}: HeroMotionBackdropProps) {
return (
<div className="hero-sheet pointer-events-none absolute inset-0 overflow-hidden">
<div className="hero-sheet-base" />
<div className="hero-blob hero-blob-left" />
<div className="hero-blob hero-blob-right" />
<div className="hero-blob hero-blob-bottom" />
<div className="hero-sheet-glow" />
<div className="hero-sheet-wave" />
<div className="hero-sheet-noise" />
<div className="hero-sheet-veil" />
<div className="hero-sheet-fade" />
</div>
+11 -5
View File
@@ -3,7 +3,7 @@ import { HeroContentMotion, HeroMotionItem, HeroShell, HeroTitle, type HeroTitle
type PageHeroProps = {
badge?: string;
title: string;
title?: string;
description?: string;
lines?: HeroTitleLineValue[];
locale?: string;
@@ -33,13 +33,19 @@ function getDefaultLines(title: string): HeroTitleLineValue[] {
}
export function PageHero({ badge, title, description, lines, locale }: PageHeroProps) {
const resolvedLines = lines ?? (title ? getDefaultLines(title) : undefined);
return (
<HeroShell compactBackdrop variant="page">
<HeroContentMotion variant="page">
<HeroMotionItem variant="page">
<HeroBadge>{badge ?? title}</HeroBadge>
</HeroMotionItem>
<HeroTitle lines={lines ?? getDefaultLines(title)} locale={locale} variant="page" />
{(badge ?? title) ? (
<HeroMotionItem variant="page">
<HeroBadge>{badge ?? title}</HeroBadge>
</HeroMotionItem>
) : null}
{resolvedLines ? (
<HeroTitle lines={resolvedLines} locale={locale} variant="page" />
) : null}
{description ? (
<HeroMotionItem variant="page">
<p className="mx-auto mt-6 max-w-[34rem] text-base leading-7 text-foreground/72">
+34 -4
View File
@@ -3,11 +3,28 @@
import type { ReactNode } from "react";
import { ArrowDown } from "lucide-react";
import { motion } from "framer-motion";
import { Container } from "@/components/layout/container";
import { HeroMotionBackdrop } from "@/components/layout/hero-motion-backdrop";
import { cn } from "@/lib/utils";
const heroItemVariants = {
hidden: { opacity: 0, y: 16 },
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.54, ease: [0.22, 1, 0.36, 1] as [number, number, number, number] },
},
};
const heroContainerVariants = {
hidden: {},
visible: {
transition: { staggerChildren: 0.13, delayChildren: 0.08 },
},
};
type HeroTone = "default" | "accent" | "soft";
type HeroLineAlign = "start" | "center" | "end";
@@ -119,14 +136,27 @@ export function HeroContentMotion({
children,
className,
}: HeroContentMotionProps) {
return <div className={className}>{children}</div>;
return (
<motion.div
className={className}
initial="hidden"
animate="visible"
variants={heroContainerVariants}
>
{children}
</motion.div>
);
}
export function HeroMotionItem({
children,
className,
}: HeroContentMotionProps) {
return <div className={className}>{children}</div>;
return (
<motion.div className={className} variants={heroItemVariants}>
{children}
</motion.div>
);
}
export function HeroTitle({
@@ -147,7 +177,7 @@ export function HeroTitle({
);
return (
<h1 className={titleClassName}>
<motion.h1 className={titleClassName} variants={heroItemVariants}>
{lines.map((line, index) => (
<span
key={`${index}-${line.text}`}
@@ -172,7 +202,7 @@ export function HeroTitle({
)}
</span>
))}
</h1>
</motion.h1>
);
}