jiti-meet/react/features/toolbox/components/web/Drawer.tsx

120 lines
3.0 KiB
TypeScript
Raw Normal View History

import React, { KeyboardEvent, ReactNode, useCallback } from 'react';
import ReactFocusLock from 'react-focus-lock';
2022-09-13 07:36:00 +00:00
import { makeStyles } from 'tss-react/mui';
import { DRAWER_MAX_HEIGHT } from '../../constants';
interface IProps {
/**
* The component(s) to be displayed within the drawer menu.
*/
2023-02-02 11:12:31 +00:00
children: ReactNode;
/**
* Class name for custom styles.
*/
className?: string;
/**
* The id of the dom element acting as the Drawer label.
*/
headingId?: string;
/**
* Whether the drawer should be shown or not.
*/
isOpen: boolean;
/**
* Function that hides the drawer.
*/
2023-02-02 11:12:31 +00:00
onClose?: Function;
}
const useStyles = makeStyles()(theme => {
return {
drawer: {
backgroundColor: theme.palette.ui01,
maxHeight: `calc(${DRAWER_MAX_HEIGHT})`,
borderRadius: '24px 24px 0 0'
}
};
});
/**
* Component that displays the mobile friendly drawer on web.
*
* @returns {ReactElement}
*/
function Drawer({
children,
className = '',
headingId,
isOpen,
onClose
}: IProps) {
2022-09-13 07:36:00 +00:00
const { classes: styles } = useStyles();
/**
* Handles clicks within the menu, preventing the propagation of the click event.
*
* @param {Object} event - The click event.
* @returns {void}
*/
const handleInsideClick = useCallback(event => {
event.stopPropagation();
}, []);
/**
* Handles clicks outside of the menu, closing it, and also stopping further propagation.
*
* @param {Object} event - The click event.
* @returns {void}
*/
const handleOutsideClick = useCallback(event => {
event.stopPropagation();
2023-02-02 11:12:31 +00:00
onClose?.();
}, [ onClose ]);
/**
* Handles pressing the escape key, closing the drawer.
*
* @param {KeyboardEvent<HTMLDivElement>} event - The keydown event.
* @returns {void}
*/
const handleEscKey = useCallback((event: KeyboardEvent<HTMLDivElement>) => {
if (event.key === 'Escape') {
event.preventDefault();
event.stopPropagation();
onClose?.();
}
}, [ onClose ]);
return (
isOpen ? (
<div
className = 'drawer-menu-container'
onClick = { handleOutsideClick }
onKeyDown = { handleEscKey }>
<div
className = { `drawer-menu ${styles.drawer} ${className}` }
onClick = { handleInsideClick }>
<ReactFocusLock
lockProps = {{
role: 'dialog',
'aria-modal': true,
'aria-labelledby': `#${headingId}`
}}
returnFocus = { true }>
{children}
</ReactFocusLock>
</div>
</div>
) : null
);
}
export default Drawer;