Skip to content

Commit 1bcfeee

Browse files
committed
Merge branch 'fix/forum-card-ux'
2 parents fdb231e + 5aa2e7f commit 1bcfeee

6 files changed

Lines changed: 176 additions & 92 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ All notable changes to `Filament Forum` will be documented in this file.
44

55
## Unreleased
66

7-
Add reusable forum content reports and moderation review workflow.
7+
## v2.4.2 - 2026-07-08
8+
9+
### What's Changed
10+
11+
* Fix near-invisible comment count heading on post detail pages
12+
* Expand post card clickable area using stretched-link pattern so the entire card navigates to the post while keeping favorite and reaction controls interactive
813

914
## v2.4.1 - 2026-07-04
1015

resources/css/filament-forum.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,24 @@
8282
.dark .mention-item .name {
8383
color: #f9fafb;
8484
}
85+
86+
.forum-post-card {
87+
position: relative;
88+
}
89+
90+
.forum-post-card__link {
91+
position: absolute;
92+
inset: 0;
93+
z-index: 1;
94+
}
95+
96+
.forum-post-card__link::after {
97+
content: "";
98+
position: absolute;
99+
inset: 0;
100+
}
101+
102+
.forum-post-card__control {
103+
position: relative;
104+
z-index: 2;
105+
}

resources/dist/filament-forum.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,24 @@
8282
.dark .mention-item .name {
8383
color: #f9fafb;
8484
}
85+
86+
.forum-post-card {
87+
position: relative;
88+
}
89+
90+
.forum-post-card__link {
91+
position: absolute;
92+
inset: 0;
93+
z-index: 1;
94+
}
95+
96+
.forum-post-card__link::after {
97+
content: "";
98+
position: absolute;
99+
inset: 0;
100+
}
101+
102+
.forum-post-card__control {
103+
position: relative;
104+
z-index: 2;
105+
}

resources/views/filament/tables/components/forum-post-card-column.blade.php

Lines changed: 96 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -4,105 +4,111 @@
44
$isFavorite = $record->isFavorite();
55
@endphp
66

7-
<div class="w-full bg-white rounded-xl shadow-xs overflow-hidden">
8-
<div class="p-4">
9-
{{-- Header with user avatar and post info --}}
10-
<div class="flex items-start justify-between">
11-
<a href="{{ ForumPostResource::getUrl('view', ['forum' => $record->forum->id, 'record' => $record->id]) }}">
12-
<div class="flex items-start space-x-4">
13-
<img
14-
src="{{ $record->user->profile_photo ?? 'https://ui-avatars.com/api/?name=' . urlencode($record->user->name ?? __('filament-forum::filament-forum.forum-post.unknown')) }}"
15-
alt="{{ $record->user->name ?? __('filament-forum::filament-forum.forum-post.unknown') }}"
16-
class="w-10 h-10 rounded-full"
17-
>
18-
<div>
19-
<h3 class="text-lg font-semibold text-gray-900">
20-
{{ $record->name }}
21-
@if($record->hasBeenEdited())
22-
<span class="text-sm text-gray-500 font-normal pl-2">{{ __('filament-forum::filament-forum.forum-post.edited') }}</span>
23-
@endif
24-
</h3>
25-
<p class="text-sm text-gray-500">
26-
@if($record->getLastCommentTime())
27-
{{ __('filament-forum::filament-forum.forum-post.last-reply') }} {{ $record->getLastCommentTime() }}
28-
@else
29-
{{ __('filament-forum::filament-forum.forum-post.no-replies') }}
30-
@endif
31-
</p>
32-
</div>
33-
</div>
34-
</a>
7+
<div class="forum-post-card w-full bg-white rounded-xl shadow-xs overflow-hidden">
8+
<div class="p-4">
9+
<a
10+
href="{{ ForumPostResource::getUrl('view', ['forum' => $record->forum->id, 'record' => $record->id]) }}"
11+
class="forum-post-card__link"
12+
aria-label="{{ $record->name }}"
13+
></a>
3514

