icynet-admin/components/common/Dropdown/Dropdown.tsx

46 lines
1.3 KiB
TypeScript

import { useEffect, useRef, useState } from 'react';
import conditionalClass from '../../../lib/utils/conditional-class';
import styles from './Dropdown.module.scss';
export const Dropdown = ({
children,
opens = 'left',
}: {
children: React.ReactNode;
opens?: 'right' | 'left';
}) => {
const [visible, setVisible] = useState(false);
const ref = useRef<HTMLDivElement>(null);
// Off click listener
useEffect(() => {
if (!visible || !ref) return;
function handleClickOutside(event: MouseEvent | TouchEvent) {
if (ref.current && !ref.current.contains(event.target as HTMLElement)) {
setVisible(false);
}
}
document.addEventListener('mousedown', handleClickOutside);
document.addEventListener('touchstart', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
document.removeEventListener('touchstart', handleClickOutside);
};
}, [ref, visible]);
return (
<div className={[styles.wrapper, styles[opens]].join(' ')} ref={ref}>
<button
className={[
styles.toggle,
conditionalClass(visible, styles.active),
].join(' ')}
onClick={() => setVisible(!visible)}
></button>
{visible && <div className={styles.dropdown}>{children}</div>}
</div>
);
};