Skip to content

Instantly share code, notes, and snippets.

@wking-io
Last active October 31, 2024 13:35
Show Gist options
  • Save wking-io/c2f93179562ca7efd5c2b64d8bace577 to your computer and use it in GitHub Desktop.
Save wking-io/c2f93179562ca7efd5c2b64d8bace577 to your computer and use it in GitHub Desktop.
AnimatePresence Fix
import { AnimatePresence, motion, Variants } from 'framer-motion'
import * as DialogPrimitive from '@radix-ui/react-dialog'
import { forwardRef, PropsWithChildren, useState } from 'react'
import clsx from 'clsx'
export default function Page() {
const [open, setOpen] = useState(false)
return (
<div>
<button onClick={() => setOpen(true)}>Open Modal</button>
<Dialog open={open} onClose={() => setOpen(false)}>
Hello world
</Dialog>
</div>
)
}
function Dialog({
open,
onClose,
className,
children,
}: PropsWithChildren<{ open: boolean; onClose(): void; className?: string }>) {
return (
<Fade show={open}>
<DialogPrimitive.Root open={open} onOpenChange={onClose}>
<DialogPrimitive.Portal>
<div className="relative z-50">
<Fade className="fixed inset-0 z-50" nested>
<DialogPrimitive.Overlay className="bg-foreground/[80%] fixed inset-0 flex w-screen justify-center overflow-y-auto p-2 focus:outline-0" />
</Fade>
<div className="fixed inset-0 z-50 w-screen overflow-y-auto pt-6 sm:pt-0">
<div className="grid min-h-full grid-rows-[4rem_auto_auto] justify-items-center p-4 lg:grid-rows-[8rem_auto_auto] 2xl:grid-rows-[12rem_auto_auto]">
{open && (
<DialogPrimitive.Content
asChild
onInteractOutside={(e) => {
// Don't close the dialog when a 1password button is clicked inside a password field
if (e.target.tagName === 'COM-1PASSWORD-BUTTON') {
e.preventDefault()
}
}}
>
<motion.div
initial={{ opacity: 0, transform: 'translateY(10%)' }}
animate={{ opacity: 1, transform: 'translateY(0)' }}
exit={{ opacity: 0, transform: 'translateY(10%)' }}
className={clsx('row-start-2 w-full max-w-lg', className)}
>
<div
className={clsx(
'bg-background shadow-dialog relative overflow-hidden rounded-2xl p-5 transition-all duration-300 forced-colors:outline',
)}
>
{children}
</div>
</motion.div>
</DialogPrimitive.Content>
)}
</div>
</div>
</div>
</DialogPrimitive.Portal>
</DialogPrimitive.Root>
</Fade>
)
}
export const Fade = forwardRef<
HTMLDivElement,
PropsWithChildren<{ show?: boolean; nested?: boolean; className?: string }>
>(({ children, show = false, nested = false, ...props }, ref) => {
const child = (
<motion.div
ref={ref}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
{...props}
>
{children}
</motion.div>
)
return nested ? (
child
) : (
<AnimatePresence>{show ? child : null}</AnimatePresence>
)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment