File tree Expand file tree Collapse file tree 6 files changed +173
-47
lines changed Expand file tree Collapse file tree 6 files changed +173
-47
lines changed Original file line number Diff line number Diff line change
1
+ 'use client' ;
2
+
3
+ import React from 'react' ;
4
+ import { m } from 'framer-motion' ;
5
+
6
+ import { NormalContainer } from '@/components/layout/container/Normal' ;
7
+ import { PostItem } from '@/components/modules/list/PostItem' ;
8
+
9
+ // 假数据
10
+ const mockData = [
11
+ { id : 1 , title : '文章标题 1' , content : '这是文章内容 1' } ,
12
+ { id : 2 , title : '文章标题 2' , content : '这是文章内容 2' } ,
13
+ { id : 3 , title : '文章标题 3' , content : '这是文章内容 3' } ,
14
+ { id : 12 , title : '文章标题 1' , content : '这是文章内容 1' } ,
15
+ { id : 22 , title : '文章标题 2' , content : '这是文章内容 2' } ,
16
+ { id : 32 , title : '文章标题 3' , content : '这是文章内容 3' } ,
17
+
18
+ // 更多假数据
19
+ ] ;
20
+
21
+ const ArticleList : React . FC = ( ) => {
22
+ return (
23
+ < NormalContainer >
24
+ < ul >
25
+ { mockData . map ( ( item , index ) => (
26
+ < m . li
27
+ initial = { { y : 50 , opacity : 0.01 } }
28
+ animate = { {
29
+ y : 0 ,
30
+ opacity : 1 ,
31
+ transition : {
32
+ delay : index * 0.1 ,
33
+ type : 'spring' ,
34
+ damping : 10 ,
35
+ stiffness : 100 ,
36
+ } ,
37
+ } }
38
+ key = { item . id }
39
+ >
40
+ < PostItem data = { item } />
41
+ </ m . li >
42
+ ) ) }
43
+ </ ul >
44
+ </ NormalContainer >
45
+ ) ;
46
+ } ;
47
+
48
+ export default ArticleList ;
Original file line number Diff line number Diff line change
1
+ import type { SVGProps } from 'react' ;
2
+
3
+ export function FeHash ( props : SVGProps < SVGSVGElement > ) {
4
+ return (
5
+ < svg width = "1em" height = "1em" viewBox = "0 0 24 24" { ...props } >
6
+ < path
7
+ fill = "currentColor"
8
+ fillRule = "evenodd"
9
+ d = "M10 15h4V9h-4v6Zm0 2v3a1 1 0 0 1-2 0v-3H5a1 1 0 0 1 0-2h3V9H5a1 1 0 1 1 0-2h3V4a1 1 0 1 1 2 0v3h4V4a1 1 0 0 1 2 0v3h3a1 1 0 0 1 0 2h-3v6h3a1 1 0 0 1 0 2h-3v3a1 1 0 0 1-2 0v-3h-4Z"
10
+ />
11
+ </ svg >
12
+ ) ;
13
+ }
Original file line number Diff line number Diff line change @@ -6,7 +6,7 @@ const Footer = () => {
6
6
return (
7
7
< footer
8
8
data-hide-print
9
- className = "relative z-[1] h-28 mt-32 pb-6 border-t border-x-uk-separator-opaque-light py-6 text-base-content/80 dark:border-white/10"
9
+ className = "relative z-[1] h-28 mt-44 pb-6 border-t border-x-uk-separator-opaque-light py-6 text-base-content/80 dark:border-white/10"
10
10
>
11
11
< div className = "px-4 sm:px-8 h-full" >
12
12
< div className = "relative mx-auto max-w-7xl lg:px-8 h-full flex flex-row items-center justify-around" >
Original file line number Diff line number Diff line change @@ -8,14 +8,10 @@ import Link from 'next/link';
8
8
import { MenuPopover } from './MenuPopover' ;
9
9
10
10
import {
11
- FaSolidCircleNotch ,
12
11
FaSolidComments ,
13
12
FaSolidDotCircle ,
14
13
FaSolidFeatherAlt ,
15
- FaSolidHistory ,
16
14
FaSolidUserFriends ,
17
- IcTwotoneSignpost ,
18
- IonBook ,
19
15
MdiFlask ,
20
16
} from '@/components/icons/menu-collection' ;
21
17
import { cn } from '@/lib/helper' ;
@@ -186,56 +182,23 @@ const headerMenuConfig: IHeaderMenu[] = [
186
182
} ,
187
183
{
188
184
title : '文稿' ,
189
- path : '/posts' ,
190
- type : 'Post' ,
191
- subMenu : [ ] ,
192
- icon : React . createElement ( IcTwotoneSignpost ) ,
193
- } ,
194
- {
195
- title : '手记' ,
196
185
type : 'Note' ,
197
- path : '/notes ' ,
186
+ path : '/list ' ,
198
187
icon : React . createElement ( FaSolidFeatherAlt ) ,
199
188
} ,
200
-
201
- {
202
- title : '时光' ,
203
- icon : React . createElement ( FaSolidHistory ) ,
204
- path : '/timeline' ,
205
- subMenu : [
206
- {
207
- title : '手记' ,
208
- icon : React . createElement ( FaSolidFeatherAlt ) ,
209
- path : '/timeline?type=note' ,
210
- } ,
211
- {
212
- title : '文稿' ,
213
- icon : React . createElement ( IonBook ) ,
214
- path : '/timeline?type=post' ,
215
- } ,
216
- ] ,
217
- } ,
218
189
{
219
190
title : '友链' ,
220
191
icon : React . createElement ( FaSolidUserFriends ) ,
221
192
path : '/friends' ,
222
193
} ,
223
-
224
194
{
225
- title : '更多' ,
226
- icon : React . createElement ( FaSolidCircleNotch ) ,
227
- path : '#' ,
228
- subMenu : [
229
- {
230
- title : '项目' ,
231
- icon : React . createElement ( MdiFlask ) ,
232
- path : '/projects' ,
233
- } ,
234
- {
235
- title : '自述' ,
236
- path : '/about' ,
237
- icon : React . createElement ( FaSolidComments ) ,
238
- } ,
239
- ] ,
195
+ title : '项目' ,
196
+ icon : React . createElement ( MdiFlask ) ,
197
+ path : '/projects' ,
198
+ } ,
199
+ {
200
+ title : '自述' ,
201
+ path : '/about' ,
202
+ icon : React . createElement ( FaSolidComments ) ,
240
203
} ,
241
204
] ;
Original file line number Diff line number Diff line change
1
+ import Link from 'next/link' ;
2
+ import { memo } from 'react' ;
3
+
4
+ import { PostItemHoverOverlay } from './PostItemHoverOverlay' ;
5
+
6
+ import { MdiClockOutline } from '@/components/icons/clock' ;
7
+ import { FeHash } from '@/components/icons/fa-hash' ;
8
+
9
+ export const PostItem = memo < { data : any } > ( function PostItem ( { data } ) {
10
+ const categorySlug = data . category ?. slug ;
11
+ const postLink = `/posts/${ categorySlug } /${ data . slug } ` ;
12
+
13
+ return (
14
+ < Link href = { postLink } className = "relative flex flex-col py-8 focus-visible:!shadow-none" >
15
+ < PostItemHoverOverlay />
16
+ < h2 className = "relative text-balance break-words text-2xl font-medium" > { data . title } </ h2 >
17
+
18
+ < div className = "post-meta-bar mt-2 flex select-none flex-wrap items-center justify-start gap-8 text-base-content/60" >
19
+ < span className = " flex min-w-0 items-center space-x-1 text-sm" >
20
+ < MdiClockOutline />
21
+ < p > 2024 年 6 月 4 日 星期二</ p >
22
+ </ span >
23
+ < span className = "flex min-w-0 items-center space-x-1 text-sm" >
24
+ < FeHash className = "translate-y-[0.5px]" />
25
+ < p > 技术/react</ p >
26
+ </ span >
27
+ </ div >
28
+ </ Link >
29
+ ) ;
30
+ } ) ;
Original file line number Diff line number Diff line change
1
+ 'use client' ;
2
+
3
+ import clsx from 'clsx' ;
4
+ import { AnimatePresence , m } from 'framer-motion' ;
5
+ import { useEffect , useRef , useState } from 'react' ;
6
+
7
+ export const PostItemHoverOverlay = ( ) => {
8
+ const [ mouseEnter , setMouseEnter ] = useState ( false ) ;
9
+ const ref = useRef < HTMLDivElement > ( null ) ;
10
+ useEffect ( ( ) => {
11
+ const $ref = ref . current ;
12
+ if ( ! $ref ) return ;
13
+
14
+ const $parent = $ref . parentElement ;
15
+
16
+ if ( ! $parent ) return ;
17
+
18
+ $parent . onfocus = ( ) => {
19
+ setMouseEnter ( true ) ;
20
+ } ;
21
+
22
+ $parent . onblur = ( ) => {
23
+ setMouseEnter ( false ) ;
24
+ } ;
25
+
26
+ return ( ) => {
27
+ $parent . onfocus = null ;
28
+ $parent . onblur = null ;
29
+ } ;
30
+ } , [ ] ) ;
31
+
32
+ return (
33
+ < >
34
+ < div
35
+ ref = { ref }
36
+ className = "absolute inset-0 z-10"
37
+ onMouseEnter = { ( ) => {
38
+ setMouseEnter ( true ) ;
39
+ } }
40
+ onMouseLeave = { ( ) => {
41
+ setMouseEnter ( false ) ;
42
+ } }
43
+ />
44
+
45
+ < AnimatePresence >
46
+ { mouseEnter && (
47
+ < m . div
48
+ layout
49
+ initial = { {
50
+ opacity : 0.2 ,
51
+ scale : 0.95 ,
52
+ } }
53
+ animate = { {
54
+ opacity : 1 ,
55
+ scale : 1 ,
56
+ } }
57
+ exit = { {
58
+ opacity : 0 ,
59
+ scale : 0.95 ,
60
+ } }
61
+ layoutId = "post-item-hover-overlay"
62
+ className = { clsx (
63
+ 'absolute z-[-1] rounded-xl' ,
64
+ 'bg-accent/10 dark:bg-neutral-800' ,
65
+ 'inset-y-4 -left-4 -right-6' ,
66
+ ) }
67
+ />
68
+ ) }
69
+ </ AnimatePresence >
70
+ </ >
71
+ ) ;
72
+ } ;
You can’t perform that action at this time.
0 commit comments