Skip to content

Commit

Permalink
Handle values removed from prop to inherited variant
Browse files Browse the repository at this point in the history
  • Loading branch information
mattgperry authored and mergatron[bot] committed Jan 3, 2024
1 parent 7bbc8cb commit b5d3f09
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 50 deletions.
85 changes: 39 additions & 46 deletions packages/framer-motion/src/gestures/__tests__/press.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,45 @@ describe("press", () => {
return expect(promise).resolves.toEqual([0.5, 1, 0.5])
})

test("press gesture on children returns to parent-defined variant", () => {
const promise = new Promise((resolve) => {
const opacityHistory: number[] = []
const opacity = motionValue(0.5)
const logOpacity = () => opacityHistory.push(opacity.get())
const Component = () => (
<motion.div animate="visible" initial="hidden">
<motion.div
data-testid="child"
variants={{
visible: { opacity: 1 },
hidden: { opacity: 0 },
}}
style={{ opacity }}
transition={{ type: false }}
whileTap={{ opacity: 0.5 }}
/>
</motion.div>
)

const { rerender, getByTestId } = render(<Component />)
rerender(<Component />)

logOpacity() // 1

// Trigger mouse down
pointerDown(getByTestId("child") as Element)

logOpacity() // 0.5

// Trigger mouse up
pointerUp(getByTestId("child") as Element)
logOpacity() // 1
resolve(opacityHistory)
})

return expect(promise).resolves.toEqual([1, 0.5, 1])
})

test("press gesture works with animation state", async () => {
const [a, b] = await new Promise((resolve) => {
const childProps = {
Expand Down Expand Up @@ -496,52 +535,6 @@ describe("press", () => {
expect(b).toHaveStyle("opacity: 0.8")
})

/**
* TODO: We want the behaviour that we can override individual componnets with their
* own whileX props to apply gesture behaviour just on that component.
*
* We want to add it in a way that maintains propagation of `animate`.
*/
// test.skip("press gesture variants - children can override with own variant", () => {
// const promise = new Promise(resolve => {
// const opacityHistory: number[] = []
// const opacity = motionValue(0.5)
// const logOpacity = () => opacityHistory.push(opacity.get())

// const Component = () => (
// <motion.div whileTap="pressed">
// <motion.div
// data-testid="child"
// variants={{
// pressed: { opacity: 1 },
// childPressed: { opacity: 0.1 },
// }}
// style={{ opacity }}
// transition={{ type: false }}
// whileTap="childPressed"
// />
// </motion.div>
// )

// const { getByTestId, rerender } = render(<Component />)
// rerender(<Component />)

// logOpacity() // 0.5

// // Trigger mouse down
// pointerDown(getByTestId("child") as Element)
// logOpacity() // 1

// // Trigger mouse up
// pointerUp(getByTestId("child") as Element)
// logOpacity() // 0.5

// resolve(opacityHistory)
// })

// return expect(promise).resolves.toEqual([0.5, 0.1, 0.5])
// })

test("press gesture variant applies and unapplies with whileHover", () => {
const promise = new Promise((resolve) => {
const opacityHistory: number[] = []
Expand Down
11 changes: 7 additions & 4 deletions packages/framer-motion/src/render/utils/animation-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ export function createAnimationState(
// If we removed a higher-priority variant (i is in reverse order)
(i > removedVariantIndex && propIsVariant)

let handledRemovedValues = false

/**
* As animations can be set as variant lists, variants or target objects, we
* coerce everything to an array if it isn't one already
Expand Down Expand Up @@ -234,7 +236,10 @@ export function createAnimationState(
}
const markToAnimate = (key: string) => {
shouldAnimateType = true
removedKeys.delete(key)
if (removedKeys.has(key)) {
handledRemovedValues = true
removedKeys.delete(key)
}
typeState.needsAnimating[key] = true
}

Expand Down Expand Up @@ -305,10 +310,8 @@ export function createAnimationState(

/**
* If this is an inherited prop we want to hard-block animations
* TODO: Test as this should probably still handle animations triggered
* by removed values?
*/
if (shouldAnimateType && !isInherited) {
if (shouldAnimateType && (!isInherited || handledRemovedValues)) {
animations.push(
...definitionList.map((animation) => ({
animation: animation as AnimationDefinition,
Expand Down

0 comments on commit b5d3f09

Please sign in to comment.