moodist/src/components/menu/menu.tsx
2024-02-24 20:22:36 +03:30

107 lines
2.5 KiB
TypeScript

import { useState } from 'react';
import { IoMenu, IoClose } from 'react-icons/io5/index';
import {
useFloating,
autoUpdate,
offset,
flip,
shift,
size,
useClick,
useDismiss,
useRole,
useInteractions,
FloatingFocusManager,
} from '@floating-ui/react';
import {
ShuffleItem,
ShareItem,
DonateItem,
NotepadItem,
SourceItem,
} from './items';
import { Divider } from './divider';
import { ShareLinkModal } from '@/components/modals/share-link';
import { Notepad } from '@/components/toolbox';
import styles from './menu.module.css';
export function Menu() {
const [isOpen, setIsOpen] = useState(false);
const [showShareLink, setShowShareLink] = useState(false);
const [showNotepad, setShowNotepad] = useState(false);
const { context, floatingStyles, refs } = useFloating({
middleware: [
offset(12),
flip(),
shift(),
size({
apply({ availableHeight, elements }) {
Object.assign(elements.floating.style, {
maxHeight: `${availableHeight}px`,
});
},
padding: 10,
}),
],
onOpenChange: setIsOpen,
open: isOpen,
placement: 'top-end',
whileElementsMounted: autoUpdate,
});
const click = useClick(context);
const dismiss = useDismiss(context);
const role = useRole(context);
const { getFloatingProps, getReferenceProps } = useInteractions([
click,
dismiss,
role,
]);
return (
<>
<div className={styles.wrapper}>
<button
aria-label="Menu"
className={styles.menuButton}
ref={refs.setReference}
onClick={() => setIsOpen(prev => !prev)}
{...getReferenceProps()}
>
{isOpen ? <IoClose /> : <IoMenu />}
</button>
{isOpen && (
<FloatingFocusManager context={context} modal={false}>
<div
ref={refs.setFloating}
style={floatingStyles}
{...getFloatingProps()}
className={styles.menu}
>
<ShareItem open={() => setShowShareLink(true)} />
<ShuffleItem />
<Divider />
<NotepadItem open={() => setShowNotepad(true)} />
<Divider />
<DonateItem />
<SourceItem />
</div>
</FloatingFocusManager>
)}
</div>
<ShareLinkModal
show={showShareLink}
onClose={() => setShowShareLink(false)}
/>
<Notepad show={showNotepad} onClose={() => setShowNotepad(false)} />
</>
);
}