--- title: JavaScript Transition Hooks Require done() Callback with css="false" impact: HIGH impactDescription: Without calling done(), JavaScript-only transitions complete immediately, skipping the animation entirely type: gotcha tags: [vue3, transition, javascript, animation, hooks, gsap, done-callback] --- # JavaScript Transition Hooks Require done() Callback with css="false" **Impact: HIGH** - When using JavaScript-only transitions (with `:css="false"`), the `@enter` and `@leave` hooks **must** call the `done()` callback to signal when the animation completes. Without calling `done()`, Vue considers the transition finished immediately, causing elements to appear/disappear without animation. This is especially important when using animation libraries like GSAP, Anime.js, or the Web Animations API. ## Task Checklist - [ ] When using `:css="false"`, always call `done()` in `@enter` and `@leave` hooks - [ ] Call `done()` when your JavaScript animation completes (in the `onComplete` callback) - [ ] Remember: `done()` is optional when CSS handles the transition, but **required** with `:css="false"` - [ ] Use `:css="false"` to prevent CSS rules from interfering with JS animations **Problematic Code:** ```vue ``` **Correct Code:** ```vue ``` ## Why Use `:css="false"`? 1. **Prevents CSS interference**: Vue won't add transition classes that might conflict 2. **Slight performance benefit**: Skips CSS transition detection 3. **Clearer intent**: Makes it explicit that JS controls the animation ```vue ``` ## Complete JavaScript Transition Example ```vue ``` ## Using Web Animations API ```vue ``` ## Common Mistakes ```javascript // WRONG: Calling done() immediately instead of after animation function onEnter(el, done) { gsap.from(el, { opacity: 0, duration: 0.5 }) done() // Called immediately - animation skipped! } // WRONG: Forgetting done() parameter function onEnter(el) { // No 'done' parameter gsap.from(el, { opacity: 0, onComplete: done // Error: done is not defined! }) } // CORRECT: Pass done to animation callback function onEnter(el, done) { gsap.from(el, { opacity: 0, duration: 0.5, onComplete: done // Called after 0.5s }) } ``` ## Reference - [Vue.js Transition - JavaScript Hooks](https://vuejs.org/guide/built-ins/transition.html#javascript-hooks) - [GSAP with Vue](https://gsap.com/resources/vue/)