From 03ce7055457824cd8a34937b794766c2f36ecde3 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Wed, 18 Sep 2024 12:03:26 +0200 Subject: [PATCH 1/3] Animate values when child variant definitions change --- packages/framer-motion/package.json | 2 +- .../src/motion/__tests__/variant.test.tsx | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/framer-motion/package.json b/packages/framer-motion/package.json index c91217e49a..ef9200acb1 100644 --- a/packages/framer-motion/package.json +++ b/packages/framer-motion/package.json @@ -63,7 +63,7 @@ "clean": "rm -rf types dist lib", "test": "yarn test-server && yarn test-client", "test-ci": "yarn test", - "test-client": "jest --config jest.config.json --max-workers=2", + "test-client": "jest --config jest.config.json --max-workers=2 variant.test.tsx", "test-server": "jest --config jest.config.ssr.json", "test-watch": "jest --watch --coverage --coverageReporters=lcov --config jest.config.json", "test-e2e": "yarn test-e2e-next && yarn test-e2e-html && yarn test-e2e-react", diff --git a/packages/framer-motion/src/motion/__tests__/variant.test.tsx b/packages/framer-motion/src/motion/__tests__/variant.test.tsx index 5fae8c4b14..7f2c3c9244 100644 --- a/packages/framer-motion/src/motion/__tests__/variant.test.tsx +++ b/packages/framer-motion/src/motion/__tests__/variant.test.tsx @@ -1295,4 +1295,32 @@ describe("animate prop as variant", () => { return expect(promise).resolves.toBe("visible") }) + + test.only("changing values within an inherited variant triggers an animation", async () => { + const Component = ({ x }: { x: number }) => { + return ( + + + + ) + } + + const { rerender, getByTestId } = render() + + await nextFrame() + + const element = getByTestId("element") + + expect(element).toHaveStyle("transform: none") + + rerender() + + await nextFrame() + + expect(element).toHaveStyle("transform: translateX(100px)") + }) }) From f6d8b0d2cc70cb8e29b300ecccde22ff1b35aca2 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Wed, 18 Sep 2024 12:52:35 +0200 Subject: [PATCH 2/3] Fixing test --- packages/framer-motion/package.json | 2 +- .../src/motion/__tests__/variant.test.tsx | 4 +- .../framer-motion/src/render/VisualElement.ts | 33 -------------- packages/framer-motion/src/render/types.ts | 10 ----- .../src/render/utils/animation-state.ts | 12 ++++-- .../src/render/utils/get-variant-context.ts | 43 +++++++++++++++++++ 6 files changed, 54 insertions(+), 50 deletions(-) create mode 100644 packages/framer-motion/src/render/utils/get-variant-context.ts diff --git a/packages/framer-motion/package.json b/packages/framer-motion/package.json index ef9200acb1..c91217e49a 100644 --- a/packages/framer-motion/package.json +++ b/packages/framer-motion/package.json @@ -63,7 +63,7 @@ "clean": "rm -rf types dist lib", "test": "yarn test-server && yarn test-client", "test-ci": "yarn test", - "test-client": "jest --config jest.config.json --max-workers=2 variant.test.tsx", + "test-client": "jest --config jest.config.json --max-workers=2", "test-server": "jest --config jest.config.ssr.json", "test-watch": "jest --watch --coverage --coverageReporters=lcov --config jest.config.json", "test-e2e": "yarn test-e2e-next && yarn test-e2e-html && yarn test-e2e-react", diff --git a/packages/framer-motion/src/motion/__tests__/variant.test.tsx b/packages/framer-motion/src/motion/__tests__/variant.test.tsx index 7f2c3c9244..1f048eaddb 100644 --- a/packages/framer-motion/src/motion/__tests__/variant.test.tsx +++ b/packages/framer-motion/src/motion/__tests__/variant.test.tsx @@ -1296,10 +1296,10 @@ describe("animate prop as variant", () => { return expect(promise).resolves.toBe("visible") }) - test.only("changing values within an inherited variant triggers an animation", async () => { + test("changing values within an inherited variant triggers an animation", async () => { const Component = ({ x }: { x: number }) => { return ( - + } -export type VariantStateContext = { - initial?: string | string[] - animate?: string | string[] - exit?: string | string[] - whileHover?: string | string[] - whileDrag?: string | string[] - whileFocus?: string | string[] - whileTap?: string | string[] -} - export type ScrapeMotionValuesFromProps = ( props: MotionProps, prevProps: MotionProps, diff --git a/packages/framer-motion/src/render/utils/animation-state.ts b/packages/framer-motion/src/render/utils/animation-state.ts index ee8d631007..bd765e4873 100644 --- a/packages/framer-motion/src/render/utils/animation-state.ts +++ b/packages/framer-motion/src/render/utils/animation-state.ts @@ -12,6 +12,7 @@ import { VisualElementAnimationOptions } from "../../animation/interfaces/types" import { AnimationDefinition } from "../../animation/types" import { animateVisualElement } from "../../animation/interfaces/visual-element" import { ResolvedValues } from "../types" +import { getVariantContext } from "./get-variant-context" export interface AnimationState { animateChanges: (type?: AnimationType) => Promise @@ -96,8 +97,8 @@ export function createAnimationState( * what to animate those to. */ function animateChanges(changedActiveType?: AnimationType) { - const props = visualElement.getProps() - const context = visualElement.getVariantContext(true) || {} + const { props } = visualElement + const context = getVariantContext(visualElement.parent) || {} /** * A list of animations that we'll build into as we iterate through the animation @@ -314,9 +315,12 @@ export function createAnimationState( } /** - * If this is an inherited prop we want to hard-block animations + * If this is an inherited prop we want to skip this animation + * unless the inherited variants haven't changed on this render. */ - if (shouldAnimateType && (!isInherited || handledRemovedValues)) { + const willAnimateViaParent = isInherited && variantDidChange + const needsAnimating = !willAnimateViaParent || handledRemovedValues + if (shouldAnimateType && needsAnimating) { animations.push( ...definitionList.map((animation) => ({ animation: animation as AnimationDefinition, diff --git a/packages/framer-motion/src/render/utils/get-variant-context.ts b/packages/framer-motion/src/render/utils/get-variant-context.ts new file mode 100644 index 0000000000..f2c9089f50 --- /dev/null +++ b/packages/framer-motion/src/render/utils/get-variant-context.ts @@ -0,0 +1,43 @@ +import { VisualElement } from "../VisualElement" +import { isVariantLabel } from "./is-variant-label" +import { variantProps } from "./variant-props" + +const numVariantProps = variantProps.length + +type VariantStateContext = { + initial?: string | string[] + animate?: string | string[] + exit?: string | string[] + whileHover?: string | string[] + whileDrag?: string | string[] + whileFocus?: string | string[] + whileTap?: string | string[] +} + +export function getVariantContext( + visualElement?: VisualElement +): undefined | VariantStateContext { + if (!visualElement) return undefined + + if (!visualElement.isControllingVariants) { + const context = visualElement.parent + ? getVariantContext(visualElement.parent) || {} + : {} + if (visualElement.props.initial !== undefined) { + context.initial = visualElement.props.initial as any + } + return context + } + + const context = {} + for (let i = 0; i < numVariantProps; i++) { + const name = variantProps[i] as keyof typeof context + const prop = visualElement.props[name] + + if (isVariantLabel(prop) || prop === false) { + context[name] = prop + } + } + + return context +} From 50ea004fba7b00897fa8c1a81d032fabe47a77ec Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Wed, 18 Sep 2024 12:54:31 +0200 Subject: [PATCH 3/3] Updating bundlesize --- packages/framer-motion/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/framer-motion/package.json b/packages/framer-motion/package.json index c91217e49a..7414141e3d 100644 --- a/packages/framer-motion/package.json +++ b/packages/framer-motion/package.json @@ -98,15 +98,15 @@ "bundlesize": [ { "path": "./dist/size-rollup-motion.js", - "maxSize": "34.05 kB" + "maxSize": "33.95 kB" }, { "path": "./dist/size-rollup-m.js", - "maxSize": "6 kB" + "maxSize": "5.9 kB" }, { "path": "./dist/size-rollup-dom-animation.js", - "maxSize": "17 kB" + "maxSize": "16.9 kB" }, { "path": "./dist/size-rollup-dom-max.js", @@ -114,7 +114,7 @@ }, { "path": "./dist/size-rollup-animate.js", - "maxSize": "18 kB" + "maxSize": "17.9 kB" } ], "gitHead": "dcf88c8f6c178d1af7a8f7dec81326db5fd68cea"