@@ -5,15 +5,39 @@ import Link from "next/link";
55import { Button } from "@/components/ui/button" ;
66import { ArrowRight } from "lucide-react" ;
77import { TubesBackground } from "./tubes-background" ;
8- import { AnimatedSphere } from "./animated-sphere" ;
98import { useReducedMotion } from "@/hooks/use-reduced-motion" ;
109
1110const words = [ "learn" , "build" , "practice" , "ship" ] ;
1211
12+ function TypedText ( {
13+ text,
14+ delayOffset = 0 ,
15+ characterClassName = "" ,
16+ } : {
17+ text : string ;
18+ delayOffset ?: number ;
19+ characterClassName ?: string ;
20+ } ) {
21+ return (
22+ < span aria-hidden = "true" >
23+ { text . split ( "" ) . map ( ( char , index ) => (
24+ < span
25+ key = { `${ text } -${ index } ` }
26+ className = { `typewriter-char inline-block ${ characterClassName } ` }
27+ style = { { animationDelay : `${ delayOffset + index * 50 } ms` } }
28+ >
29+ { char === " " ? "\u00A0" : char }
30+ </ span >
31+ ) ) }
32+ </ span >
33+ ) ;
34+ }
35+
1336export function HeroSection ( ) {
1437 const isVisible = true ;
1538 const [ wordIndex , setWordIndex ] = useState ( 0 ) ;
1639 const prefersReducedMotion = useReducedMotion ( ) ;
40+ const activeWord = words [ wordIndex ] ;
1741
1842 useEffect ( ( ) => {
1943 if ( prefersReducedMotion ) return ;
@@ -26,18 +50,14 @@ export function HeroSection() {
2650
2751 return (
2852 < section className = "relative flex min-h-screen flex-col justify-center overflow-hidden bg-background text-foreground" >
29- < div className = "absolute right-[-12 %] top-1/2 hidden h-[620px] w-[620px] -translate-y-1/2 pointer-events-none md:block lg:h-[820px] lg:w-[820px]" >
53+ < div className = "absolute right-[-6 %] top-1/2 hidden h-[620px] w-[620px] -translate-y-1/2 opacity-50 pointer-events-none mix-blend-multiply md:block lg:h-[820px] lg:w-[820px]" >
3054 < TubesBackground
3155 tone = "light"
3256 enableClickInteraction = { false }
33- className = "h-full min-h-full rounded-full border border-cyan-500/10 shadow-[0_30px_120px_rgba(6,182,212,0.16)] "
57+ className = "h-full min-h-full"
3458 />
3559 </ div >
3660
37- < div className = "absolute right-0 top-1/2 hidden h-[600px] w-[600px] -translate-y-1/2 opacity-25 pointer-events-none md:block lg:h-[800px] lg:w-[800px]" >
38- < AnimatedSphere />
39- </ div >
40-
4161 < div className = "absolute inset-0 overflow-hidden pointer-events-none opacity-30" >
4262 { [ ...Array ( 8 ) ] . map ( ( _ , i ) => (
4363 < div
@@ -69,27 +89,29 @@ export function HeroSection() {
6989
7090 < div className = "mb-12" >
7191 < h1
72- className = { `text-[clamp(3rem,12vw,10rem)] font-display leading-[0.9] tracking-tight transition-all duration-1000 ${
92+ aria-label = { `The place to ${ activeWord } AI` }
93+ className = { `max-w-6xl text-[clamp(3rem,12vw,10rem)] font-display leading-[0.92] tracking-normal transition-all duration-1000 ${
7394 isVisible ? "opacity-100 translate-y-0" : "opacity-0 translate-y-8"
7495 } `}
7596 >
76- < span className = "block" > The place to</ span >
77- < span className = "block" >
78- < span className = "relative inline-block brand-wordmark-text" >
79- < span key = { wordIndex } className = "inline-flex" >
80- { words [ wordIndex ] . split ( "" ) . map ( ( char , i ) => (
81- < span
82- key = { `${ wordIndex } -${ i } ` }
83- className = { prefersReducedMotion ? "inline-block" : "inline-block animate-char-in" }
84- style = { prefersReducedMotion ? undefined : { animationDelay : `${ i * 50 } ms` } }
85- >
86- { char }
87- </ span >
88- ) ) }
97+ < span className = "block" aria-hidden = "true" > The place to</ span >
98+ < span className = "mt-2 block md:mt-3" aria-hidden = "true" >
99+ < span className = "inline-flex items-baseline gap-[0.16em]" >
100+ < span className = "relative inline-flex min-w-[7.1ch] items-baseline md:min-w-[7.6ch]" >
101+ < span key = { wordIndex } className = "inline-flex" >
102+ { prefersReducedMotion ? (
103+ < span className = "brand-wordmark-text" > { activeWord } </ span >
104+ ) : (
105+ < TypedText text = { activeWord } characterClassName = "brand-wordmark-text" />
106+ ) }
107+ </ span >
108+ { prefersReducedMotion ? (
109+ null
110+ ) : < span className = "typewriter-caret ml-2 h-[0.72em] w-[0.06em] bg-cyan-600" /> }
111+ < span className = "absolute -bottom-2 left-0 h-2 w-full origin-left rounded-full bg-cyan-400/15 shadow-[0_0_28px_rgba(6,182,212,0.22)]" />
89112 </ span >
90- < span className = "absolute -bottom-2 left-0 right-0 h-3 bg-cyan-400/15 shadow-[0_0_28px_rgba(6,182,212,0.22)]" />
91- </ span > { " " }
92- AI
113+ < span > AI</ span >
114+ </ span >
93115 </ span >
94116 </ h1 >
95117 </ div >
0 commit comments