"use client"; import { useState, type ReactNode } from "react"; import { CornerUpLeft, Copy, SmilePlus } from "lucide-react"; import { toast } from "sonner"; import { cn } from "@/lib/utils"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import type { Message } from "@/types"; // WhatsApp's own quick-reaction bar starts with these six. Picking the same // set keeps the affordance familiar without pulling in a 300KB emoji library. const QUICK_EMOJIS = ["👍", "❤️", "😂", "😮", "😢", "🙏"]; interface MessageActionsProps { message: Message; onReply: () => void; onReact: (emoji: string) => void; children: ReactNode; } /** * Hover/long-press toolbar wrapper around a ``. The bubble * itself stays a pure presenter — this component owns the action surface so * the bubble's render path is unaffected when the toolbar isn't visible. */ export function MessageActions({ message, onReply, onReact, children, }: MessageActionsProps) { // Touch devices have no hover. Long-press fires `contextmenu`; we capture // it, suppress the native menu, and pin the toolbar open until the user // interacts elsewhere. const [touchOpen, setTouchOpen] = useState(false); const [pickerOpen, setPickerOpen] = useState(false); const isAgent = message.sender_type === "agent" || message.sender_type === "bot"; const handleContextMenu = (e: React.MouseEvent) => { e.preventDefault(); setTouchOpen(true); }; const handleCopy = async () => { const text = message.content_text ?? ""; if (!text) { toast.error("Nothing to copy"); return; } try { await navigator.clipboard.writeText(text); toast.success("Copied"); } catch { toast.error("Copy failed"); } setTouchOpen(false); }; const handlePickEmoji = (emoji: string) => { onReact(emoji); setPickerOpen(false); setTouchOpen(false); }; const handleReply = () => { onReply(); setTouchOpen(false); }; // Row alignment lives here (not in MessageBubble) so the `group/actions` // hover region matches the bubble's content width — hovering empty space // in the row no longer reveals the toolbar. return (
setTouchOpen(false)} >
{children}
{QUICK_EMOJIS.map((e) => ( ))}
); }