From 87858a95b035d44311af725c521ec3e93d71906c Mon Sep 17 00:00:00 2001 From: Ushindi Gedeon Date: Sun, 19 May 2024 11:51:13 +0200 Subject: [PATCH] [Improve] Close emoji selector when the user selects one (#2535) * [Improve] Close emoji selector when the user selects one * Add functionality to close the emojis dropdown when the user clicks outside * Fix failing checks --- apps/web/lib/components/inputs/input.tsx | 67 ++++++++++++++---------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/apps/web/lib/components/inputs/input.tsx b/apps/web/lib/components/inputs/input.tsx index 94545ace2..a56ca03b9 100644 --- a/apps/web/lib/components/inputs/input.tsx +++ b/apps/web/lib/components/inputs/input.tsx @@ -3,12 +3,13 @@ import { mergeRefs } from '@app/helpers'; import { IClassName } from '@app/interfaces'; import { clsxm } from '@app/utils'; -import { Dispatch, forwardRef, MutableRefObject, ReactNode, SetStateAction, useEffect, useRef, useState } from 'react'; +import { Dispatch, forwardRef, MutableRefObject, ReactNode, Ref, SetStateAction, useEffect, useRef, useState } from 'react'; +import { useOutsideClick } from '@app/hooks/useOutsideClick'; import { SpinnerLoader } from '../loader'; import { Text } from '../typography'; -import { BsEmojiSmile } from "react-icons/bs"; -import data from "@emoji-mart/data"; -import Picker from "@emoji-mart/react"; +import { BsEmojiSmile } from 'react-icons/bs'; +import data from '@emoji-mart/data'; +import Picker from '@emoji-mart/react'; type Props = { readonly errors?: Record; @@ -20,7 +21,7 @@ type Props = { autoCustomFocus?: boolean; notValidBorder?: boolean; emojis?: boolean; - setTaskName?: (taskName: string) => void; + setTaskName?: (taskName: string) => void; ignoreElementRefForTitle?: MutableRefObject; } & React.ComponentPropsWithRef<'input'>; @@ -50,18 +51,23 @@ export const InputField = forwardRef( const [showEmoji, setShowEmoji] = useState(false); const addEmoji = (emoji: { native: string }) => { - const input = inputRef.current as HTMLInputElement | null; + const input = inputRef.current as HTMLInputElement | null; if (input) { const currentValue = input.value || ''; const newValue = currentValue + emoji.native; - if(setTaskName){ - setTaskName(newValue) + if (setTaskName) { + setTaskName(newValue); } input.value = newValue; input.focus(); } + setShowEmoji(false); + }; + const handleOutsideClick = () => { + setShowEmoji(false); }; + const { targetEl } = useOutsideClick(handleOutsideClick); useEffect(() => { if (errors && name && errors[name]) { setError(errors[name]); @@ -102,13 +108,17 @@ export const InputField = forwardRef( className )} onKeyUp={onKeyUp} - onMouseOut={()=>{ - if(showEmoji==true){ - setShowEmoji(false)}}} + onMouseOut={() => { + if (showEmoji == true) { + setShowEmoji(false); + } + }} {...res} - /> + /> ); + const filteredRefs = [targetEl, ignoreElementRefForTitle].filter(Boolean); + return noWrapper ? ( inputElement ) : ( @@ -125,21 +135,24 @@ export const InputField = forwardRef( > {leadingNode &&
{leadingNode}
}
{inputElement}
- { - emojis &&
setShowEmoji(true)} className={clsxm('mr-3')} /> - {showEmoji && ( -
- -
- )}
- } + {emojis && ( +
+ setShowEmoji(true)} className={clsxm('mr-3')} /> + {showEmoji && ( +
| MutableRefObject)[])} + className="absolute right-1 z-50"> + +
+ )} +
+ )} {trailingNode &&
{trailingNode}
} {error && {error}}