open-productive-stack/drupal/nextjs/components/animated-hero-title.tsx
rnsrk f8b8f53d54 Add Drupal headless stack with Next.js frontend
- Add Next.js frontend service (nextjs) with Dockerfile and source
- Update docker-compose.yml: image names, Drupal 11.3.3, nextjs service
- Add docker-compose.override.yml.disabled for dev hot-reload
- Add install-headless-modules.sh for OAuth/JSON:API module setup
- Add README.md with full setup and configuration guide
- Update nginx/Dockerfile and nginx.conf.template for cms. subdomain
- Update drupal/Dockerfile PHP-FPM build args
- Gitignore **/.vscode/ to prevent IDE workspace files from being tracked
2026-03-30 11:14:17 +02:00

78 lines
2.3 KiB
TypeScript

"use client"
const TEXT = "I'm Robert."
type Direction = "up" | "down" | "r" | "e" | "t"
const LETTER_ANIMS: Record<number, Direction> = {
0: "down", // I
1: "up", // '
2: "down", // m
3: "down", // space - treat as down for delay
4: "r", // R (special)
5: "down", // o
6: "up", // b
7: "e", // e (special: o first, then e)
8: "down", // r
9: "t", // t (special: appears with o, then slides right)
10: "down", // .
}
const DELAYS_MS = [0, 80, 240, 320, 400, 560, 680, 760, 1400, 760, 1560]
export function AnimatedHeroTitle() {
return (
<h1
className="home-hero-title mb-2 font-bold tracking-tight text-slate-900"
style={{ fontSize: "var(--fluid-hero)" }}
>
{TEXT.split("").map((char, i) => {
if (char === " ") {
return <span key={i} className="inline-block" style={{ width: "0.25em" }} aria-hidden />
}
const dir = LETTER_ANIMS[i] ?? "down"
const delay = DELAYS_MS[i] ?? i * 80
const animClass =
dir === "r"
? "hero-letter-r animate-letter-from-up"
: dir === "e"
? "hero-letter-e"
: dir === "t"
? "hero-letter-t animate-letter-t-slide"
: dir === "up"
? "animate-letter-from-up"
: "animate-letter-from-down"
const animDelay =
dir === "r" ? delay + 320 : dir === "e" ? delay + 1050 : delay
const style =
dir === "r"
? { "--b-delay": `${delay}ms`, animationDelay: `${animDelay}ms` } as React.CSSProperties
: dir === "e"
? { "--o-delay": `${delay}ms` } as React.CSSProperties
: { animationDelay: `${animDelay}ms` }
return (
<span
key={i}
className={`inline-block overflow-hidden ${animClass}`}
style={style}
aria-hidden
>
{dir === "e" ? (
<span className="block animate-letter-e-fade-in" style={{ animationDelay: `${animDelay}ms` }}>
e
</span>
) : dir === "r" ? (
"R"
) : dir === "t" ? (
"t"
) : (
char
)}
</span>
)
})}
</h1>
)
}