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
This commit is contained in:
parent
71a8dac389
commit
f8b8f53d54
85 changed files with 7802 additions and 17 deletions
78
drupal/nextjs/components/animated-hero-title.tsx
Normal file
78
drupal/nextjs/components/animated-hero-title.tsx
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
"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>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue