Fix emoji picker closing when expanding to full picker

The popover's mouse-leave timeout was firing during the DOM transition
from the quick-select bar to the full emoji-mart picker, causing it to
close immediately. Added an expanded state flag that disables the
hover-to-close behavior when the full picker is shown.
This commit is contained in:
Mary Kate Fain
2026-02-23 12:07:53 -06:00
parent c046e33f6b
commit edd13e26f7
2 changed files with 15 additions and 1 deletions
+7 -1
View File
@@ -19,6 +19,8 @@ interface QuickReactMenuProps {
eventKind: number;
/** Called after an emoji is selected so the parent can close the popover. */
onClose?: () => void;
/** Called when the full picker is opened/closed so the parent can lock the popover open. */
onExpandChange?: (expanded: boolean) => void;
/** Optional extra class names. */
className?: string;
}
@@ -28,6 +30,7 @@ export function QuickReactMenu({
eventPubkey,
eventKind,
onClose,
onExpandChange,
className,
}: QuickReactMenuProps) {
const { user } = useCurrentUser();
@@ -145,7 +148,10 @@ export function QuickReactMenu({
{/* More button to show full picker */}
<button
onClick={() => setShowFullPicker(true)}
onClick={() => {
setShowFullPicker(true);
onExpandChange?.(true);
}}
className="flex items-center justify-center size-9 rounded-full text-muted-foreground transition-all hover:bg-accent hover:text-foreground hover:scale-110 active:scale-95"
title="More reactions"
>
+8
View File
@@ -32,6 +32,7 @@ export function ReactionButton({
const [menuOpen, setMenuOpen] = useState(false);
const closeTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const justClosedRef = useRef(false);
const pickerExpandedRef = useRef(false);
const userReaction = useUserReaction(eventId);
const hasReacted = !!userReaction;
@@ -48,6 +49,8 @@ export function ReactionButton({
}, [user]);
const handleMouseLeave = useCallback(() => {
// Don't auto-close when the full emoji picker is open
if (pickerExpandedRef.current) return;
// Delay closing to allow user to move to the menu
closeTimeoutRef.current = setTimeout(() => {
setMenuOpen(false);
@@ -57,6 +60,7 @@ export function ReactionButton({
return (
<Popover open={menuOpen} onOpenChange={(open) => {
if (open && justClosedRef.current) return;
if (!open) pickerExpandedRef.current = false;
setMenuOpen(open);
}}>
<PopoverTrigger asChild>
@@ -103,7 +107,11 @@ export function ReactionButton({
eventId={eventId}
eventPubkey={eventPubkey}
eventKind={eventKind}
onExpandChange={(expanded) => {
pickerExpandedRef.current = expanded;
}}
onClose={() => {
pickerExpandedRef.current = false;
justClosedRef.current = true;
setMenuOpen(false);
setTimeout(() => {