1- " use client"
1+ ' use client'
22
3- import Link from 'next/link' ;
4- import Image from 'next/image' ;
5- import { useState , useEffect , useRef } from 'react' ;
6- const images = [
7- '/assets/images/preview/shiro.png' ,
3+ import Link from 'next/link'
4+ import Image from 'next/image'
5+ import { useState , useEffect , useRef } from 'react'
6+ const images = [
7+ '/assets/images/preview/shiro.png' ,
88 '/assets/images/preview/kami.png' ,
9- '/assets/images/preview/console.png'
10- ] ;
11- const imageNames = [ 'Shiro主题' , 'Kami主题' , '控制台' ] ;
12- import { cn } from 'utils/cn' ;
13- import { buttonVariants } from 'app/components/ui/button' ;
14- import { LuCirclePlay } from " react-icons/lu" ;
15- import { FaGithub } from " react-icons/fa" ;
16- import { motion , AnimatePresence } from " framer-motion" ;
9+ '/assets/images/preview/console.png' ,
10+ ]
11+ const imageNames = [ 'Shiro 主题' , 'Kami 主题' , '控制台' ]
12+ import { cn } from 'utils/cn'
13+ import { buttonVariants } from 'app/components/ui/button'
14+ import { LuCirclePlay } from ' react-icons/lu'
15+ import { FaGithub } from ' react-icons/fa'
16+ import { motion , AnimatePresence } from ' framer-motion'
1717
1818export function Hero ( ) {
19- const [ currentImage , setCurrentImage ] = useState ( 0 ) ;
20- const [ isPaused , setIsPaused ] = useState ( false ) ;
21- const timerRef = useRef < NodeJS . Timeout | null > ( null ) ;
19+ const [ currentImage , setCurrentImage ] = useState ( 0 )
20+ const [ isPaused , setIsPaused ] = useState ( false )
21+ const timerRef = useRef < NodeJS . Timeout | null > ( null )
2222
2323 // 自动轮播功能
2424 useEffect ( ( ) => {
2525 if ( ! isPaused ) {
2626 timerRef . current = setInterval ( ( ) => {
27- setCurrentImage ( ( prev ) => ( prev + 1 ) % images . length ) ;
28- } , 5000 ) ;
27+ setCurrentImage ( ( prev ) => ( prev + 1 ) % images . length )
28+ } , 5000 )
2929 }
30-
30+
3131 return ( ) => {
32- if ( timerRef . current ) clearInterval ( timerRef . current ) ;
33- } ;
34- } , [ isPaused ] ) ;
32+ if ( timerRef . current ) clearInterval ( timerRef . current )
33+ }
34+ } , [ isPaused ] )
3535
3636 return (
3737 < div className = "container relative z-[2] flex flex-col overflow-hidden rounded-lg bg-background px-6 pt-12 max-md:text-center md:px-12 md:pt-16" >
3838 < div className = "md:flex md:items-center md:gap-8 mb-8" >
39- < div className = "flex-shrink-0 md:w-2/5" >
40- < Image
41- src = "/logo.png"
42- alt = "Mix Space Logo"
43- width = { 400 }
44- height = { 133 }
45- className = "max-w-full h-auto max-md:mx-auto"
46- priority
47- />
48- </ div >
49- < div className = "md:flex md:flex-col md:gap-4" >
50- < p className = "text-muted-foreground md:text-xl max-md:mt-4" >
51- Mix Space 是一个现代化的前后端分离个人空间解决方案,也可以作为个人博客使用。
52- </ p >
53-
54- < div className = "flex flex-wrap justify-center md:justify-start gap-4 mt-4 md:mt-2 mb-4" >
55- < Link
56- href = "/docs/core"
57- className = { cn (
58- buttonVariants ( { size : 'lg' , className : 'rounded-full min-w-[140px] justify-center' } ) ,
59- ) }
60- >
61- < LuCirclePlay className = "size-4 mr-2" /> 开始使用
62- </ Link >
63- < a
64- href = "https://github.com/mx-space"
65- className = { cn (
66- buttonVariants ( {
67- size : 'lg' ,
68- variant : 'outline' ,
69- className : 'rounded-full bg-background min-w-[140px] justify-center' ,
70- } ) ,
71- ) }
72- >
73- < FaGithub className = "size-4 mr-2" /> Github
74- </ a >
39+ < div className = "flex-shrink-0 md:w-2/5" >
40+ < Image
41+ src = "/logo.png"
42+ alt = "Mix Space Logo"
43+ width = { 400 }
44+ height = { 133 }
45+ className = "max-w-full h-auto max-md:mx-auto"
46+ priority
47+ />
48+ </ div >
49+ < div className = "md:flex md:flex-col md:gap-4" >
50+ < p className = "text-muted-foreground md:text-xl max-md:mt-4" >
51+ Mix Space
52+ 是一个现代化的前后端分离个人空间解决方案,也可以作为个人博客使用。
53+ </ p >
54+
55+ < div className = "flex flex-wrap justify-center md:justify-start gap-4 mt-4 md:mt-2 mb-4" >
56+ < Link
57+ href = "/docs/core"
58+ className = { cn (
59+ buttonVariants ( {
60+ size : 'lg' ,
61+ className : 'rounded-full min-w-[140px] justify-center' ,
62+ } ) ,
63+ ) }
64+ >
65+ < LuCirclePlay className = "size-4 mr-2" /> 开始使用
66+ </ Link >
67+ < a
68+ href = "https://github.com/mx-space"
69+ className = { cn (
70+ buttonVariants ( {
71+ size : 'lg' ,
72+ variant : 'outline' ,
73+ className :
74+ 'rounded-full bg-background min-w-[140px] justify-center' ,
75+ } ) ,
76+ ) }
77+ >
78+ < FaGithub className = "size-4 mr-2" /> Github
79+ </ a >
80+ </ div >
7581 </ div >
7682 </ div >
77- </ div >
78-
79- < div
83+
84+ < div
8085 className = "relative mt-6 md:mt-8 mb-12 overflow-visible"
8186 onMouseEnter = { ( ) => setIsPaused ( true ) }
8287 onMouseLeave = { ( ) => setIsPaused ( false ) }
8388 >
8489 < div className = "relative w-full overflow-visible" >
85- < div className = "w-full mx-auto overflow-hidden rounded-xl ring-1 ring-foreground/5 shadow-xl shadow-foreground/5 " >
90+ < div className = "w-full mx-auto overflow-hidden rounded-xl" >
8691 < div className = "relative aspect-video w-full bg-gradient-to-br from-secondary/20 to-secondary/10" >
87- < AnimatePresence initial = { false } mode = "wait " >
92+ < AnimatePresence initial = { false } mode = "popLayout " >
8893 < motion . div
8994 key = { currentImage }
9095 initial = { { opacity : 0 , scale : 0.95 } }
9196 animate = { { opacity : 1 , scale : 1 } }
9297 exit = { { opacity : 0 , scale : 0.95 } }
93- transition = { { duration : 0.5 } }
98+ transition = { { duration : 0.3 } }
9499 className = "absolute inset-0"
95100 >
96101 < Image
@@ -106,25 +111,25 @@ export function Hero() {
106111 </ AnimatePresence >
107112 </ div >
108113 </ div >
109-
110- < div className = "absolute bottom-3 md:bottom-[calc(var(--spacing)*4)] left-1/2 -translate-x-1/2 z-[2] flex flex-row border border-[var(--color-fd-border)] rounded-full bg-[var(--color-fd-card)] p-0.5 md:p-1 shadow-md shadow-[var(--color-fd-background)] overflow-x-auto max-w-[calc(100%-2rem)] no-scrollbar" >
114+
115+ < div className = "absolute bottom-3 md:bottom-[calc(var(--spacing)*4)] left-1/2 -translate-x-1/2 z-[2] flex flex-row border border-[var(--color-fd-border)] rounded-full bg-[var(--color-fd-card)] p-0.5 md:p-1 shadow-md shadow-[var(--color-fd-background)] overflow-x-auto max-w-[calc(100%-2rem)] no-scrollbar" >
111116 { imageNames . map ( ( name , index ) => (
112117 < button
113- key = { `title-${ index } ` }
114- onClick = { ( ) => setCurrentImage ( index ) }
115- className = { `px-2 md:px-4 py-1 md:py-2 rounded-full text-xs md:text-sm font-medium transition-all whitespace-nowrap ${
116- index === currentImage
117- ? 'bg-[var(--color-fd-accent)] text-[var(--color-fd-accent-foreground)]'
118- : 'text-[var(--color-fd-muted-foreground)] hover:bg-[var(--color-fd-secondary)] hover:text-[var(--color-fd-secondary-foreground)]'
119- } `}
120- aria-label = { `查看${ name } ` }
118+ key = { `title-${ index } ` }
119+ onClick = { ( ) => setCurrentImage ( index ) }
120+ className = { `px-2 md:px-4 py-1 md:py-2 rounded-full text-xs md:text-sm font-medium transition-all whitespace-nowrap ${
121+ index === currentImage
122+ ? 'bg-[var(--color-fd-accent)] text-[var(--color-fd-accent-foreground)]'
123+ : 'text-[var(--color-fd-muted-foreground)] hover:bg-[var(--color-fd-secondary)] hover:text-[var(--color-fd-secondary-foreground)]'
124+ } `}
125+ aria-label = { `查看${ name } ` }
121126 >
122- { name }
127+ { name }
123128 </ button >
124129 ) ) }
125- </ div >
130+ </ div >
126131 </ div >
127132 </ div >
128133 </ div >
129- ) ;
134+ )
130135}
0 commit comments