diff --git a/dev/examples/Animation-variants.tsx b/dev/examples/Animation-variants.tsx index 386a086ebb..4e895bacad 100644 --- a/dev/examples/Animation-variants.tsx +++ b/dev/examples/Animation-variants.tsx @@ -1,15 +1,13 @@ import React from "react" import { motion, useMotionValue } from "framer-motion" +const MotionFragment = motion(React.Fragment) + export function App() { const backgroundColor = useMotionValue("#f00") const [isActive, setIsActive] = React.useState(true) return ( - setIsActive(!isActive)} - > + setIsActive(!isActive)} style={{ ...box, backgroundColor }} /> - + ) } diff --git a/dev/package.json b/dev/package.json index 9ec05dd796..f627c0e975 100644 --- a/dev/package.json +++ b/dev/package.json @@ -1,6 +1,6 @@ { "name": "framer-motion--dev", - "version": "11.0.5", + "version": "11.0.6-alpha.1", "private": true, "scripts": { "dev": "webpack serve --config ./webpack/config.js --hot" @@ -8,8 +8,8 @@ "dependencies": { "@react-three/drei": "^7.27.3", "@react-three/fiber": "^8.2.2", - "framer-motion": "^11.0.5", - "framer-motion-3d": "^11.0.5", + "framer-motion": "^11.0.6-alpha.1", + "framer-motion-3d": "^11.0.6-alpha.1", "path-browserify": "^1.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/lerna.json b/lerna.json index fc6b8024ad..09e11752da 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "11.0.5", + "version": "11.0.6-alpha.1", "packages": [ "packages/*" ], diff --git a/packages/framer-motion-3d/package.json b/packages/framer-motion-3d/package.json index a695a8041b..ee2f080873 100644 --- a/packages/framer-motion-3d/package.json +++ b/packages/framer-motion-3d/package.json @@ -1,6 +1,6 @@ { "name": "framer-motion-3d", - "version": "11.0.5", + "version": "11.0.6-alpha.1", "description": "A simple and powerful React animation library for @react-three/fiber", "main": "dist/cjs/index.js", "module": "dist/es/index.mjs", @@ -46,7 +46,7 @@ "postpublish": "git push --tags" }, "dependencies": { - "framer-motion": "^11.0.5", + "framer-motion": "^11.0.6-alpha.1", "react-merge-refs": "^2.0.1" }, "peerDependencies": { @@ -60,5 +60,5 @@ "@react-three/test-renderer": "^9.0.0", "@rollup/plugin-commonjs": "^22.0.1" }, - "gitHead": "789e502ed2ae98982e7f0ec10f42896fb82ee6e1" + "gitHead": "e2fbe34a0b3c031b5fc856e1b4c4124479c4b754" } diff --git a/packages/framer-motion/package.json b/packages/framer-motion/package.json index 4d901fc926..20a07ce767 100644 --- a/packages/framer-motion/package.json +++ b/packages/framer-motion/package.json @@ -1,6 +1,6 @@ { "name": "framer-motion", - "version": "11.0.5", + "version": "11.0.6-alpha.1", "description": "A simple and powerful JavaScript animation library", "main": "dist/cjs/index.js", "module": "dist/es/index.mjs", @@ -85,7 +85,7 @@ "bundlesize": [ { "path": "./dist/size-rollup-motion.js", - "maxSize": "31.24 kB" + "maxSize": "31.26 kB" }, { "path": "./dist/size-rollup-m.js", @@ -116,5 +116,5 @@ "maxSize": "32.1 kB" } ], - "gitHead": "789e502ed2ae98982e7f0ec10f42896fb82ee6e1" + "gitHead": "e2fbe34a0b3c031b5fc856e1b4c4124479c4b754" } diff --git a/packages/framer-motion/src/motion/__tests__/ssr.test.tsx b/packages/framer-motion/src/motion/__tests__/ssr.test.tsx index 91628db811..0a30de2a3e 100644 --- a/packages/framer-motion/src/motion/__tests__/ssr.test.tsx +++ b/packages/framer-motion/src/motion/__tests__/ssr.test.tsx @@ -5,6 +5,8 @@ import { motionValue } from "../../value" import { AnimatePresence } from "../../components/AnimatePresence" import { Reorder } from "../../components/Reorder" +const MotionFragment = motion(React.Fragment) + function runTests(render: (components: any) => string) { test("doesn't throw", () => { render( @@ -21,6 +23,20 @@ function runTests(render: (components: any) => string) { expect(true).toBe(true) }) + test("doesn't throw when rendering Fragment", () => { + render( + + ) + + expect(true).toBe(true) + }) test("correctly renders HTML", () => { const y = motionValue(200) const div = render( diff --git a/packages/framer-motion/src/motion/__tests__/variant.test.tsx b/packages/framer-motion/src/motion/__tests__/variant.test.tsx index dd9a09e808..78fcc1b925 100644 --- a/packages/framer-motion/src/motion/__tests__/variant.test.tsx +++ b/packages/framer-motion/src/motion/__tests__/variant.test.tsx @@ -11,6 +11,8 @@ import { motionValue } from "../../value" import { useState } from "react" import { nextFrame } from "../../gestures/__tests__/utils" +const MotionFragment = motion(React.Fragment) + describe("animate prop as variant", () => { test("animates to set variant", async () => { const variants: Variants = { @@ -423,6 +425,54 @@ describe("animate prop as variant", () => { return expect(promise).resolves.toBe(0.1) }) + /** + * This test enshrines the behaviour that when a value is removed from an element as the result of a parent variant, + * it should fallback to the style prop. This is a bug in Framer Motion - the desired behaviour is that it falls + * back to the defined variant in initial. However, changing this behaviour would break generated code in Framer + * so we can't fix it until we find a migration path out of that. + */ + test("FRAMER BUG: When a value is removed from an element as the result of a parent variant, fallback to style", async () => { + const Component = ({ animate }: { animate?: string }) => { + return ( + + + + ) + } + + const { getByTestId, rerender } = render() + const element = getByTestId("child") + expect(element).toHaveStyle("opacity: 0.5") + + rerender() + rerender() + + await nextFrame() + + expect(element).toHaveStyle("opacity: 0.5") + + rerender() + rerender() + + await nextFrame() + expect(element).toHaveStyle("opacity: 1") + + rerender() + rerender() + + await nextFrame() + expect(element).toHaveStyle("opacity: 0") // Contained in variant a, which is set as initial + }) + test("initial: false correctly propagates", async () => { const promise = new Promise((resolve) => { const opacity = motionValue(0.5) diff --git a/packages/framer-motion/src/render/dom/use-render.ts b/packages/framer-motion/src/render/dom/use-render.ts index bc103c452e..3f07351f4c 100644 --- a/packages/framer-motion/src/render/dom/use-render.ts +++ b/packages/framer-motion/src/render/dom/use-render.ts @@ -1,4 +1,4 @@ -import { createElement, useMemo } from "react" +import { Fragment, createElement, useMemo } from "react" import { useHTMLProps } from "../html/use-props" import { filterProps } from "./utils/filter-props" import { isSVGComponent } from "./utils/is-svg-component" @@ -28,11 +28,10 @@ export function createUseRender(forwardMotionProps = false) { typeof Component === "string", forwardMotionProps ) - const elementProps = { - ...filteredProps, - ...visualProps, - ref, - } + const elementProps = + Component !== Fragment + ? { ...filteredProps, ...visualProps, ref } + : {} /** * If component has been handed a motion value as its child, diff --git a/yarn.lock b/yarn.lock index fea1da2098..5ee4c63ae8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8010,8 +8010,8 @@ __metadata: cache-loader: ^1.2.5 convert-tsconfig-paths-to-webpack-aliases: ^0.9.2 fork-ts-checker-webpack-plugin: ^6.2.0 - framer-motion: ^11.0.5 - framer-motion-3d: ^11.0.5 + framer-motion: ^11.0.6-alpha.1 + framer-motion-3d: ^11.0.6-alpha.1 path-browserify: ^1.0.1 react: ^18.2.0 react-dom: ^18.2.0 @@ -8080,14 +8080,14 @@ __metadata: languageName: unknown linkType: soft -"framer-motion-3d@^11.0.5, framer-motion-3d@workspace:packages/framer-motion-3d": +"framer-motion-3d@^11.0.6-alpha.1, framer-motion-3d@workspace:packages/framer-motion-3d": version: 0.0.0-use.local resolution: "framer-motion-3d@workspace:packages/framer-motion-3d" dependencies: "@react-three/fiber": ^8.2.2 "@react-three/test-renderer": ^9.0.0 "@rollup/plugin-commonjs": ^22.0.1 - framer-motion: ^11.0.5 + framer-motion: ^11.0.6-alpha.1 react-merge-refs: ^2.0.1 peerDependencies: "@react-three/fiber": ^8.2.2 @@ -8097,7 +8097,7 @@ __metadata: languageName: unknown linkType: soft -"framer-motion@^11.0.5, framer-motion@workspace:packages/framer-motion": +"framer-motion@^11.0.6-alpha.1, framer-motion@workspace:packages/framer-motion": version: 0.0.0-use.local resolution: "framer-motion@workspace:packages/framer-motion" dependencies: