- Gallery
- Social & Communication
- ReactionPicker
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";23import { Button } from "@/components/ui/button";4import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";5import { Plus } from "lucide-react";6import { useState } from "react";78interface Reaction {9 emoji: string;10 count: number;11 selected: boolean;12}1314const 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];2223const moreEmojis = ["🔥", "👏", "🙌", "💯", "✨", "💪", "🤔", "👀", "🎯", "💡"];2425export default function ReactionPicker() {26 const [reactions, setReactions] = useState<Reaction[]>(defaultReactions);2728 const toggleReaction = (index: number) => {29 setReactions((prev) =>30 prev.map((r, i) =>31 i === index32 ? { ...r, selected: !r.selected, count: r.selected ? r.count - 1 : r.count + 1 }33 : r34 )35 );36 };3738 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 };4647 return (48 <div className="flex items-center gap-1 flex-wrap">49 {reactions.map((reaction, index) => (50 <Button51 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 <Button71 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}