From 50e71c1156b3e46ee8038d549c083130337cf995 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sun, 1 May 2022 14:31:40 -0500 Subject: [PATCH] EmojiButtonWrapper: delay closing the selector for 500ms --- .../components/emoji-button-wrapper.tsx | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/app/soapbox/components/emoji-button-wrapper.tsx b/app/soapbox/components/emoji-button-wrapper.tsx index c28aebc49..231525867 100644 --- a/app/soapbox/components/emoji-button-wrapper.tsx +++ b/app/soapbox/components/emoji-button-wrapper.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames'; -import React, { useState } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { usePopper } from 'react-popper'; import { useDispatch } from 'react-redux'; @@ -22,6 +22,7 @@ const EmojiButtonWrapper: React.FC = ({ statusId, children const status = useAppSelector(state => state.statuses.get(statusId)); const soapboxConfig = useSoapboxConfig(); + const timeout = useRef(); const [visible, setVisible] = useState(false); // const [focused, setFocused] = useState(false); @@ -42,16 +43,40 @@ const EmojiButtonWrapper: React.FC = ({ statusId, children ], }); + useEffect(() => { + return () => { + if (timeout.current) { + clearTimeout(timeout.current); + } + }; + }, []); + if (!status) return null; const handleMouseEnter = () => { + if (timeout.current) { + clearTimeout(timeout.current); + } + if (!isUserTouching()) { setVisible(true); } }; const handleMouseLeave = () => { - setVisible(false); + if (timeout.current) { + clearTimeout(timeout.current); + } + + // Unless the user is touching, delay closing the emoji selector briefly + // so the user can move the mouse diagonally to make a selection. + if (isUserTouching()) { + setVisible(false); + } else { + timeout.current = setTimeout(() => { + setVisible(false); + }, 500); + } }; const handleReact = (emoji: string): void => {