Skip to content

Commit 75f93b5

Browse files
committed
feat: implement body scroll lock in mobile navigation for improved user experience
- Added BodyScrollLock component to prevent background scrolling when the mobile navigation is open. - Updated MobileNavigation to utilize createPortal for rendering the overlay, enhancing the navigation's usability and accessibility. - Maintained existing navigation links while improving the overall structure and interaction of the mobile menu.
1 parent d9ed207 commit 75f93b5

1 file changed

Lines changed: 82 additions & 74 deletions

File tree

apps/website/components/Header.tsx

Lines changed: 82 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { cn } from "@/lib/utils";
44
import { Popover, Transition } from "@headlessui/react";
55
import { ChevronRight } from "lucide-react";
66
import Link from "next/link";
7-
import { Fragment, type JSX, type SVGProps } from "react";
7+
import { Fragment, useEffect, type JSX, type SVGProps } from "react";
8+
import { createPortal } from "react-dom";
89
import { Container } from "./Container";
910
import GithubStars from "./GithubStars";
1011
import { trackGAEvent } from "./analitycs";
@@ -72,84 +73,91 @@ function MobileNavIcon({ open }: { open: boolean }) {
7273
);
7374
}
7475

76+
function BodyScrollLock({ lock }: { lock: boolean }) {
77+
useEffect(() => {
78+
document.body.style.overflow = lock ? "hidden" : "";
79+
return () => {
80+
document.body.style.overflow = "";
81+
};
82+
}, [lock]);
83+
return null;
84+
}
85+
7586
function MobileNavigation() {
7687
return (
7788
<Popover>
78-
<Popover.Button
79-
className="relative z-10 flex h-8 w-8 items-center justify-center ui-not-focus-visible:outline-none"
80-
aria-label="Toggle Navigation"
81-
>
82-
{({ open }) => <MobileNavIcon open={open} />}
83-
</Popover.Button>
84-
<Transition.Root>
85-
<Transition.Child
86-
as={Fragment as any}
87-
enter="duration-150 ease-out"
88-
enterFrom="opacity-0"
89-
enterTo="opacity-100"
90-
leave="duration-150 ease-in"
91-
leaveFrom="opacity-100"
92-
leaveTo="opacity-0"
93-
>
94-
<Popover.Overlay className="fixed inset-0 bg-background/50" />
95-
</Transition.Child>
96-
97-
<Transition.Child
98-
as={Fragment as any}
99-
enter="duration-150 ease-out"
100-
enterFrom="opacity-0 scale-95"
101-
enterTo="opacity-100 scale-100"
102-
leave="duration-100 ease-in"
103-
leaveFrom="opacity-100 scale-100"
104-
leaveTo="opacity-0 scale-95"
105-
>
106-
<Popover.Panel
107-
as="div"
108-
className="absolute inset-x-0 top-full mt-4 flex origin-top flex-col rounded-2xl border border-border bg-background p-4 text-lg tracking-tight text-primary shadow-xl ring-1 ring-border/5"
89+
{({ open, close }) => (
90+
<>
91+
<BodyScrollLock lock={open} />
92+
<Popover.Button
93+
className="relative z-10 flex h-8 w-8 items-center justify-center ui-not-focus-visible:outline-none"
94+
aria-label="Toggle Navigation"
10995
>
110-
<p className="px-2 py-1 text-xs font-semibold uppercase text-muted-foreground">
111-
Features
112-
</p>
113-
<MobileNavLink href="/features/application-deployment-platform">Application Deployment</MobileNavLink>
114-
<MobileNavLink href="/features/database-management-tool">Databases</MobileNavLink>
115-
<hr className="m-2 border-border" />
116-
<MobileNavLink href="/pricing">Pricing</MobileNavLink>
117-
<hr className="m-2 border-border" />
118-
<p className="px-2 py-1 text-xs font-semibold uppercase text-muted-foreground">
119-
Solutions
120-
</p>
121-
<MobileNavLink href="/enterprise">Enterprise</MobileNavLink>
122-
<MobileNavLink href="/partners">Partners</MobileNavLink>
123-
<hr className="m-2 border-border" />
124-
<MobileNavLink
125-
href="https://docs.dokploy.com/docs/core"
126-
target="_blank"
127-
>
128-
Docs
129-
</MobileNavLink>
130-
<hr className="m-2 border-border" />
131-
<p className="px-2 py-1 text-xs font-semibold uppercase text-muted-foreground">
132-
Resources
133-
</p>
134-
<MobileNavLink href="https://templates.dokploy.com" target="_blank">Templates</MobileNavLink>
135-
<MobileNavLink href="/blog">Blog</MobileNavLink>
136-
<MobileNavLink href="/#faqs">FAQ</MobileNavLink>
137-
<hr className="m-2 border-border" />
138-
<MobileNavLink href="/contact">Contact</MobileNavLink>
139-
<MobileNavLink
140-
href="https://app.dokploy.com/register"
141-
target="_blank"
96+
<MobileNavIcon open={open} />
97+
</Popover.Button>
98+
{open && createPortal(
99+
<div className="fixed inset-0 z-40 bg-background/50" onClick={() => close()} />,
100+
document.body
101+
)}
102+
<Transition.Root>
103+
<Transition.Child
104+
as={Fragment as any}
105+
enter="duration-150 ease-out"
106+
enterFrom="opacity-0 scale-95"
107+
enterTo="opacity-100 scale-100"
108+
leave="duration-100 ease-in"
109+
leaveFrom="opacity-100 scale-100"
110+
leaveTo="opacity-0 scale-95"
142111
>
143-
<Button className="w-full" asChild>
144-
<div className="group relative mx-auto flex w-full max-w-fit flex-row items-center justify-center rounded-2xl text-sm font-medium">
145-
<span>Sign In</span>
146-
<ChevronRight className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
147-
</div>
148-
</Button>
149-
</MobileNavLink>
150-
</Popover.Panel>
151-
</Transition.Child>
152-
</Transition.Root>
112+
<Popover.Panel
113+
as="div"
114+
className="absolute inset-x-0 top-full mt-4 flex origin-top flex-col rounded-2xl border border-border bg-background p-4 text-lg tracking-tight text-primary shadow-xl ring-1 ring-border/5 max-h-[80vh] overflow-y-auto"
115+
>
116+
<p className="px-2 py-1 text-xs font-semibold uppercase text-muted-foreground">
117+
Features
118+
</p>
119+
<MobileNavLink href="/features/application-deployment-platform">Application Deployment</MobileNavLink>
120+
<MobileNavLink href="/features/database-management-tool">Databases</MobileNavLink>
121+
<hr className="m-2 border-border" />
122+
<MobileNavLink href="/pricing">Pricing</MobileNavLink>
123+
<hr className="m-2 border-border" />
124+
<p className="px-2 py-1 text-xs font-semibold uppercase text-muted-foreground">
125+
Solutions
126+
</p>
127+
<MobileNavLink href="/enterprise">Enterprise</MobileNavLink>
128+
<MobileNavLink href="/partners">Partners</MobileNavLink>
129+
<hr className="m-2 border-border" />
130+
<MobileNavLink
131+
href="https://docs.dokploy.com/docs/core"
132+
target="_blank"
133+
>
134+
Docs
135+
</MobileNavLink>
136+
<hr className="m-2 border-border" />
137+
<p className="px-2 py-1 text-xs font-semibold uppercase text-muted-foreground">
138+
Resources
139+
</p>
140+
<MobileNavLink href="https://templates.dokploy.com" target="_blank">Templates</MobileNavLink>
141+
<MobileNavLink href="/blog">Blog</MobileNavLink>
142+
<MobileNavLink href="/#faqs">FAQ</MobileNavLink>
143+
<hr className="m-2 border-border" />
144+
<MobileNavLink href="/contact">Contact</MobileNavLink>
145+
<MobileNavLink
146+
href="https://app.dokploy.com/register"
147+
target="_blank"
148+
>
149+
<Button className="w-full" asChild>
150+
<div className="group relative mx-auto flex w-full max-w-fit flex-row items-center justify-center rounded-2xl text-sm font-medium">
151+
<span>Sign In</span>
152+
<ChevronRight className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
153+
</div>
154+
</Button>
155+
</MobileNavLink>
156+
</Popover.Panel>
157+
</Transition.Child>
158+
</Transition.Root>
159+
</>
160+
)}
153161
</Popover>
154162
);
155163
}

0 commit comments

Comments
 (0)