Please use Desktop to view and interact with components
Components300msspring
Fluid Modal Transition
Modal that expands smoothly from clicked trigger element using layoutId
modaltransitionlayoutexpandfluid
Useto navigate between components
Preview
Code
TypeScript + React
'use client'
import { useState, useEffect } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { X } from 'lucide-react'
export function FluidModalTransition() {
const [isOpen, setIsOpen] = useState(false)
useEffect(() => {
setIsOpen(true)
}, [])
return (
<>
<button
onClick={() => setIsOpen(true)}
className="rounded-lg bg-primary px-4 py-2 text-primary-foreground"
>
Open Modal
</button>
<AnimatePresence>
{isOpen && (
<>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={() => setIsOpen(false)}
className="fixed inset-0 z-50 bg-background/80 backdrop-blur-sm"
/>
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
<motion.div
layoutId="modal-content"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ type: 'spring', stiffness: 300, damping: 30 }}
className="relative w-full max-w-lg rounded-2xl border border-border bg-card p-6 shadow-2xl"
>
<div className="mb-4 flex items-center justify-between">
<h2 className="text-xl font-semibold">Modal Title</h2>
<motion.button
whileHover={{ scale: 1.1, rotate: 90 }}
whileTap={{ scale: 0.9 }}
onClick={() => setIsOpen(false)}
className="flex h-8 w-8 items-center justify-center rounded-full hover:bg-muted"
>
<X className="h-4 w-4" />
</motion.button>
</div>
<div>
<p className="text-muted-foreground mb-4">
This is a fluid modal transition. The modal expands smoothly from the trigger element.
</p>
<p className="text-sm text-muted-foreground">Click the X button to close.</p>
</div>
</motion.div>
</div>
</>
)}
</AnimatePresence>
</>
)
}
How to Use
- 1Install Framer Motion:
npm install framer-motion - 2Copy the code from above
- 3Paste it into your project and customize as needed
- 4Colors are customizable via Tailwind CSS classes. The default theme uses dark mode colors defined in your globals.css file