1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-24 20:36:40 +07:00
vault-frontend/src/components/menu/MenuButton/index.tsx
2023-03-17 18:13:04 +06:00

100 lines
2.4 KiB
TypeScript

import React, { FC, ReactNode, useEffect, useState } from 'react';
import { Placement } from '@popperjs/core';
import classNames from 'classnames';
import { usePopper } from 'react-popper';
import { Icon } from '~/components/input/Icon';
import { useFocusEvent } from '~/hooks/dom/useFocusEvent';
import styles from './styles.module.scss';
interface MenuButtonProps {
position?: Placement;
icon?: ReactNode;
className?: string;
activate?: 'hover' | 'focus';
fixed?: boolean;
translucent?: boolean;
}
const MenuButton: FC<MenuButtonProps> = ({
position = 'auto',
children,
className,
icon = <Icon icon="dots-vertical" size={24} />,
translucent = true,
activate = 'focus',
fixed,
}) => {
const focus = useFocusEvent(false, 300);
const hover = useFocusEvent(false, 300);
const [referenceElement, setReferenceElement] =
useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(
null,
);
const [arrowElement, setArrowElement] = useState<HTMLDivElement | null>(null);
const popper = usePopper(referenceElement, popperElement, {
placement: position,
strategy: fixed ? 'fixed' : 'absolute',
modifiers: [
{ name: 'arrow', options: { element: arrowElement } },
{
name: 'offset',
options: {
offset: [0, 10],
},
},
{
name: 'preventOverflow',
options: {
padding: 10,
},
},
],
});
const visible = activate === 'focus' ? focus.focused : hover.focused;
useEffect(() => {
popper.update?.();
}, [visible]);
return (
<>
<button
className={classNames(styles.menu, className)}
ref={setReferenceElement}
onFocus={focus.onFocus}
onBlur={focus.onBlur}
onMouseOver={hover.onFocus}
onMouseOut={hover.onBlur}
>
{icon}
</button>
<div
style={popper.styles.popper}
ref={setPopperElement}
{...popper.attributes.popper}
className={classNames(styles.popper, {
[styles.fixed]: fixed,
[styles.translucent]: translucent,
[styles.visible]: visible,
})}
>
<div
style={popper.styles.arrow}
ref={setArrowElement}
className={styles.arrow}
/>
{children}
</div>
</>
);
};
export { MenuButton };