Reputation: 1
my goal is, when the navigation menu is opened and the popover gets displayed, to disable scrolling on the page. And then, on close, restore scrolling.
I write in typescript using nextJs, tailwind css, framer motion, next-intl and of course headless-ui (all last releases).
Couldn't seem to find any similar question or solution.
Thanks for your time and help
current interface with scrolling always enabled
Here is my code with a trivial solution I found...
import {
Popover,
PopoverBackdrop,
PopoverButton,
PopoverPanel,
} from '@headlessui/react';
import { EnvelopeOpenIcon } from '@heroicons/react/20/solid';
import { Bars3Icon, ChevronUpIcon } from '@heroicons/react/24/solid';
import { AnimatePresence, motion } from 'framer-motion';
import { Button } from './Button';
import { MobileNavLinks } from './NavLinks';
export default function MobileNavigation() {
return (
<Popover>
{({ open }) => {
document.body.style.overflow = open ? 'hidden' : 'auto';
console.log(open);
return (
<>
<PopoverButton
className="relative flex size-12 z-10 items-center justify-center rounded-lg stroke-mcm p-2 hover:bg-gray-200/50 hover:stroke-gray-600 active:stroke-gray-900 ui-not-focus-visible:outline-none focus-visible:outline-none"
aria-label="Toggle site navigation"
>
{({ open }) =>
open ? (
<ChevronUpIcon className="h-7 w-7" />
) : (
<Bars3Icon className="h-7 w-7" />
)
}
</PopoverButton>
<AnimatePresence initial={false}>
{open && (
<>
<PopoverBackdrop
static
as={motion.div}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-0 bg-gray-300/60 backdrop-blur"
/>
<PopoverPanel
static
as={motion.div}
initial={{ opacity: 0, y: -32 }}
animate={{ opacity: 1, y: 0 }}
exit={{
opacity: 0,
y: -32,
transition: { duration: 0.2 },
}}
className="absolute inset-x-0 top-0 z-0 origin-top rounded-b-2xl bg-gray-50 px-6 pb-6 pt-24 shadow-2xl shadow-gray-900/20"
>
<div className="space-y-4">
<MobileNavLinks />
<PopoverButton
as={Button}
className="sm:hidden"
label="contacts"
icon={
<EnvelopeOpenIcon className="h-7 w-7" />
}
color="blue"
></PopoverButton>
</div>
</PopoverPanel>
</>
)}
</AnimatePresence>
</>
);}
}
</Popover>
);
}
document.body.style.overflow = open ? 'hidden' : 'auto';
works but the evaluation get's called multiple times during React's re-render cycles.
Could't figure out how to integrate useEffect() in here, without incurring in errors like:
React Hook "useEffect" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.eslintreact-hooks/rules-of-hooks
Upvotes: 0
Views: 371