Merge branch 'dropdown-menu-improvements' into 'develop'

Dropdown menu improvements and fixes

See merge request soapbox-pub/soapbox!2541
This commit is contained in:
marcin mikołajczak 2023-06-02 20:42:34 +00:00
commit ea298472a8
2 changed files with 27 additions and 44 deletions

View file

@ -87,7 +87,7 @@ const DropdownMenuItem = ({ index, item, onClick }: IDropdownMenuItem) => {
title={item.text}
className={
clsx({
'flex px-4 py-2.5 text-sm text-gray-700 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none cursor-pointer': true,
'flex px-4 py-2.5 text-sm text-gray-700 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 focus:bg-gray-100 dark:focus:bg-gray-800 focus:outline-none cursor-pointer': true,
'text-danger-600 dark:text-danger-400': item.destructive,
})
}
@ -106,4 +106,4 @@ const DropdownMenuItem = ({ index, item, onClick }: IDropdownMenuItem) => {
);
};
export default DropdownMenuItem;
export default DropdownMenuItem;

View file

@ -4,12 +4,9 @@ import { supportsPassiveEvents } from 'detect-passive-events';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
import {
closeDropdownMenu as closeDropdownMenuRedux,
openDropdownMenu,
} from 'soapbox/actions/dropdown-menu';
import { closeDropdownMenu as closeDropdownMenuRedux, openDropdownMenu } from 'soapbox/actions/dropdown-menu';
import { closeModal, openModal } from 'soapbox/actions/modals';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { useAppDispatch } from 'soapbox/hooks';
import { isUserTouching } from 'soapbox/is-mobile';
import { IconButton, Portal } from '../ui';
@ -53,10 +50,8 @@ const DropdownMenu = (props: IDropdownMenu) => {
const history = useHistory();
const [isOpen, setIsOpen] = useState<boolean>(false);
const isOpenRedux = useAppSelector(state => state.dropdown_menu.isOpen);
const arrowRef = useRef<HTMLDivElement>(null);
const activeElement = useRef<Element | null>(null);
const isOnMobile = isUserTouching();
@ -116,10 +111,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
};
const handleClose = () => {
if (activeElement.current && activeElement.current === refs.reference.current) {
(activeElement.current as any).focus();
activeElement.current = null;
}
(refs.reference.current as HTMLButtonElement)?.focus();
if (isOnMobile) {
dispatch(closeModal('ACTIONS'));
@ -134,24 +126,13 @@ const DropdownMenu = (props: IDropdownMenu) => {
};
const closeDropdownMenu = () => {
if (isOpenRedux) {
dispatch(closeDropdownMenuRedux());
}
};
dispatch((dispatch, getState) => {
const isOpenRedux = getState().dropdown_menu.isOpen;
const handleMouseDown: React.EventHandler<React.MouseEvent | React.KeyboardEvent> = () => {
if (!isOpen) {
activeElement.current = document.activeElement;
}
};
const handleButtonKeyDown: React.EventHandler<React.KeyboardEvent> = (event) => {
switch (event.key) {
case ' ':
case 'Enter':
handleMouseDown(event);
break;
}
if (isOpenRedux) {
dispatch(closeDropdownMenuRedux());
}
});
};
const handleKeyPress: React.EventHandler<React.KeyboardEvent<HTMLButtonElement>> = (event) => {
@ -263,16 +244,22 @@ const DropdownMenu = (props: IDropdownMenu) => {
}, []);
useEffect(() => {
document.addEventListener('click', handleDocumentClick, false);
document.addEventListener('keydown', handleKeyDown, false);
document.addEventListener('touchend', handleDocumentClick, listenerOptions);
if (isOpen) {
if (refs.floating.current) {
(refs.floating.current?.querySelector('li a[role=\'button\']') as HTMLAnchorElement)?.focus();
}
return () => {
document.removeEventListener('click', handleDocumentClick);
document.removeEventListener('keydown', handleKeyDown);
document.removeEventListener('touchend', handleDocumentClick);
};
}, [refs.floating.current]);
document.addEventListener('click', handleDocumentClick, false);
document.addEventListener('keydown', handleKeyDown, false);
document.addEventListener('touchend', handleDocumentClick, listenerOptions);
return () => {
document.removeEventListener('click', handleDocumentClick);
document.removeEventListener('keydown', handleKeyDown);
document.removeEventListener('touchend', handleDocumentClick);
};
}
}, [isOpen, refs.floating.current]);
if (items.length === 0) {
return null;
@ -284,8 +271,6 @@ const DropdownMenu = (props: IDropdownMenu) => {
React.cloneElement(children, {
disabled,
onClick: handleClick,
onMouseDown: handleMouseDown,
onKeyDown: handleButtonKeyDown,
onKeyPress: handleKeyPress,
ref: refs.setReference,
})
@ -299,8 +284,6 @@ const DropdownMenu = (props: IDropdownMenu) => {
title={title}
src={src}
onClick={handleClick}
onMouseDown={handleMouseDown}
onKeyDown={handleButtonKeyDown}
onKeyPress={handleKeyPress}
ref={refs.setReference}
/>
@ -346,4 +329,4 @@ const DropdownMenu = (props: IDropdownMenu) => {
);
};
export default DropdownMenu;
export default DropdownMenu;