Animate dropdown menu

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak
2024-08-16 12:12:00 +02:00
parent e72df3fc60
commit b1330cb99a

View File

@ -50,6 +50,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
const history = useHistory(); const history = useHistory();
const [isOpen, setIsOpen] = useState<boolean>(false); const [isOpen, setIsOpen] = useState<boolean>(false);
const [isDisplayed, setIsDisplayed] = useState<boolean>(false);
const arrowRef = useRef<HTMLDivElement>(null); const arrowRef = useRef<HTMLDivElement>(null);
@ -254,12 +255,18 @@ const DropdownMenu = (props: IDropdownMenu) => {
} }
}, [isOpen, refs.floating.current]); }, [isOpen, refs.floating.current]);
useEffect(() => {
setTimeout(() => setIsDisplayed(isOpen), isOpen ? 0 : 150);
}, [isOpen]);
if (items.length === 0) { if (items.length === 0) {
return null; return null;
} }
const autoFocus = !items.some((item) => item?.active); const autoFocus = !items.some((item) => item?.active);
console.log(placement);
return ( return (
<> <>
{children ? ( {children ? (
@ -284,14 +291,23 @@ const DropdownMenu = (props: IDropdownMenu) => {
/> />
)} )}
{isOpen ? ( {isOpen || isDisplayed ? (
<Portal> <Portal>
<div <div
data-testid='dropdown-menu' data-testid='dropdown-menu'
ref={refs.setFloating} ref={refs.setFloating}
className={ className={
clsx('z-[1001] w-56 rounded-md bg-white py-1 shadow-lg transition-opacity duration-100 focus:outline-none black:bg-black dark:bg-gray-900 dark:ring-2 dark:ring-primary-700', { clsx('z-[1001] w-56 rounded-md bg-white py-1 shadow-lg duration-100 ease-in-out focus:outline-none black:bg-black no-reduce-motion:transition-transform dark:bg-gray-900 dark:ring-2 dark:ring-primary-700', {
'opacity-0 pointer-events-none': !isOpen, 'scale-0': !(isDisplayed && isOpen),
'scale-100': (isDisplayed && isOpen),
'origin-bottom': placement === 'top',
'origin-left': placement === 'right',
'origin-top': placement === 'bottom',
'origin-right': placement === 'left',
'origin-bottom-left': placement === 'top-start',
'origin-bottom-right': placement === 'top-end',
'origin-top-left': placement === 'bottom-start',
'origin-top-right': placement === 'bottom-end',
}) })
} }
style={{ style={{