ReactionBar.tsx
Raw
1import { ALLOWED_REACTIONS } from "../constants.ts";
2import type { SessionUser } from "../middleware/session.ts";
3
4export interface ReactionCount {
5 emoji: string;
6 count: number;
7 userReacted: boolean;
8}
9
10interface ReactionBarProps {
11 reactions: ReactionCount[];
12 postUrl: string;
13 commentId?: number;
14 user: SessionUser | null;
15}
16
17export function ReactionBar({
18 reactions,
19 postUrl,
20 commentId,
21 user,
22}: ReactionBarProps) {
23 if (!user && reactions.length === 0) return null;
24 const existing = new Set(reactions.map((r) => r.emoji));
25 const all = [...ALLOWED_REACTIONS];
26 return (
27 <div class="reaction-bar">
28 {reactions.map((r) => (
29 <form method="POST" action={postUrl} class="reaction-form">
30 {commentId != null && (
31 <input
32 type="hidden"
33 name="comment_id"
34 value={String(commentId)}
35 />
36 )}
37 <input type="hidden" name="emoji" value={r.emoji} />
38 <button
39 type="submit"
40 class={`reaction-btn${r.userReacted ? " reacted" : ""}`}
41 disabled={!user}
42 >
43 {r.emoji} {r.count}
44 </button>
45 </form>
46 ))}
47 {user && (
48 <details class="reaction-picker">
49 <summary class="reaction-add-btn">+</summary>
50 <div class="reaction-picker-dropdown">
51 {all
52 .filter((e) => !existing.has(e))
53 .map((e) => (
54 <form
55 method="POST"
56 action={postUrl}
57 class="reaction-form"
58 >
59 {commentId != null && (
60 <input
61 type="hidden"
62 name="comment_id"
63 value={String(commentId)}
64 />
65 )}
66 <input
67 type="hidden"
68 name="emoji"
69 value={e}
70 />
71 <button
72 type="submit"
73 class="reaction-picker-btn"
74 >
75 {e}
76 </button>
77 </form>
78 ))}
79 </div>
80 </details>
81 )}
82 </div>
83 );
84}
85