36-
{{-- Favorite Toggle --}}
37-
<div x-cloak x-data="{ isFavorite: {{ $isFavorite ? 'true' : 'false' }} }"
38-
x-on:favorite-toggled.window="if ($event.detail.recordId === {{ $record->getKey() }}) isFavorite = $event.detail.isFavorite">
39-
<button
40-
wire:click="toggleFavorite({{ $record->getKey() }})"
41-
type="button"
42-
:class="{
43-
'transition-colors': true
44-
}"
45-
>
46-
<div x-tooltip.raw="{{ __('filament-forum::filament-forum.forum-post.toggle-favorite') }}">
47-
<x-filament::loading-indicator
48-
wire:loading
49-
wire:target="toggleFavorite({{ $record->getKey() }})"
50-
class="w-6 h-6 text-primary-500"
51-
/>
52-
53-
<div wire:loading.remove>
54-
<x-heroicon-s-star class="w-6 h-6 text-primary-500" x-show="isFavorite" />
55-
<x-heroicon-o-star class="w-6 h-6 text-gray-400 hover:text-primary-500" x-show="!isFavorite" />
56-
</div>
57-
</div>
58-
</button>
59-
</div>
15+
{{-- Header with user avatar and post info --}}
16+
<div class="flex items-start justify-between">
17+
<div class="flex items-start space-x-4">
18+
<img
19+
src="{{ $record->user->profile_photo ?? 'https://ui-avatars.com/api/?name=' . urlencode($record->user->name ?? __('filament-forum::filament-forum.forum-post.unknown')) }}"
20+
alt="{{ $record->user->name ?? __('filament-forum::filament-forum.forum-post.unknown') }}"
21+
class="w-10 h-10 rounded-full"
22+
>
23+
<div>
24+
<h3 class="text-lg font-semibold text-gray-900">
25+
{{ $record->name }}
26+
@if($record->hasBeenEdited())
27+
<span class="text-sm text-gray-500 font-normal pl-2">{{ __('filament-forum::filament-forum.forum-post.edited') }}</span>
28+
@endif
29+
</h3>
30+
<p class="text-sm text-gray-500">
31+
@if($record->getLastCommentTime())
32+
{{ __('filament-forum::filament-forum.forum-post.last-reply') }} {{ $record->getLastCommentTime() }}
33+
@else
34+
{{ __('filament-forum::filament-forum.forum-post.no-replies') }}
35+
@endif
36+
</p>
6037
</div>
38+
</div>
6139

62-
{{-- Description --}}
63-
<a href="{{ ForumPostResource::getUrl('view', ['forum' => $record->forum->id, 'record' => $record->id]) }}">
64-
<div class="mt-4">
65-
<p class="text-sm text-gray-600">
66-
{{ Str::limit(strip_tags($record->description), 200) }}
67-
</p>
40+
{{-- Favorite Toggle --}}
41+
<div
42+
class="forum-post-card__control"
43+
x-cloak
44+
x-data="{ isFavorite: {{ $isFavorite ? 'true' : 'false' }} }"
45+
x-on:favorite-toggled.window="if ($event.detail.recordId === {{ $record->getKey() }}) isFavorite = $event.detail.isFavorite"
46+
>
47+
<button
48+
wire:click="toggleFavorite({{ $record->getKey() }})"
49+
type="button"
50+
:class="{
51+
'transition-colors': true
52+
}"
53+
>
54+
<div x-tooltip.raw="{{ __('filament-forum::filament-forum.forum-post.toggle-favorite') }}">
55+
<x-filament::loading-indicator
56+
wire:loading
57+
wire:target="toggleFavorite({{ $record->getKey() }})"
58+
class="w-6 h-6 text-primary-500"
59+
/>
60+
61+
<div wire:loading.remove>
62+
<x-heroicon-s-star class="w-6 h-6 text-primary-500" x-show="isFavorite" />
63+
<x-heroicon-o-star class="w-6 h-6 text-gray-400 hover:text-primary-500" x-show="!isFavorite" />
6864
</div>
69-
</a>
65+
</div>
66+
</button>
67+
</div>
68+
</div>
7069

71-
{{-- Footer with stats, reactions and comment authors --}}
72-
<div class="flex items-center justify-between mt-4 pt-4 border-t border-gray-100">
73-
<div class="text-sm text-gray-500">
74-
@php
75-
$viewsCount = $record->views_count ?? 0;
76-
$replies = $record->comments()->count();
77-
@endphp
70+
{{-- Description --}}
71+
<div class="mt-4">
72+
<p class="text-sm text-gray-600">
73+
{{ Str::limit(strip_tags($record->description), 200) }}
74+
</p>
75+
</div>
7876

79-
{{ trans_choice('filament-forum::filament-forum.forum-post.views', $viewsCount, ['value' => $viewsCount]) }} &bull; {{ trans_choice('filament-forum::filament-forum.forum-post.replies', $replies, ['value' => $replies]) }}
80-
</div>
77+
{{-- Footer with stats, reactions and comment authors --}}
78+
<div class="flex items-center justify-between mt-4 pt-4 border-t border-gray-100">
79+
<div class="text-sm text-gray-500">
80+
@php
81+
$viewsCount = $record->views_count ?? 0;
82+
$replies = $record->comments()->count();
83+
@endphp
8184

