@@ -20,18 +20,10 @@ export default function Home() {
2020 < div className = "min-h-screen flex flex-col font-sans" >
2121 < Navbar />
2222 < Hero />
23- < StickyFadeSection zIndex = { 10 } heightVh = { 220 } fadeStart = { 0.60 } fadeEnd = { 0.92 } >
24- < Platforms />
25- </ StickyFadeSection >
26- < StickyFadeSection zIndex = { 20 } heightVh = { 220 } fadeStart = { 0.60 } fadeEnd = { 0.92 } >
27- < Providers />
28- </ StickyFadeSection >
29- < StickyFadeSection zIndex = { 30 } heightVh = { 200 } fadeStart = { 0.58 } fadeEnd = { 0.9 } >
30- < Plugins />
31- </ StickyFadeSection >
32- < StickyFadeSection zIndex = { 40 } heightVh = { 200 } fadeStart = { 0.58 } fadeEnd = { 0.9 } >
33- < Community />
34- </ StickyFadeSection >
23+ < Platforms />
24+ < Providers />
25+ < Plugins />
26+ < Community />
3527 < MoreThings />
3628 < GetStarted />
3729 < SiteFooter />
@@ -61,67 +53,6 @@ function useScrollY() {
6153 return scrollY ;
6254}
6355
64- // Compute a 0..1 fade progress for a tall wrapper with a sticky child
65- function useSectionFade (
66- wrapperRef : { current : HTMLElement | null } ,
67- fadeStart : number = 0.55 ,
68- fadeEnd : number = 0.9
69- ) {
70- const [ opacity , setOpacity ] = useState ( 1 ) ;
71- useEffect ( ( ) => {
72- if ( typeof window === "undefined" ) return ;
73- let raf = 0 as number | 0 ;
74- const update = ( ) => {
75- const el = wrapperRef . current as HTMLElement | null ;
76- if ( ! el ) return setOpacity ( 1 ) ;
77- const rect = el . getBoundingClientRect ( ) ;
78- const total = Math . max ( 1 , el . offsetHeight ) ;
79- const scrolled = Math . min ( Math . max ( 0 , - rect . top ) , total ) ;
80- const progress = scrolled / total ; // 0..1
81- const t = Math . min ( 1 , Math . max ( 0 , ( progress - fadeStart ) / Math . max ( 0.0001 , ( fadeEnd - fadeStart ) ) ) ) ;
82- const eased = 1 - ( t * t * ( 3 - 2 * t ) ) ; // smoothstep ease-out for fade
83- setOpacity ( eased ) ;
84- } ;
85- const onScroll = ( ) => {
86- if ( ! raf ) raf = requestAnimationFrame ( ( ) => { update ( ) ; raf = 0 as number | 0 ; } ) as unknown as number ;
87- } ;
88- const onResize = ( ) => { update ( ) ; } ;
89- update ( ) ;
90- window . addEventListener ( "scroll" , onScroll , { passive : true } ) ;
91- window . addEventListener ( "resize" , onResize , { passive : true } ) ;
92- return ( ) => {
93- if ( raf ) cancelAnimationFrame ( raf ) ;
94- window . removeEventListener ( "scroll" , onScroll ) ;
95- window . removeEventListener ( "resize" , onResize ) ;
96- } ;
97- } , [ wrapperRef , fadeStart , fadeEnd ] ) ;
98- return opacity ;
99- }
100-
101- function StickyFadeSection ( {
102- children,
103- zIndex,
104- heightVh = 200 ,
105- fadeStart = 0.6 ,
106- fadeEnd = 0.9 ,
107- } : {
108- children : React . ReactNode ;
109- zIndex : number ;
110- heightVh ?: number ;
111- fadeStart ?: number ;
112- fadeEnd ?: number ;
113- } ) {
114- const wrapperRef = useRef < HTMLElement | null > ( null ) ;
115- const opacity = useSectionFade ( wrapperRef , fadeStart , fadeEnd ) ;
116- return (
117- < section ref = { wrapperRef } className = "relative" style = { { height : `${ heightVh } vh` } } >
118- < div className = "sticky top-16" style = { { zIndex, opacity } } >
119- { children }
120- </ div >
121- </ section >
122- ) ;
123- }
124-
12556function Navbar ( ) {
12657 const [ openLang , setOpenLang ] = useState ( false ) ;
12758 const [ openMenu , setOpenMenu ] = useState ( false ) ;
@@ -221,7 +152,7 @@ function Navbar() {
221152 < ChevronDownIcon aria-hidden className = { `w-4 h-4 transition-transform duration-200 ${ openLang ? 'rotate-180' : '' } ` } />
222153 </ button >
223154 { openLang && (
224- < ul className = "absolute right-0 mt-3 w-28 rounded-lg border border-ui bg-background shadow-lg origin-top-right animate-dropdown" >
155+ < ul className = "absolute right-0 mt-5 w-28 rounded-lg border border-ui bg-background shadow-lg origin-top-right animate-dropdown" >
225156 < li className = "px-3 py-2 hover:bg-black/[.04] dark:hover:bg-white/[.06] cursor-pointer" onClick = { ( ) => { setLocale ( "zh-CN" ) ; setOpenLang ( false ) ; } } > 简体中文</ li >
226157 < li className = "px-3 py-2 hover:bg-black/[.04] dark:hover:bg-white/[.06] cursor-pointer" onClick = { ( ) => { setLocale ( "en-US" ) ; setOpenLang ( false ) ; } } > English</ li >
227158 < li className = "px-3 py-2 hover:bg-black/[.04] dark:hover:bg-white/[.06] cursor-pointer" onClick = { ( ) => { setLocale ( "ja-JP" ) ; setOpenLang ( false ) ; } } > 日本語</ li >
@@ -476,8 +407,6 @@ function Platforms() {
476407
477408function Providers ( ) {
478409 const { t } = useI18n ( ) ;
479- const scrollY = useScrollY ( ) ;
480- const provParallax = { transform : `translateY(${ scrollY * 0.03 } px)` , willChange : "transform" } as React . CSSProperties ;
481410 const items = [
482411 { name : "OpenAI" , src : "https://registry.npmmirror.com/@lobehub/icons-static-svg/latest/files/icons/openai.svg" } ,
483412 { name : "xAI" , src : "https://registry.npmmirror.com/@lobehub/icons-static-svg/latest/files/icons/xai.svg" } ,
@@ -500,11 +429,7 @@ function Providers() {
500429 { name : "FastGPT" , src : "https://registry.npmmirror.com/@lobehub/icons-static-svg/latest/files/icons/fastgpt-color.svg" } ,
501430 ] ;
502431 return (
503- < section className = "relative overflow-hidden min-h-[calc(100vh-64px)] flex items-center py-12 sm:py-16" style = { { backgroundColor : "var(--section-surface)" } } >
504- < div aria-hidden className = "pointer-events-none absolute inset-0 -z-10" style = { provParallax } >
505- < div className = "absolute -top-8 -left-10 w-64 h-64 rounded-full blur-3xl opacity-15 brand-bg animate-orb-pulse" />
506- < div className = "absolute bottom-[-40px] right-1/4 w-72 h-72 rounded-full blur-3xl opacity-10 animate-orb-pulse" style = { { backgroundColor : "#22d3ee" } } />
507- </ div >
432+ < section className = "min-h-[calc(100vh-64px)] flex items-center py-12 sm:py-16" >
508433 < div className = "mx-auto max-w-6xl px-4 sm:px-6" >
509434 < Reveal as = "h2" className = "text-center text-3xl sm:text-4xl font-semibold tracking-tight mb-6 sm:mb-8 gradient-title" delay = { 0 } > { t ( "models.title" ) } </ Reveal >
510435 < Reveal as = "p" className = "text-center mt-2 text-sm opacity-80 mb-10 sm:mb-12" delay = { 150 } > { t ( "models.subtitle" ) } </ Reveal >
@@ -658,8 +583,6 @@ function Plugins() {
658583
659584function Community ( ) {
660585 const { t } = useI18n ( ) ;
661- const scrollY = useScrollY ( ) ;
662- const commParallax = { transform : `translateY(${ scrollY * 0.02 } px)` , willChange : "transform" } as React . CSSProperties ;
663586 const [ stats , setStats ] = useState < { stars : number ; forks : number ; contributors : number ; plugins : number } > ( { stars : 0 , forks : 0 , contributors : 0 , plugins : 0 } ) ;
664587 useEffect ( ( ) => {
665588 fetch ( "/api/plugins" , { cache : "no-store" } )
@@ -688,11 +611,7 @@ function Community() {
688611 ) ;
689612
690613 return (
691- < section className = "relative overflow-hidden py-12 sm:py-16" style = { { backgroundColor : "var(--section-surface)" } } >
692- < div aria-hidden className = "pointer-events-none absolute inset-0 -z-10" style = { commParallax } >
693- < div className = "absolute top-[-20px] right-[-40px] w-60 h-60 rounded-full blur-3xl opacity-10 brand-bg animate-orb-pulse" />
694- < div className = "absolute bottom-[-50px] left-1/5 w-72 h-72 rounded-full blur-3xl opacity-10" style = { { backgroundColor : "#a78bfa" } } />
695- </ div >
614+ < section className = "py-12 sm:py-16" >
696615 < div className = "mx-auto max-w-6xl px-4 sm:px-6" >
697616 < Reveal as = "h2" className = "text-center text-3xl sm:text-4xl font-semibold tracking-tight gradient-title" delay = { 0 } > { t ( "community.title" ) } </ Reveal >
698617 < Reveal as = "p" className = "text-center mt-2 mb-10 text-sm opacity-80" delay = { 150 } > { t ( "community.subtitle" ) } </ Reveal >
0 commit comments