I have a project using react and motion.
Currently i have a component with a fixed overlay showing a bunch of ui. This UI lets the user toggle between 2 views, one vertical and one horizontal.
What’s happening:
- When the view is toggled various parts of the overlay fly into view from the top or bottom of the screen. This happens because the page changes hight drasticly.
What do i want to happen:
- The idea was that when changing views, the UI would stay still, fixed over the rest of the page.
I could just take out all layout animations from all motion components, but that would make the UI quite boring and it’s not my intent. I want to keep all the diferent animations but just confine them to the overlay.
I’ve tried using layoutRoot but it’s not really doing much.
Here’s a rundown of the components:
const { setComic, comic, layout, modal } = useComicReaderContext();
useEffect(() => {
setComic(currentComic);
});
return (
<div className="flex h-dvh w-full justify-center">
<AnimatePresence
initial={false}
mode="sync"
>
{layout === comicLayoutModes.VERTICAL && (
<VerticalLayout
key={'vertical'}
pages={currentComic.pages} //renders a bunch of images one under the other
/>
)}
{layout === comicLayoutModes.SINGLE_PAGE && (
<SinglePageLayout key={'singlePage'} /> // renders 1 image at a time.
)}
{modal && (
<ComicInterface
comic={currentComic}
key={'UIOverlay'}
/>
)}
</AnimatePresence>
</div>
and the interface itself:
const { title, author, tags, likes, price } = comic;
const { setModal, setDrawer, drawer } = useComicReaderContext();
return (
<motion.div
ref={overlay}
layoutRoot
key={'comicInterfaceOverlay'}
className="fixed bottom-0 left-0 right-0 top-0 z-10 w-full overflow-hidden bg-black/75"
>
<motion.div className="mx-auto flex h-full w-full justify-between gap-2 py-2 text-white md:py-8">
<AnimatePresence mode="sync">
<motion.div
transition={{ ease: 'easeInOut' }}
key="left col"
className="flex shrink-0 flex-col justify-between pl-2 md:pl-8"
>
{`some buttons`}
</motion.div>
{/* center col THISONE goes nuts when changing view*/}
<motion.div
key={'centerCol'}
onClick={(e) => onDismiss(e)}
transition={{ ease: 'easeInOut' }}
className="flex h-full w-full shrink flex-col items-center justify-center md:w-8/12"
>
<motion.button
initial={{ scale: 1 }}
layout
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
onClick={(e) => onDismiss(e)}
className="cursor-pointer inline-flex h-20 w-[150px] items-center justify-center rounded-3xl bg-primary p-2 text-sm text-black hover:shadow-[0_0_10px_1px_rgba(250,250,250,1)] md:w-[250px] md:p-4 md:text-lg"
>
Click to continue reading
</motion.button>
</motion.div>
{/* right col */}
<motion.div
key="rightCol"
layout
transition={{ duration: 0.2 }}
className={`flex flex-col justify-center gap-y-12 justify-self-end pr-2 md:pr-8`}
>
<div
className="flex flex-col items-center"
>
<div className='flex flex-col items-center w-[80px]'>
<button
onClick={() => handleToggle()}
className="border-gray rounded-full w-[50px] h-[30px] p-1 border-2 bg-body cursor-pointer flex items-center"
>
{layout === comicLayoutModes.VERTICAL && <motion.div
layout="position"
layoutId='knob'
layoutDependency={[layout, drawer]}
className={`flex items-center justify-center rounded-full bg-primary w-[20px] h-[20px] ml-auto`}
>
<GalleryVertical size={12} className='stroke-body' />
</motion.div>}
{layout === comicLayoutModes.SINGLE_PAGE && <motion.div
layoutId='knob'
layout="position"
layoutDependency={[layout, drawer]}
className={`flex items-center justify-center rounded-full bg-primary w-[20px] h-[20px] mr-auto`}
>
<GalleryHorizontal size={12} className='stroke-body' />
</motion.div>}
</button>
<span className='text-sm'>
{layout === comicLayoutModes.VERTICAL ? "Vertical" : "Single Page"}
</span>
</div>
</div>
</motion.div>
{drawer && <Drawers open={drawer} />}
</AnimatePresence>
</motion.div>
</motion.div>
);
};