Skip to content

Instantly share code, notes, and snippets.

@Malien
Last active November 17, 2024 11:11
Show Gist options
  • Select an option

  • Save Malien/9a4cf28268098934fb86d080dbfd6440 to your computer and use it in GitHub Desktop.

Select an option

Save Malien/9a4cf28268098934fb86d080dbfd6440 to your computer and use it in GitHub Desktop.
Exit animations in react
function Modal({ onClose }) {
const ref = useRef(null)
useLayoutEffect(() => {
// Enter animation
const animation = ref.current.animate(
{ opacity: [0, 1], transform: ["transitionY(-200px)", "transitionY(0)"] },
{ duration: 200, easing: "ease-in" }
)
return () => animation.cancel()
}, [])
async function handleClose() {
// Exit animation
const animation = ref.current.animate(
{ opacity: 0, transform: "transitionY(-200px)" },
{ duration: 200, easing: "ease-in", fill: "forwards" }
)
await animation.finished
onClose()
}
return <div ref={ref}">
<button type="button" onClick={handleClose}>Close</button>
</div>
}
function Parent() {
const [open, setOpen] = useState(false)
return <div>
<button type="button" onClick={() => setOpen(true)}>
Open modal
</button>
{open && <Modal onClose={() => setOpen(false)} />}
</div>
}
function Modal({ onClose }) {
const [shown, setShown] = useState(true)
const ref = useRef(null)
function handleAnimationEnd(ev) {
if (ev.target !== ref.current) return
// If you are using css modules, the animationName will be mangled
// so use the imported mapping like `animationName === styles.conceal`
if (ev.animationName !== "conceal") return
onClose()
}
let className = "dialog"
if (shown) className += " shown"
return <div ref={ref} className={className} onAnimationEnd={handleAnimationEnd}>
<button type="button" onClick={() => setShown(false)}>
Close
</button>
</div>
}
function Parent() {
const [open, setOpen] = useState(false)
return <div>
<button type="button" onClick={() => setOpen(true)}>
Open modal
</button>
{open && <Modal onClose={() => setOpen(false)} />}
</div>
}
.dialog.shown {
animation: reveal 0.2s ease-in;
}
.dialog {
animation: conceal 0.2s ease-in;
}
@keyframes reveal {
from {
opacity: 0;
transform: transitionY(-200px);
}
to {
opacity: 1;
transform: transitionY(0);
}
}
@keyframes conceal {
from {
opacity: 1;
transform: transitionY(0);
}
to {
opacity: 0;
transform: transitionY(-200px);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment