move menu links to map, add window-size hook

This commit is contained in:
premiare
2023-08-18 19:35:45 +10:00
parent ad1ff6159c
commit 9b92cad2db
4 changed files with 102 additions and 58 deletions

View File

@ -13,15 +13,15 @@ import { MobileNavigation } from './mobile-navigation';
export type HeaderProps = HTMLAttributes<HTMLElement>; export type HeaderProps = HTMLAttributes<HTMLElement>;
export const Header = ({ className, ...props }: HeaderProps) => { export const Header = ({ className, ...props }: HeaderProps) => {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState<boolean>(false); const [isMobileOpen, setIsMobileOpen] = useState<boolean>(false);
const handleMenuToggle = () => { const handleMenuToggle = () => {
setIsMobileMenuOpen(!isMobileMenuOpen); setIsMobileOpen(!isMobileOpen);
}; };
return ( return (
<header className={cn('flex items-center justify-between', className)} {...props}> <header className={cn('flex items-center justify-between', className)} {...props}>
<Link href="/"> <Link href="/" className="z-10" onClick={() => isMobileOpen && handleMenuToggle()}>
<Image src="/logo.png" alt="Documenso Logo" width={170} height={0}></Image> <Image src="/logo.png" alt="Documenso Logo" width={170} height={0}></Image>
</Link> </Link>
@ -43,8 +43,8 @@ export const Header = ({ className, ...props }: HeaderProps) => {
</Link> </Link>
</div> </div>
<HamburgerMenu menuToggle={handleMenuToggle} isMenuOpen={isMobileMenuOpen} /> <HamburgerMenu menuToggle={handleMenuToggle} isMenuOpen={isMobileOpen} />
<MobileNavigation isMenuOpen={isMobileMenuOpen} /> <MobileNavigation isMenuOpen={isMobileOpen} menuToggle={handleMenuToggle} />
</header> </header>
); );
}; };

View File

@ -6,19 +6,25 @@ import { Menu, X } from 'lucide-react';
import { Button } from '@documenso/ui/primitives/button'; import { Button } from '@documenso/ui/primitives/button';
import { useWindowSize } from '~/hooks/use-window-size';
export interface HamburgerMenuProps { export interface HamburgerMenuProps {
isMenuOpen: boolean; isMenuOpen: boolean;
menuToggle: () => void; menuToggle: () => void;
} }
export const HamburgerMenu = ({ isMenuOpen, menuToggle }: HamburgerMenuProps) => { export const HamburgerMenu = ({ isMenuOpen, menuToggle }: HamburgerMenuProps) => {
const { width } = useWindowSize();
useEffect(() => { useEffect(() => {
// Update document.body.style.overflow based on the menu state // Update document.body.style.overflow based on the menu state
// and check that the window width is less than 768px // If the window width is less than 768px, we want to prevent scrolling when the menu is open
// if (window.innerWidth < 768) { if (width < 768 && isMenuOpen) {
// document.body.style.overflow = isMenuOpen ? 'hidden' : 'auto'; document.body.style.overflow = 'hidden';
// } } else {
}, [isMenuOpen]); document.body.style.overflow = 'auto';
}
}, [isMenuOpen, width]);
return ( return (
<div className="flex md:hidden"> <div className="flex md:hidden">

View File

@ -12,12 +12,48 @@ import backgroundPattern from '~/assets/background-pattern.png';
export type MobileNavigationProps = { export type MobileNavigationProps = {
isMenuOpen: boolean; isMenuOpen: boolean;
className?: string; menuToggle: () => void;
}; };
export const MobileNavigation = ({ isMenuOpen }: MobileNavigationProps) => { export interface MenuNavigationLinksProps {
href: string;
text: string;
}
export const MenuNavigationLinks = [
{
href: '/blog',
text: 'Blog',
},
{
href: '/pricing',
text: 'Pricing',
},
{
href: 'https://status.documenso.com',
text: 'Status',
},
{
href: 'mailto:support@documenso.com',
text: 'Support',
},
{
href: '/privacy',
text: 'Privacy',
},
{
href: 'https://app.documenso.com/login',
text: 'Sign in',
},
];
export const MobileNavigation = ({ isMenuOpen, menuToggle }: MobileNavigationProps) => {
const shouldReduceMotion = useReducedMotion(); const shouldReduceMotion = useReducedMotion();
const handleMenuItemClick = () => {
menuToggle();
};
const itemVariants: Variants = { const itemVariants: Variants = {
open: { open: {
opacity: 1, opacity: 1,
@ -71,51 +107,18 @@ export const MobileNavigation = ({ isMenuOpen }: MobileNavigationProps) => {
}, },
}} }}
> >
<motion.div className="flex w-full flex-col items-center gap-y-2 px-8 pt-12"> <motion.div className="flex w-full flex-col items-center gap-y-4 px-8 pt-12">
{MenuNavigationLinks.map((link: MenuNavigationLinksProps) => (
<Link <Link
key={link.href}
passHref passHref
href="/blog" onClick={() => handleMenuItemClick()}
className="text-4xl font-semibold text-[#6D6D6D] hover:text-[#6D6D6D]" href={link.href}
className="text-4xl font-semibold text-[#8D8D8D] hover:text-[#6D6D6D]"
> >
<motion.p variants={itemVariants}>Blog</motion.p> <motion.p variants={itemVariants}>{link.text}</motion.p>
</Link>
<Link
href="/pricing"
className="text-4xl font-semibold text-[#6D6D6D] hover:text-[#6D6D6D]"
>
<motion.p variants={itemVariants}>Pricing</motion.p>
</Link>
<Link
href="https://status.documenso.com"
target="_blank"
className="text-4xl font-semibold text-[#6D6D6D] hover:text-[#6D6D6D]"
>
<motion.p variants={itemVariants}>Status</motion.p>
</Link>
<Link
href="mailto:support@documenso.com"
className="text-4xl font-semibold text-[#6D6D6D] hover:text-[#6D6D6D]"
>
<motion.p variants={itemVariants}>Support</motion.p>
</Link>
<Link
href="/privacy"
className="text-4xl font-semibold text-[#6D6D6D] hover:text-[#6D6D6D]"
>
<motion.p variants={itemVariants}>Privacy</motion.p>
</Link>
<Link
href="https://app.documenso.com/login"
target="_blank"
className="text-4xl font-semibold text-[#6D6D6D] hover:text-[#6D6D6D]"
>
<motion.p variants={itemVariants}>Sign in</motion.p>
</Link> </Link>
))}
</motion.div> </motion.div>
<div className="mx-auto mt-8 flex w-full flex-wrap items-center justify-center gap-x-4 gap-y-4 "> <div className="mx-auto mt-8 flex w-full flex-wrap items-center justify-center gap-x-4 gap-y-4 ">
@ -147,7 +150,7 @@ export const MobileNavigation = ({ isMenuOpen }: MobileNavigationProps) => {
<Image <Image
src={backgroundPattern} src={backgroundPattern}
alt="background pattern" alt="background pattern"
className="-mr-[15vw] -mt-[15vh] h-full max-h-[150vh] scale-125 object-cover md:-mr-[50vw] md:scale-150 lg:scale-[175%]" className="-mr-[15vw] mt-[12vh] h-full max-h-[150vh] scale-125 object-cover md:-mr-[50vw] md:scale-150 lg:scale-[175%]"
/> />
</div> </div>
</motion.div> </motion.div>

View File

@ -0,0 +1,35 @@
import { useEffect, useState } from 'react';
// This hook is used to get the window size
// It returns an object with the width and height of the window
// Works with window resizing as well, not to be confused with isMobile from is-mobile package
interface WindowSize {
width: number;
height: number;
}
export function useWindowSize(): WindowSize {
const [windowSize, setWindowSize] = useState<WindowSize>({
width: 0,
height: 0,
});
const handleSize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
useEffect(() => {
handleSize();
window.addEventListener('resize', handleSize);
return () => {
window.removeEventListener('resize', handleSize);
};
}, []);
return windowSize;
}