82-
<div class="flex items-center gap-3">
83-
{{-- Post Reactions --}}
84-
<div>
85-
@livewire('tapp.filament-forum.forum-post-reactions', ['post' => $record], key('post-reactions-' . $record->id))
86-
</div>
85+
{{ trans_choice('filament-forum::filament-forum.forum-post.views', $viewsCount, ['value' => $viewsCount]) }} &bull; {{ trans_choice('filament-forum::filament-forum.forum-post.replies', $replies, ['value' => $replies]) }}
86+
</div>
87+
88+
<div class="flex items-center gap-3">
89+
{{-- Post Reactions --}}
90+
<div class="forum-post-card__control">
91+
@livewire('tapp.filament-forum.forum-post-reactions', ['post' => $record], key('post-reactions-' . $record->id))
92+
</div>
8793

88-
{{-- Comment Authors --}}
89-
<div class="flex items-center -space-x-2">
90-
@foreach($record->getCommentAuthors() as $author)
91-
<img
92-
src="{{ $author->profile_photo ?? 'https://ui-avatars.com/api/?name=' . urlencode($author->name) }}"
93-
alt="{{ $author->name }}"
94-
class="w-8 h-8 rounded-full border-2 border-white"
95-
>
96-
@endforeach
97-
@if($record->getCountDistinctUsersWhoCommented() > 3)
98-
<div class="flex items-center justify-center w-8 h-8 rounded-full bg-gray-100 border-2 border-white">
99-
<span class="text-xs text-gray-500 font-medium">
100-
+{{ $record->getCountDistinctUsersWhoCommented() - 3 }}
101-
</span>
102-
</div>
103-
@endif
104-
</div>
94+
{{-- Comment Authors --}}
95+
<div class="flex items-center -space-x-2">
96+
@foreach($record->getCommentAuthors() as $author)
97+
<img
98+
src="{{ $author->profile_photo ?? 'https://ui-avatars.com/api/?name=' . urlencode($author->name) }}"
99+
alt="{{ $author->name }}"
100+
class="w-8 h-8 rounded-full border-2 border-white"
101+
>
102+
@endforeach
103+
@if($record->getCountDistinctUsersWhoCommented() > 3)
104+
<div class="flex items-center justify-center w-8 h-8 rounded-full bg-gray-100 border-2 border-white">
105+
<span class="text-xs text-gray-500 font-medium">
106+
+{{ $record->getCountDistinctUsersWhoCommented() - 3 }}
107+
</span>
105108
</div>
109+
@endif
106110
</div>
111+
</div>
107112
</div>
113+
</div>
108114
</div>

resources/views/livewire/forum-comments.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{{-- Comments Header + Collapsible Form --}}
33
<div x-data="{ showCommentForm: false }" @comment-created.window="showCommentForm = false">
44
<div class="flex items-center justify-between mb-4">
5-
<h3 class="text-base font-medium text-gray-100">
5+
<h3 class="text-base font-medium text-gray-900 dark:text-gray-100">
66
{{ trans_choice('filament-forum::filament-forum.comments.count', $comments->count(), ['count' => $comments->count()]) }}
77
</h3>
88
@auth

tests/Feature/ForumUxTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
it('renders comment count with readable text color in blade template', function () {
4+
$bladePath = __DIR__.'/../../resources/views/livewire/forum-comments.blade.php';
5+
6+
$contents = file_get_contents($bladePath);
7+
8+
expect($contents)->toContain('text-gray-900 dark:text-gray-100');
9+
});
10+
11+
it('renders post card with stretched link markup', function () {
12+
$bladePath = __DIR__.'/../../resources/views/filament/tables/components/forum-post-card-column.blade.php';
13+
14+
$contents = file_get_contents($bladePath);
15+
16+
expect($contents)
17+
->toContain('forum-post-card')
18+
->toContain('forum-post-card__link')
19+
->toContain('forum-post-card__control');
20+
});
21+
22+
it('includes stretched link styles in built css', function () {
23+
$cssPath = __DIR__.'/../../resources/dist/filament-forum.css';
24+
25+
$contents = file_get_contents($cssPath);
26+
27+
expect($contents)
28+
->toContain('.forum-post-card {')
29+
->toContain('.forum-post-card__link {')
30+
->toContain('.forum-post-card__control {');
31+
});

0 commit comments

Comments
 (0)