mirror of
https://github.com/documenso/documenso.git
synced 2025-11-12 15:53:02 +10:00
move menu links to map, add window-size hook
This commit is contained in:
@ -13,15 +13,15 @@ import { MobileNavigation } from './mobile-navigation';
|
||||
export type HeaderProps = HTMLAttributes<HTMLElement>;
|
||||
|
||||
export const Header = ({ className, ...props }: HeaderProps) => {
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState<boolean>(false);
|
||||
const [isMobileOpen, setIsMobileOpen] = useState<boolean>(false);
|
||||
|
||||
const handleMenuToggle = () => {
|
||||
setIsMobileMenuOpen(!isMobileMenuOpen);
|
||||
setIsMobileOpen(!isMobileOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<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>
|
||||
</Link>
|
||||
|
||||
@ -43,8 +43,8 @@ export const Header = ({ className, ...props }: HeaderProps) => {
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<HamburgerMenu menuToggle={handleMenuToggle} isMenuOpen={isMobileMenuOpen} />
|
||||
<MobileNavigation isMenuOpen={isMobileMenuOpen} />
|
||||
<HamburgerMenu menuToggle={handleMenuToggle} isMenuOpen={isMobileOpen} />
|
||||
<MobileNavigation isMenuOpen={isMobileOpen} menuToggle={handleMenuToggle} />
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
@ -6,19 +6,25 @@ import { Menu, X } from 'lucide-react';
|
||||
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
|
||||
import { useWindowSize } from '~/hooks/use-window-size';
|
||||
|
||||
export interface HamburgerMenuProps {
|
||||
isMenuOpen: boolean;
|
||||
menuToggle: () => void;
|
||||
}
|
||||
|
||||
export const HamburgerMenu = ({ isMenuOpen, menuToggle }: HamburgerMenuProps) => {
|
||||
const { width } = useWindowSize();
|
||||
|
||||
useEffect(() => {
|
||||
// Update document.body.style.overflow based on the menu state
|
||||
// and check that the window width is less than 768px
|
||||
// if (window.innerWidth < 768) {
|
||||
// document.body.style.overflow = isMenuOpen ? 'hidden' : 'auto';
|
||||
// }
|
||||
}, [isMenuOpen]);
|
||||
// If the window width is less than 768px, we want to prevent scrolling when the menu is open
|
||||
if (width < 768 && isMenuOpen) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
} else {
|
||||
document.body.style.overflow = 'auto';
|
||||
}
|
||||
}, [isMenuOpen, width]);
|
||||
|
||||
return (
|
||||
<div className="flex md:hidden">
|
||||
|
||||
@ -12,12 +12,48 @@ import backgroundPattern from '~/assets/background-pattern.png';
|
||||
|
||||
export type MobileNavigationProps = {
|
||||
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 handleMenuItemClick = () => {
|
||||
menuToggle();
|
||||
};
|
||||
|
||||
const itemVariants: Variants = {
|
||||
open: {
|
||||
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">
|
||||
<Link
|
||||
passHref
|
||||
href="/blog"
|
||||
className="text-4xl font-semibold text-[#6D6D6D] hover:text-[#6D6D6D]"
|
||||
>
|
||||
<motion.p variants={itemVariants}>Blog</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>
|
||||
<motion.div className="flex w-full flex-col items-center gap-y-4 px-8 pt-12">
|
||||
{MenuNavigationLinks.map((link: MenuNavigationLinksProps) => (
|
||||
<Link
|
||||
key={link.href}
|
||||
passHref
|
||||
onClick={() => handleMenuItemClick()}
|
||||
href={link.href}
|
||||
className="text-4xl font-semibold text-[#8D8D8D] hover:text-[#6D6D6D]"
|
||||
>
|
||||
<motion.p variants={itemVariants}>{link.text}</motion.p>
|
||||
</Link>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
<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
|
||||
src={backgroundPattern}
|
||||
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>
|
||||
</motion.div>
|
||||
|
||||
35
apps/marketing/src/hooks/use-window-size.ts
Normal file
35
apps/marketing/src/hooks/use-window-size.ts
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user