framer / motion

Open source, production-ready animation and gesture library for React
https://framer.com/motion
MIT License
23.39k stars 784 forks source link

[BUG] Variants with beforeChildren stopped working in 11.0.12 (still broken in 11.0.14) #2571

Closed KonradLinkowski closed 6 months ago

KonradLinkowski commented 6 months ago

1. Read the FAQs 👇

2. Describe the bug

Current variant is not applying it's styles after state change

Example video:

https://github.com/framer/motion/assets/26126510/084b407c-7d2e-489b-8bc9-ea7d3fb1b643

(It should expand and collapse)

3. IMPORTANT: Provide a CodeSandbox reproduction of the bug

Stackblitz: https://stackblitz.com/edit/vitejs-vite-u5anyc?file=src%2Fmenu.tsx

Code:

import { motion } from 'framer-motion';
import { useState } from 'react';
import viteLogo from '/vite.svg';

export const Menu = () => {
  const [isExpanded, setIsExpanded] = useState(false);

  return (
    <motion.div
      initial={false}
      animate={isExpanded ? 'expand' : 'collapse'}
      variants={{
        expand: {
          width: '18rem',
          transition: {
            duration: 0.25,
            ease: 'easeIn',
            when: 'beforeChildren',
          },
        },
        collapse: {
          width: '3.5rem',
          transition: {
            duration: 0.25,
            ease: 'easeOut',
            when: 'afterChildren',
          },
        },
      }}
      className="menu"
    >
      <button onClick={() => setIsExpanded(!isExpanded)}>resize</button>
      {isExpanded ? 'expanded' : 'collaped'}
      <div className="menu_container">
        <motion.img
          className="menu_logo"
          src={viteLogo}
          alt={'Logo'}
          variants={{
            expand: {
              opacity: 0,
              transitionEnd: {
                display: 'none',
              },
            },
            collapse: {
              opacity: 1,
              display: 'block',
            },
          }}
          transition={{
            duration: 0.2,
          }}
        />
      </div>
    </motion.div>
  );
};

4. Steps to reproduce

Steps to reproduce the behavior:

  1. Have a motion.div with two variants
  2. Set beforeChildren on one of the transitions
  3. Have a motion.img child
  4. Try changing variant
  5. Doesn't work

5. Expected behavior

  1. Works

6. Video or screenshots https://github.com/framer/motion/assets/26126510/084b407c-7d2e-489b-8bc9-ea7d3fb1b643 7. Environment details

mattgperry commented 6 months ago

Seems to be related to the transitionEnd