Initial commit
This commit is contained in:
147
src/components/navbar/expandingMenu/ExpandingMenu.tsx
Normal file
147
src/components/navbar/expandingMenu/ExpandingMenu.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
"use client";
|
||||
import { useCallback, memo } from 'react';
|
||||
import { useResponsiveMenuWidth } from './useResponsiveMenuWidth';
|
||||
import { useButtonClick } from '@/components/button/useButtonClick';
|
||||
|
||||
interface NavItem {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface ExpandingMenuProps {
|
||||
isOpen: boolean;
|
||||
onToggle: () => void;
|
||||
navItems: NavItem[];
|
||||
isScrolled?: boolean;
|
||||
}
|
||||
|
||||
const ExpandingMenu = memo<ExpandingMenuProps>(function ExpandingMenu({
|
||||
isOpen,
|
||||
onToggle,
|
||||
navItems,
|
||||
isScrolled = false
|
||||
}) {
|
||||
const { isMounted, menuWidth } = useResponsiveMenuWidth();
|
||||
|
||||
const handleNavClick = useCallback(() => {
|
||||
onToggle();
|
||||
}, [onToggle]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
rounded-theme-capped absolute top-3 right-3
|
||||
transition-[top] duration-500 ease-in-out
|
||||
${isScrolled ? '' : ''}
|
||||
`}>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className={`
|
||||
primary-button
|
||||
backdrop-blur-xs
|
||||
transition-all duration-700 ease-[cubic-bezier(0.5,0.5,0,1)]
|
||||
bg-foreground rounded-theme-capped absolute top-0 right-0
|
||||
${isOpen
|
||||
? 'w-full h-full'
|
||||
: 'h-9 w-[var(--height-9)]'
|
||||
}
|
||||
`}
|
||||
/>
|
||||
|
||||
<div className={`
|
||||
relative p-6 flex flex-col gap-6
|
||||
transition-all duration-500 ease-[cubic-bezier(0.5,0.5,0,1)]
|
||||
pointer-events-auto origin-[100%_0]
|
||||
${isOpen
|
||||
? 'scale-100 opacity-100 visible'
|
||||
: 'scale-[0.15] opacity-0 invisible'
|
||||
}
|
||||
`}
|
||||
style={{
|
||||
transition: 'all 0.5s cubic-bezier(0.5, 0.5, 0, 1), transform 0.7s cubic-bezier(0.5, 0.5, 0, 1)',
|
||||
width: isMounted ? menuWidth : 'var(--width-20)'
|
||||
}}
|
||||
>
|
||||
<p className="text-xl text-background" aria-hidden="true">Menu</p>
|
||||
<ul
|
||||
role="menu"
|
||||
className="relative list-none flex flex-col gap-3 m-0 p-0"
|
||||
>
|
||||
{navItems.map((item) => {
|
||||
const MenuButton = () => {
|
||||
const handleClick = useButtonClick(item.id, handleNavClick);
|
||||
|
||||
return (
|
||||
<button
|
||||
aria-label={`Navigate to ${item.name}`}
|
||||
className={`
|
||||
text-background flex justify-between items-center
|
||||
no-underline bg-none border-none cursor-pointer w-full
|
||||
font-inherit group
|
||||
`}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<span className="text-base">
|
||||
{item.name}
|
||||
</span>
|
||||
<div className="bg-current rounded-theme-capped shrink-0 h-2 aspect-square" />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<li
|
||||
key={item.id}
|
||||
role="menuitem"
|
||||
className="m-0 p-0 list-none"
|
||||
>
|
||||
<MenuButton />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button
|
||||
aria-label={isOpen ? 'Close menu' : 'Open menu'}
|
||||
aria-expanded={isOpen}
|
||||
aria-controls="navigation-menu"
|
||||
className={`
|
||||
transition-transform duration-700 ease-[cubic-bezier(0.5,0.5,0,1)]
|
||||
pointer-events-auto cursor-pointer rounded-theme-capped
|
||||
flex justify-center items-center
|
||||
h-9 w-[var(--height-9)] aspect-square absolute top-0 right-0
|
||||
bg-transparent border-none
|
||||
${isOpen
|
||||
? '-translate-x-3 translate-y-3'
|
||||
: 'translate-x-0 translate-y-0'
|
||||
}
|
||||
`}
|
||||
onClick={onToggle}
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className={`
|
||||
transition-transform duration-700 ease-[cubic-bezier(0.5,0.5,0,1)]
|
||||
bg-background w-[40%] h-0.25 absolute
|
||||
${isOpen
|
||||
? 'translate-y-0 rotate-45'
|
||||
: '-translate-y-1 hover:translate-y-1'
|
||||
}
|
||||
`} />
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className={`
|
||||
transition-transform duration-700 ease-[cubic-bezier(0.5,0.5,0,1)]
|
||||
bg-background w-[40%] h-0.25 absolute
|
||||
${isOpen
|
||||
? 'translate-y-0 -rotate-45'
|
||||
: 'translate-y-1 hover:-translate-y-1'
|
||||
}
|
||||
`} />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default ExpandingMenu;
|
||||
Reference in New Issue
Block a user