Files
resume/components/sections/hero.tsx
evan 6fec90ea71 feat: build resume website with MagicUI components
- 6 sections: Hero, About, Experience, Skills, Projects, Contact
- MagicUI: Globe, Particles, Meteors, AnimatedList, IconCloud, BentoGrid
- Dark mode support, scroll-triggered animations
- Static export ready for deployment
2026-04-14 15:09:48 +08:00

101 lines
3.3 KiB
TypeScript
Raw Permalink 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.
"use client"
import { useMemo } from "react"
import { useTheme } from "next-themes"
import type { COBEOptions } from "cobe"
import { Globe } from "@/components/ui/globe"
import { Particles } from "@/components/ui/particles"
import { Meteors } from "@/components/ui/meteors"
import { AnimatedGradientText } from "@/components/ui/animated-gradient-text"
import { TextAnimate } from "@/components/ui/text-animate"
export function Hero() {
const { resolvedTheme } = useTheme()
const isDark = resolvedTheme === "dark"
const globeConfig = useMemo((): Omit<COBEOptions, "width" | "height"> => {
const baseConfig: Omit<COBEOptions, "width" | "height"> = {
phi: 0,
theta: 0.3,
dark: isDark ? 1 : 0,
diffuse: 0.4,
mapSamples: 12000,
mapBrightness: 1.2,
devicePixelRatio: 2,
baseColor: isDark ? [0.3, 0.3, 0.3] as [number, number, number] : [1, 1, 1] as [number, number, number],
markerColor: [251 / 255, 100 / 255, 21 / 255] as [number, number, number],
glowColor: isDark ? [0.5, 0.5, 0.5] as [number, number, number] : [1, 1, 1] as [number, number, number],
markers: [
{ location: [39.9042, 116.4074], size: 0.08 },
{ location: [40.7128, -74.006], size: 0.1 },
{ location: [51.5074, -0.1278], size: 0.07 },
{ location: [35.6762, 139.6503], size: 0.06 },
],
}
return baseConfig
}, [isDark])
return (
<section className="relative flex min-h-svh items-center justify-center overflow-hidden">
{/* Background effects */}
<div className="absolute inset-0">
<Globe className="opacity-40" config={globeConfig} />
</div>
<Particles
className="absolute inset-0"
quantity={40}
color={isDark ? "#ffffff" : "#000000"}
/>
<Meteors number={12} />
{/* Content */}
<div className="relative z-10 mx-auto max-w-4xl px-6 text-center">
<AnimatedGradientText className="mb-4 text-lg font-medium tracking-wide sm:text-xl">
👋
</AnimatedGradientText>
<h1 className="mb-4 text-5xl font-bold tracking-tight sm:text-7xl md:text-8xl">
<TextAnimate
by="character"
animation="blurInUp"
delay={0.3}
once
>
Evan Sun
</TextAnimate>
</h1>
<TextAnimate
as="p"
className="mx-auto max-w-2xl text-lg text-muted-foreground sm:text-xl"
by="word"
animation="fadeIn"
delay={0.8}
once
>
/ AI
</TextAnimate>
<div className="mt-8 flex justify-center gap-4">
<a
href="#contact"
className="rounded-lg bg-foreground px-6 py-2.5 text-sm font-medium text-background transition-opacity hover:opacity-80"
>
</a>
<a
href="#projects"
className="rounded-lg border border-border px-6 py-2.5 text-sm font-medium transition-colors hover:bg-accent"
>
</a>
</div>
</div>
{/* Fade gradient at bottom */}
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-32 bg-gradient-to-t from-background to-transparent" />
</section>
)
}