New

ReactionPicker

Emoji reaction bar with most-used reactions, count badges, and add reaction button.

Social & Communicationreactionsemojisocialengagementfeedback

Dependencies

Other dependencies:

@/components/ui/button@/components/ui/popover

How to use this component

Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.

Code

1"use client";
2
3import { Button } from "@/components/ui/button";
4import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
5import { Plus } from "lucide-react";
6import { useState } from "react";
7
8interface Reaction {
9 emoji: string;
10 count: number;
11 selected: boolean;
12}
13
14const defaultReactions: Reaction[] = [
15 { emoji: "👍", count: 24, selected: false },
16 { emoji: "❤️", count: 18, selected: true },
17 { emoji: "😂", count: 12, selected: false },
18 { emoji: "😮", count: 5, selected: false },
19 { emoji: "😢", count: 2, selected: false },
20 { emoji: "🎉", count: 8, selected: false },
21];
22
23const moreEmojis = ["🔥", "👏", "🙌", "💯", "✨", "💪", "🤔", "👀", "🎯", "💡"];
24
25export default function ReactionPicker() {
26 const [reactions, setReactions] = useState<Reaction[]>(defaultReactions);
27
28 const toggleReaction = (index: number) => {
29 setReactions((prev) =>
30 prev.map((r, i) =>
31 i === index
32 ? { ...r, selected: !r.selected, count: r.selected ? r.count - 1 : r.count + 1 }
33 : r
34 )
35 );
36 };
37
38 const addEmoji = (emoji: string) => {
39 const existing = reactions.findIndex((r) => r.emoji === emoji);
40 if (existing >= 0) {
41 toggleReaction(existing);
42 } else {
43 setReactions((prev) => [...prev, { emoji, count: 1, selected: true }]);
44 }
45 };
46
47 return (
48 <div className="flex items-center gap-1 flex-wrap">
49 {reactions.map((reaction, index) => (
50 <Button
51 key={reaction.emoji}
52 variant="outline"
53 size="sm"
54 onClick={() => toggleReaction(index)}
55 className={`gap-1 ${reaction.selected ? "border-primary bg-primary/10" : ""}`}
56 >
57 <span>{reaction.emoji}</span>
58 <span className="text-xs">{reaction.count}</span>
59 </Button>
60 ))}
61 <Popover>
62 <PopoverTrigger asChild>
63 <Button variant="outline" size="sm" className="gap-1">
64 <Plus className="w-3 h-3" />
65 </Button>
66 </PopoverTrigger>
67 <PopoverContent className="w-auto p-2">
68 <div className="grid grid-cols-5 gap-1">
69 {moreEmojis.map((emoji) => (
70 <Button
71 key={emoji}
72 variant="ghost"
73 size="sm"
74 className="h-8 w-8 p-0 text-lg"
75 onClick={() => addEmoji(emoji)}
76 >
77 {emoji}
78 </Button>
79 ))}
80 </div>
81 </PopoverContent>
82 </Popover>
83 </div>
84 );
85}

Related Social & Communication Components

Command Palette

Search for a command to run...