@@ -10,7 +10,7 @@ import { formatDistanceToNow } from "date-fns";
1010
1111import { Button } from "@/components/ui/button" ;
1212import { UserAvatar } from "@/components/user-avatar" ;
13- import { RichTextViewer } from "@/components/editor/rich-text-viewer " ;
13+ import { cn } from "@/lib/utils " ;
1414
1515interface ForumContentProps {
1616 challengeId : string ;
@@ -27,42 +27,42 @@ export function ForumContent({ challengeId }: ForumContentProps) {
2727 < div >
2828 < div className = "mb-6 flex items-center justify-between" >
2929 < h1 className = "text-2xl font-bold" > Forum</ h1 >
30- < Button asChild >
30+ < Button asChild size = "sm" >
3131 < Link href = { `/challenges/${ challengeId } /forum/new` } >
3232 < Plus className = "h-4 w-4" />
3333 New Post
3434 </ Link >
3535 </ Button >
3636 </ div >
3737
38- < div className = "space-y-2 " >
38+ < div className = "divide-y divide-zinc-800/70 " >
3939 { results . map ( ( item ) => (
4040 < ForumPostCard
4141 key = { item . post . _id }
4242 item = { item }
4343 challengeId = { challengeId }
4444 />
4545 ) ) }
46+ </ div >
4647
47- { status === "CanLoadMore" && (
48- < div className = "pt-4 text-center" >
49- < Button variant = "outline" onClick = { ( ) => loadMore ( 20 ) } >
50- Load more
51- </ Button >
52- </ div >
53- ) }
48+ { status === "CanLoadMore" && (
49+ < div className = "pt-6 text-center" >
50+ < Button variant = "outline" size = "sm " onClick = { ( ) => loadMore ( 20 ) } >
51+ Load more
52+ </ Button >
53+ </ div >
54+ ) }
5455
55- { results . length === 0 && status !== "LoadingFirstPage" && (
56- < div className = "py-12 text-center text-zinc-500" >
57- < MessageSquare className = "mx-auto mb-3 h-8 w-8" />
58- < p > No posts yet. Start the conversation!</ p >
59- </ div >
60- ) }
56+ { results . length === 0 && status !== "LoadingFirstPage" && (
57+ < div className = "py-16 text-center text-zinc-500" >
58+ < MessageSquare className = "mx-auto mb-3 h-8 w-8" />
59+ < p className = "text-sm" > No posts yet. Start the conversation!</ p >
60+ </ div >
61+ ) }
6162
62- { status === "LoadingFirstPage" && (
63- < div className = "py-12 text-center text-zinc-500" > Loading...</ div >
64- ) }
65- </ div >
63+ { status === "LoadingFirstPage" && (
64+ < div className = "py-16 text-center text-zinc-500 text-sm" > Loading...</ div >
65+ ) }
6666 </ div >
6767 ) ;
6868}
@@ -109,70 +109,70 @@ const ForumPostCard = memo(function ForumPostCard({ item, challengeId }: ForumPo
109109 return (
110110 < Link
111111 href = { `/challenges/${ challengeId } /forum/${ item . post . _id } ` }
112- className = "flex gap-3 rounded-lg border border-zinc-800 p-4 transition-colors hover:border-zinc-700 hover:bg-zinc-900/50"
112+ className = { cn (
113+ "flex gap-3 py-3 transition-colors hover:bg-zinc-900/40" ,
114+ item . post . isPinned && "bg-amber-500/[0.02]" ,
115+ ) }
113116 >
114117 { /* Upvote column */ }
115- < div className = "flex flex-col items-center gap-1 " >
118+ < div className = "flex w-10 shrink-0 flex-col items-center pt-0.5 " >
116119 < button
117120 onClick = { handleUpvote }
118121 disabled = { isUpvoting }
119- className = { `rounded p-1 transition-colors ${
122+ className = { cn (
123+ "rounded p-1 transition-colors active:scale-95" ,
120124 item . upvotedByUser
121- ? "text-indigo-400 hover:text-indigo-300 "
122- : "text-zinc-500 hover:text-zinc-300"
123- } ` }
125+ ? "text-indigo-400"
126+ : "text-zinc-600 hover:text-zinc-400" ,
127+ ) }
124128 >
125129 < ArrowBigUp
126130 className = "h-5 w-5"
127131 fill = { item . upvotedByUser ? "currentColor" : "none" }
128132 />
129133 </ button >
130134 < span
131- className = { `text-xs font-medium ${
132- item . upvotedByUser ? "text-indigo-400" : "text-zinc-500"
133- } `}
135+ className = { cn (
136+ "text-xs font-mono font-medium" ,
137+ item . upvotedByUser ? "text-indigo-400" : "text-zinc-500" ,
138+ ) }
134139 >
135140 { item . upvoteCount }
136141 </ span >
137142 </ div >
138143
139- { /* Content column */ }
144+ { /* Content */ }
140145 < div className = "min-w-0 flex-1" >
141- < div className = "flex items-center gap-2" >
146+ { /* Title row */ }
147+ < div className = "flex items-center gap-1.5" >
142148 { item . post . isPinned && (
143- < Pin className = "h-3 w-3 flex- shrink-0 text-amber-400" />
149+ < Pin className = "h-3 w-3 shrink-0 rotate-45 text-amber-400" />
144150 ) }
145- < h3 className = "truncate font-semibold text-white " >
151+ < h3 className = "truncate text-sm font-semibold text-zinc-100 " >
146152 { item . post . title }
147153 </ h3 >
148154 </ div >
149155
150- < div className = "mt-1 line-clamp-2 text-sm text-zinc-400 [&_*]:text-zinc-400" >
151- < RichTextViewer content = { item . post . content } />
152- </ div >
153-
154- < div className = "mt-2 flex items-center gap-2 text-xs text-zinc-500" >
156+ { /* Meta line */ }
157+ < div className = "mt-1 flex items-center gap-1.5 text-xs text-zinc-500" >
155158 { item . user && (
156- < UserAvatar
157- user = { item . user }
158- size = "sm"
159- />
160- ) }
161- < span className = "flex flex-wrap items-center gap-x-2 gap-y-1" >
162- { item . user && (
159+ < >
160+ < UserAvatar user = { item . user } size = "xs" disableLink />
163161 < span className = "font-medium text-zinc-400" >
164- { item . user . name || item . user . username }
162+ { item . user . username }
165163 </ span >
166- ) }
167- < span >
168- { formatDistanceToNow ( new Date ( item . post . createdAt ) , {
169- addSuffix : true ,
170- } ) }
171- </ span >
172- < span className = "flex items-center gap-1" >
173- < MessageSquare className = "h-3 w-3" />
174- { item . replyCount }
175- </ span >
164+ < span > ·</ span >
165+ </ >
166+ ) }
167+ < span >
168+ { formatDistanceToNow ( new Date ( item . post . createdAt ) , {
169+ addSuffix : true ,
170+ } ) }
171+ </ span >
172+ < span > ·</ span >
173+ < span className = "flex items-center gap-1" >
174+ < MessageSquare className = "h-3 w-3" />
175+ { item . replyCount }
176176 </ span >
177177 </ div >
178178 </ div >
0 commit comments