mirror of
https://github.com/XFox111/my-website.git
synced 2026-04-22 07:28:01 +03:00
init: First version
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
"use client";
|
||||
|
||||
import { Dismiss24Regular, Navigation24Regular } from "@fluentui/react-icons";
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import Button, { ButtonProps } from "./Button";
|
||||
import NavigationLinks from "./NavigationLinks";
|
||||
import cls from "./Sidemenu.module.scss";
|
||||
import SocialLinks from "./SocialLinks";
|
||||
import links from "@/_data/links";
|
||||
|
||||
const Sidemenu: React.FC<SidemenuProps> = ({ button, ...panelProps }) =>
|
||||
{
|
||||
const [isOpen, setOpen] = useState<boolean>(false);
|
||||
const dialogRef = useRef<HTMLDialogElement>(null);
|
||||
|
||||
const onCancel: React.ReactEventHandler<HTMLDialogElement> = useCallback((args) =>
|
||||
{
|
||||
args.preventDefault();
|
||||
setOpen(false);
|
||||
return true;
|
||||
}, []);
|
||||
|
||||
// We use this method to enable user to close the menu by clicking ouside it.
|
||||
const onClick: React.MouseEventHandler<HTMLDialogElement> = useCallback((args) =>
|
||||
{
|
||||
const wrapper = args.currentTarget.childNodes[0];
|
||||
|
||||
// If user clicked outside of the dialog boudaries, or clicked specifically on an anchor, we can close the menu
|
||||
if (!wrapper.contains(args.target as Node) || args.target instanceof HTMLAnchorElement)
|
||||
setOpen(false);
|
||||
}, []);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
dialogRef.current?.showModal();
|
||||
}
|
||||
else if (dialogRef.current?.classList.contains(cls.show)) // This check is to prevent a bug when the menu is closed before opening
|
||||
{
|
||||
dialogRef.current?.addEventListener("transitionend", function WaitForClose()
|
||||
{
|
||||
dialogRef.current?.removeEventListener("transitionend", WaitForClose);
|
||||
dialogRef.current?.close();
|
||||
});
|
||||
}
|
||||
|
||||
dialogRef.current?.classList.toggle(cls.show, isOpen);
|
||||
}, [isOpen]);
|
||||
|
||||
return <>
|
||||
<Button { ...button }
|
||||
appearance="secondary"
|
||||
title="Menu"
|
||||
onClick={ () => setOpen(true) }
|
||||
icon={ <Navigation24Regular /> } />
|
||||
|
||||
<dialog { ...panelProps } className={ `${cls.dialog} ${panelProps.className}` } ref={ dialogRef }
|
||||
onCancel={ onCancel } onClick={ onClick }>
|
||||
|
||||
<div className={ cls.wrapper }>
|
||||
|
||||
<header>
|
||||
<h3>Menu</h3>
|
||||
<Button
|
||||
appearance="secondary"
|
||||
title="Close"
|
||||
onClick={ () => setOpen(false) }
|
||||
icon={ <Dismiss24Regular /> } />
|
||||
</header>
|
||||
|
||||
<NavigationLinks className={ cls.navigation } links={ { className: cls.link } } />
|
||||
<SocialLinks />
|
||||
<Button className={ cls.resume } as="next" href={ links.resume }>Download resume</Button>
|
||||
|
||||
</div>
|
||||
</dialog>
|
||||
</>;
|
||||
};
|
||||
|
||||
export default Sidemenu;
|
||||
|
||||
export type SidemenuProps = React.DialogHTMLAttributes<HTMLDialogElement> & {
|
||||
button?: ButtonProps;
|
||||
};
|
||||
Reference in New Issue
Block a user