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
This commit is contained in:
100
components/sections/hero.tsx
Normal file
100
components/sections/hero.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user