@@ -25,24 +25,23 @@ interface BlogListProps {
2525export function BlogList ( { blogs } : BlogListProps ) {
2626 const [ filteredBlogs , setFilteredBlogs ] = useState < BlogPost [ ] > ( blogs ) ;
2727 const handleFilteredResults = useCallback ( ( filtered : BlogPost [ ] ) => { setFilteredBlogs ( filtered ) } , [ ] ) ;
28- const [ featured , ...others ] = filteredBlogs ;
2928
3029 return (
3130 < >
32- < section className = "mt-8 sm:mt-12 " >
31+ < section className = "mt-8 sm:mt-10 " >
3332 < BlogSearch blogs = { blogs } onFilteredResults = { handleFilteredResults } />
3433 </ section >
3534
3635 { filteredBlogs . length !== blogs . length && (
37- < section className = "text-center mb-6" >
36+ < section className = "text-center mb-6 mt-6 " >
3837 < p className = "text-sm text-muted-foreground" >
3938 Showing { filteredBlogs . length } of { blogs . length } blog posts
4039 </ p >
4140 </ section >
4241 ) }
4342
4443 { filteredBlogs . length === 0 && (
45- < section className = "text-center py-12 " >
44+ < section className = "text-center py-16 " >
4645 < p className = "text-lg text-muted-foreground mb-2" >
4746 No matching blog posts found
4847 </ p >
@@ -52,108 +51,140 @@ export function BlogList({ blogs }: BlogListProps) {
5251 </ section >
5352 ) }
5453
55- { /* Featured Post */ }
56- { featured && (
57- < section className = "mt-6 sm:mt-8" >
58- < Link
59- href = { featured . url }
60- className = "group block overflow-hidden rounded-xl border border-white/20 bg-card/80 p-6 sm:p-8 shadow-sm transition duration-300 hover:border-[#E84142]/60 hover:shadow-[0_0_0_1px_rgba(232,65,66,0.6),0_0_30px_6px_rgba(232,65,66,0.35)] dark:bg-card-dark/80"
61- >
62- < div className = "flex flex-col gap-4" >
63- < div className = "flex items-center justify-between" >
64- < p className = "text-xs text-muted-foreground" >
65- { new Date (
66- featured . data . date ?? featured . url
67- ) . toDateString ( ) }
68- </ p >
69- < span className = "rounded-full bg-primary/10 px-3 py-1 text-xs font-medium text-primary" >
70- Featured
71- </ span >
72- </ div >
54+ { /* Blog Grid */ }
55+ { filteredBlogs . length > 0 && (
56+ < section className = "mt-10 sm:mt-12" >
57+ { /* Featured Post - Full Width */ }
58+ { filteredBlogs [ 0 ] && (
59+ < Link
60+ href = { filteredBlogs [ 0 ] . url }
61+ className = "group relative flex flex-col md:flex-row gap-6 rounded-xl border border-primary/30 bg-gradient-to-br from-card/80 to-card/60 backdrop-blur-sm p-6 md:p-8 shadow-lg transition-all duration-300 hover:border-primary/50 hover:shadow-xl hover:shadow-primary/10 hover:-translate-y-0.5 dark:from-card-dark/80 dark:to-card-dark/60 dark:border-white/20 dark:hover:border-white/30 mb-8"
62+ >
63+ { /* Hover gradient overlay */ }
64+ < div className = "absolute inset-0 bg-gradient-to-br from-primary/5 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 rounded-xl" />
7365
74- < h2 className = "text-2xl sm:text-3xl font-bold tracking-tight" >
75- { featured . data . title }
76- </ h2 >
77-
78- < p className = "text-sm sm:text-base text-muted-foreground max-w-3xl" >
79- { featured . data . description }
80- </ p >
81-
82- < div className = "flex flex-wrap items-center gap-2 text-xs sm:text-sm" >
83- { featured . data . topics . map ( ( topic : string ) => (
84- < span
85- key = { topic }
86- className = "rounded-full bg-fd-accent px-3 py-1.5 font-medium text-muted-foreground"
87- >
88- { topic }
66+ < div className = "relative flex-1 flex flex-col" >
67+ { /* Header */ }
68+ < div className = "flex items-center gap-3 mb-3" >
69+ < span className = "rounded-full bg-primary/15 px-3 py-1 text-xs font-semibold text-primary ring-1 ring-primary/20" >
70+ Latest
8971 </ span >
90- ) ) }
91- </ div >
72+ < time className = "text-xs font-medium text-muted-foreground/70 uppercase tracking-wider" >
73+ { new Date ( filteredBlogs [ 0 ] . data . date ?? filteredBlogs [ 0 ] . url ) . toDateString ( ) }
74+ </ time >
75+ </ div >
9276
93- < div className = "mt-2 flex flex-wrap items-center gap-3 text-sm text-muted-foreground" >
94- { featured . data . authors . map ( ( author : string ) => (
95- < span key = { author } className = "inline-flex items-center gap-2" >
96- < X size = { 12 } />
97- < span className = "truncate" > { author } </ span >
98- </ span >
99- ) ) }
100- < span className = "ml-auto inline-flex items-center gap-1 text-primary" >
101- Read article{ " " }
102- < ArrowRight
103- size = { 14 }
104- className = "transition-transform group-hover:translate-x-0.5"
105- />
106- </ span >
107- </ div >
108- </ div >
109- </ Link >
110- </ section >
111- ) }
77+ { /* Title */ }
78+ < h3 className = "text-2xl md:text-3xl font-bold tracking-tight leading-tight transition-colors group-hover:text-primary mb-3" >
79+ { filteredBlogs [ 0 ] . data . title }
80+ </ h3 >
11281
113- { /* All Posts */ }
114- { others . length > 0 && (
115- < section className = "mt-12 sm:mt-16" >
116- < h3 className = "mb-6 text-lg font-semibold tracking-tight text-foreground/90" >
117- { filteredBlogs . length === blogs . length
118- ? "Latest posts"
119- : "More matching posts" }
120- </ h3 >
121- < div className = "grid grid-cols-1 md:grid-cols-2 gap-5" >
122- { others . map ( ( g ) => (
123- < Link
124- key = { g . url }
125- href = { g . url }
126- className = "flex flex-col gap-2 rounded-lg border border-white/20 bg-card p-4 shadow-sm transition duration-300 hover:border-[#E84142]/60 hover:shadow-[0_0_0_1px_rgba(232,65,66,0.6),0_0_24px_5px_rgba(232,65,66,0.3)] dark:bg-card-dark"
127- >
128- < p className = "text-xs text-muted-foreground" >
129- { new Date ( g . data . date ?? g . url ) . toDateString ( ) }
130- </ p >
131- < h4 className = "text-xl font-semibold tracking-tight" >
132- { g . data . title }
133- </ h4 >
134- < p className = "text-sm text-muted-foreground line-clamp-3" >
135- { g . data . description }
82+ { /* Description */ }
83+ < p className = "text-base text-muted-foreground/90 leading-relaxed mb-4 line-clamp-2" >
84+ { filteredBlogs [ 0 ] . data . description }
13685 </ p >
137- < div className = "mt-2 flex flex-wrap items-center gap-2 text-xs" >
138- { g . data . topics . map ( ( topic : string ) => (
86+
87+ { /* Topics */ }
88+ < div className = "flex flex-wrap items-center gap-2 mb-4" >
89+ { filteredBlogs [ 0 ] . data . topics . slice ( 0 , 4 ) . map ( ( topic : string ) => (
13990 < span
14091 key = { topic }
141- className = "rounded-full bg-fd-accent px-3 py-1.5 font-medium text-muted- foreground"
92+ className = "rounded-full bg-secondary/70 px-3 py-1.5 text-xs font-medium text-foreground/80 transition-colors group-hover:bg-secondary "
14293 >
14394 { topic }
14495 </ span >
14596 ) ) }
97+ { filteredBlogs [ 0 ] . data . topics . length > 4 && (
98+ < span className = "text-xs text-muted-foreground" >
99+ +{ filteredBlogs [ 0 ] . data . topics . length - 4 }
100+ </ span >
101+ ) }
146102 </ div >
147- < div className = "mt-1 flex flex-wrap items-center gap-2 text-sm text-muted-foreground" >
148- { g . data . authors . map ( ( author : string ) => (
149- < span
150- key = { author }
151- className = "inline-flex items-center gap-2"
152- >
153- < X size = { 12 } />
154- < span className = "truncate" > { author } </ span >
103+
104+ { /* Authors & Read More */ }
105+ < div className = "flex flex-wrap items-center justify-between gap-3 pt-3 mt-auto border-t border-border/30" >
106+ < div className = "flex flex-wrap items-center gap-3 text-sm text-muted-foreground/80" >
107+ { filteredBlogs [ 0 ] . data . authors . slice ( 0 , 2 ) . map ( ( author : string ) => (
108+ < span key = { author } className = "inline-flex items-center gap-1.5" >
109+ < X size = { 12 } />
110+ < span className = "truncate font-medium text-xs" > { author } </ span >
111+ </ span >
112+ ) ) }
113+ { filteredBlogs [ 0 ] . data . authors . length > 2 && (
114+ < span className = "text-xs" > +{ filteredBlogs [ 0 ] . data . authors . length - 2 } </ span >
115+ ) }
116+ </ div >
117+ < span className = "inline-flex items-center gap-1.5 text-sm font-medium text-primary transition-transform group-hover:translate-x-1" >
118+ Read article
119+ < ArrowRight size = { 16 } className = "transition-transform group-hover:translate-x-0.5" />
120+ </ span >
121+ </ div >
122+ </ div >
123+ </ Link >
124+ ) }
125+
126+ { /* Regular Grid */ }
127+ < div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" >
128+ { filteredBlogs . slice ( 1 ) . map ( ( post ) => (
129+ < Link
130+ key = { post . url }
131+ href = { post . url }
132+ className = "group relative flex flex-col rounded-xl border border-border/50 bg-card/60 backdrop-blur-sm shadow-md transition-all duration-300 hover:border-primary/40 hover:shadow-xl hover:shadow-primary/10 hover:-translate-y-1 dark:bg-card-dark/60 dark:border-white/20 dark:hover:border-white/30 overflow-hidden"
133+ >
134+ { /* Hover gradient overlay */ }
135+ < div className = "absolute inset-0 bg-gradient-to-br from-primary/5 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
136+
137+ < div className = "relative flex flex-col h-full p-6" >
138+ { /* Header */ }
139+ < time className = "text-xs font-medium text-muted-foreground/70 uppercase tracking-wider mb-3" >
140+ { new Date ( post . data . date ?? post . url ) . toDateString ( ) }
141+ </ time >
142+
143+ { /* Title */ }
144+ < h4 className = "text-xl font-bold tracking-tight leading-snug transition-colors group-hover:text-primary mb-3" >
145+ { post . data . title }
146+ </ h4 >
147+
148+ { /* Description */ }
149+ < p className = "text-sm text-muted-foreground/90 leading-relaxed mb-4 flex-grow line-clamp-3" >
150+ { post . data . description }
151+ </ p >
152+
153+ { /* Topics */ }
154+ < div className = "flex flex-wrap items-center gap-2 mb-4" >
155+ { post . data . topics . slice ( 0 , 3 ) . map ( ( topic : string ) => (
156+ < span
157+ key = { topic }
158+ className = "rounded-full bg-secondary/70 px-3 py-1.5 text-xs font-medium text-foreground/80 transition-colors group-hover:bg-secondary"
159+ >
160+ { topic }
161+ </ span >
162+ ) ) }
163+ { post . data . topics . length > 3 && (
164+ < span className = "text-xs text-muted-foreground" >
165+ +{ post . data . topics . length - 3 }
166+ </ span >
167+ ) }
168+ </ div >
169+
170+ { /* Authors & Read More */ }
171+ < div className = "flex flex-wrap items-center justify-between gap-3 pt-3 border-t border-border/30" >
172+ < div className = "flex flex-wrap items-center gap-3 text-sm text-muted-foreground/80" >
173+ { post . data . authors . slice ( 0 , 2 ) . map ( ( author : string ) => (
174+ < span key = { author } className = "inline-flex items-center gap-1.5" >
175+ < X size = { 12 } />
176+ < span className = "truncate font-medium text-xs" > { author } </ span >
177+ </ span >
178+ ) ) }
179+ { post . data . authors . length > 2 && (
180+ < span className = "text-xs" > +{ post . data . authors . length - 2 } </ span >
181+ ) }
182+ </ div >
183+ < span className = "inline-flex items-center gap-1.5 text-xs font-medium text-primary transition-transform group-hover:translate-x-1" >
184+ Read
185+ < ArrowRight size = { 14 } className = "transition-transform group-hover:translate-x-0.5" />
155186 </ span >
156- ) ) }
187+ </ div >
157188 </ div >
158189 </ Link >
159190 ) ) }
0 commit comments