framer / motion Goto Github PK
View Code? Open in Web Editor NEWOpen source, production-ready animation and gesture library for React
Home Page: https://framer.com/motion
License: MIT License
Open source, production-ready animation and gesture library for React
Home Page: https://framer.com/motion
License: MIT License
Describe the bug
When an exit animation is running while the <AnimatePresence/>
component itself gets unmounted, you get an Can't perform a React state update on an unmounted component
error.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
No state update should happen when the parent AnimatePresence is unmounted
Desktop (please complete the following information):
It would be great to get some realworld examples. When it"s production ready, we would like to see some real scenarios, like page transitions in use with react router dom.
`
const AnimationSettings = {
transition: { duration: 0.5 },
initial: { opacity: 0, y: 20 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -20 },
};
const Routes = () => {
const { location } = React.useContext(__RouterContext);
return (
<AnimatePresence {...AnimationSettings}>
<Route path="/board/:id" component={({ match }) => <BoardDetail boardId={match.params.id} />} />
<Route path="/dashboard" exact component={Dashboard} />
<Route path="/projects" exact component={Projects} />
<Route path="/createboard" exact component={CreateBoard} />
<Route path="/statistic/:id" component={({ match }) => <Statistic questionId={match.params.id} />} />
</Switch>
</AnimatePresence>
);
};
export default Routes;
`
// First render
<motion.li animate={{ x: 0 }} />
// Second render
<motion.li animate={{ y: 0 }} /> // y won't animate
Currently, because of a usually-hidden implementation detail with AnimatePresence
, using custom components works a little like this:
const Custom = ({ animate, onAnimationComplete }) => (
<motion.div
animate={animate}
onAnimationComplete={onAnimationComplete})
/>
)
const MyComponent = ({ isVisible }) => (
<AnimatePresence>
{isVisible && (
<Custom exit={{ opacity: 0 }} />
)}
</AnimatePresence>
)
Which is a bit of a mess and doesn't work well with types.
It might be possible with context to achieve an intuitive API like this:
const Custom = () => (
<motion.div exit={{ opacity: 0 }} />
)
const MyComponent = ({ isVisible }) => (
<AnimatePresence>
{isVisible && <Custom />}
</AnimatePresence>
)
Is your feature request related to a problem? Please describe.
Can't currently use with react native components
Describe the solution you'd like
support for react-native (motion.View
?)
Describe alternatives you've considered
I haven't dug much into if this is even possible atm.
Describe the bug
I created this component and put it on my app page:
function Punch({ punchIt, initialIsExit }: { initialIsExit: boolean, punchIt(): Promise<void> }) {
const [exit, setExit] = useState(initialIsExit);
const [canDrag, setCanDrag] = useState<'x' | false>('x');
const controls = useAnimation();
const [ok, setOk] = useState(false);
const x = useMotionValue(0);
const background = useTransform(x, v => backgroundColorInterpolation(Math.abs(v)));
const scale = useTransform(x, v => backgroundScaleInterpolation(Math.abs(v)));
const color = useTransform(x, v => indicatorColorInterpolation(Math.abs(v)));
const tickPath = useTransform(x, v => indicatorProgressInterpolation(Math.abs(v)));
const [svgDisplay, setSvgDisplay] = useState('none');
const okpath = useMotionValue(0);
async function onDragEnd(event: MouseEvent, info: PanInfo) {
if (Math.abs(info.point.x) > moveSize) {
setCanDrag(false);
await controls.start({
x: exit ? -moveSize : moveSize,
transition: {
ease: 'easeOut'
}
});
setExit(!exit);
await punchIt();
setOk(true);
await controls.start({
x: 0,
left: exit ? 8 : moveSize + 8,
transition: {
delay: 0.5,
duration: 0.6,
}
});
setOk(false);
setCanDrag('x');
return;
}
await controls.start({
x: 0,
transition: {
duration: 0.5
}
});
setSvgDisplay('none');
}
function okAnimationComplete() {
if (okpath.get() === 0) {
setSvgDisplay('none');
}
}
return (
<div className="punch-container">
<motion.span>
{exit ? 'Sair' : 'Entrar'}
</motion.span>
<motion.div
drag={canDrag}
animate={controls}
dragMomentum={false}
dragElastic={1}
className="punch-button"
onDragStart={() => setSvgDisplay('block')}
onDragEnd={onDragEnd}
style={{ x, left: initialIsExit ? moveSize + 8 : 8 }}>
<motion.div className="back" style={{ scale, background }} />
<motion.div animate={{ rotate: exit ? 180 : 0 }} className="icon-container">
<Icon>keyboard_arrow_right</Icon>
</motion.div>
</motion.div>
<motion.svg viewBox="0 0 50 50" style={{ display: svgDisplay }}>
<motion.path
fill="none"
strokeWidth="2"
stroke={color}
d="m 20 0 a 1 1 0 0 0 0 40 a -20 -20 20 0 0 0 -40"
style={{ translateX: 5, translateY: 5, pathLength: tickPath }}
/>
<motion.path
fill="none"
strokeWidth="2"
stroke="black"
d="M14,26 L 22,33 L 35,16"
strokeDasharray="1 0"
animate={{
pathLength: ok ? 1 : 0,
transition: {
duration: 0.4
}
}}
onAnimationComplete={okAnimationComplete}
style={{ pathLength: okpath }}
/>
</motion.svg>
</div>
);
}
But now when I try to run the test to render the entire app, throws this error:
To Reproduce
it('should renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
TypeError: element.getTotalLength is not a function
11 | const div = document.createElement('div');
12 | ReactDOM.render(<App />, div);
> 13 | ReactDOM.unmountComponentAtNode(div);
| ^
14 | });
15 |
at svg (node_modules/framer-motion/node_modules/stylefire/lib/index.js:466:48)
at createDOMStyler (node_modules/framer-motion/node_modules/stylefire/lib/index.js:491:18)
at getStyler (node_modules/framer-motion/node_modules/stylefire/lib/index.js:501:48)
at index (node_modules/framer-motion/node_modules/stylefire/lib/index.js:507:12)
at node_modules/framer-motion/dist/framer-motion.cjs.js:564:25
at commitHookEffectList (node_modules/react-dom/cjs/react-dom.development.js:17283:26)
at commitPassiveHookEffects (node_modules/react-dom/cjs/react-dom.development.js:17307:3)
at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:149:14)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:199:16)
at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:256:31)
at commitPassiveEffects (node_modules/react-dom/cjs/react-dom.development.js:18774:9)
at wrapped (node_modules/scheduler/cjs/scheduler-tracing.development.js:207:34)
at flushPassiveEffects (node_modules/react-dom/cjs/react-dom.development.js:18822:5)
at scheduleRootUpdate (node_modules/react-dom/cjs/react-dom.development.js:20570:3)
at updateContainerAtExpirationTime (node_modules/react-dom/cjs/react-dom.development.js:20600:10)
at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:20657:10)
at ReactRoot.Object.<anonymous>.ReactRoot.render (node_modules/react-dom/cjs/react-dom.development.js:20953:3)
at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:21105:12)
at node_modules/react-dom/cjs/react-dom.development.js:21178:9
at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:20459:10)
at Object.unmountComponentAtNode (node_modules/react-dom/cjs/react-dom.development.js:21177:7)
at Object.unmountComponentAtNode (src/App.spec.tsx:13:12)
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Uncaught [TypeError: element.getTotalLength is not a function]
at reportException (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
at invokeEventListeners (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:209:9)
at HTMLUnknownElementImpl._dispatch (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
at HTMLUnknownElementImpl.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
at HTMLUnknownElementImpl.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
at HTMLUnknownElement.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
at Object.invokeGuardedCallbackDev (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:199:16)
at invokeGuardedCallback (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:256:31)
at commitPassiveEffects (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:18774:9)
at wrapped (/home/rhogeranacleto/repos/dale-ponto/node_modules/scheduler/cjs/scheduler-tracing.development.js:207:34) TypeError: element.getTotalLength is not a function
at svg (/home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/node_modules/stylefire/lib/index.js:466:48)
at createDOMStyler (/home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/node_modules/stylefire/lib/index.js:491:18)
at getStyler (/home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/node_modules/stylefire/lib/index.js:501:48)
at index (/home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/node_modules/stylefire/lib/index.js:507:12)
at /home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/dist/framer-motion.cjs.js:564:25
at commitHookEffectList (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:17283:26)
at commitPassiveHookEffects (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:17307:3)
at HTMLUnknownElement.callCallback (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:149:14)
at invokeEventListeners (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
at HTMLUnknownElementImpl._dispatch (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
at HTMLUnknownElementImpl.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
at HTMLUnknownElementImpl.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
at HTMLUnknownElement.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
at Object.invokeGuardedCallbackDev (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:199:16)
at invokeGuardedCallback (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:256:31)
at commitPassiveEffects (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:18774:9)
at wrapped (/home/rhogeranacleto/repos/dale-ponto/node_modules/scheduler/cjs/scheduler-tracing.development.js:207:34)
at flushPassiveEffects (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:18822:5)
at scheduleRootUpdate (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20570:3)
at updateContainerAtExpirationTime (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20600:10)
at updateContainer (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20657:10)
at ReactRoot.Object.<anonymous>.ReactRoot.render (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20953:3)
at legacyRenderSubtreeIntoContainer (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:21105:12)
at /home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:21178:9
at unbatchedUpdates (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20459:10)
at Object.unmountComponentAtNode (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:21177:7)
at Object.unmountComponentAtNode (/home/rhogeranacleto/repos/dale-ponto/src/App.spec.tsx:13:12)
at Object.asyncJestTest (/home/rhogeranacleto/repos/dale-ponto/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)
at resolve (/home/rhogeranacleto/repos/dale-ponto/node_modules/jest-jasmine2/build/queueRunner.js:43:12)
at new Promise (<anonymous>)
at mapper (/home/rhogeranacleto/repos/dale-ponto/node_modules/jest-jasmine2/build/queueRunner.js:26:19)
at promise.then (/home/rhogeranacleto/repos/dale-ponto/node_modules/jest-jasmine2/build/queueRunner.js:73:41)
at processTicksAndRejections (internal/process/task_queues.js:86:5)
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Uncaught [TypeError: element.getTotalLength is not a function]
at reportException (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
at invokeEventListeners (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:209:9)
at HTMLUnknownElementImpl._dispatch (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
at HTMLUnknownElementImpl.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
at HTMLUnknownElementImpl.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
at HTMLUnknownElement.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
at Object.invokeGuardedCallbackDev (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:199:16)
at invokeGuardedCallback (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:256:31)
at commitPassiveEffects (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:18774:9)
at wrapped (/home/rhogeranacleto/repos/dale-ponto/node_modules/scheduler/cjs/scheduler-tracing.development.js:207:34) TypeError: element.getTotalLength is not a function
at svg (/home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/node_modules/stylefire/lib/index.js:466:48)
at createDOMStyler (/home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/node_modules/stylefire/lib/index.js:491:18)
at getStyler (/home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/node_modules/stylefire/lib/index.js:501:48)
at index (/home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/node_modules/stylefire/lib/index.js:507:12)
at /home/rhogeranacleto/repos/dale-ponto/node_modules/framer-motion/dist/framer-motion.cjs.js:564:25
at commitHookEffectList (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:17283:26)
at commitPassiveHookEffects (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:17307:3)
at HTMLUnknownElement.callCallback (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:149:14)
at invokeEventListeners (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
at HTMLUnknownElementImpl._dispatch (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
at HTMLUnknownElementImpl.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
at HTMLUnknownElementImpl.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
at HTMLUnknownElement.dispatchEvent (/home/rhogeranacleto/repos/dale-ponto/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
at Object.invokeGuardedCallbackDev (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:199:16)
at invokeGuardedCallback (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:256:31)
at commitPassiveEffects (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:18774:9)
at wrapped (/home/rhogeranacleto/repos/dale-ponto/node_modules/scheduler/cjs/scheduler-tracing.development.js:207:34)
at flushPassiveEffects (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:18822:5)
at scheduleRootUpdate (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20570:3)
at updateContainerAtExpirationTime (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20600:10)
at updateContainer (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20657:10)
at ReactRoot.Object.<anonymous>.ReactRoot.render (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20953:3)
at legacyRenderSubtreeIntoContainer (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:21105:12)
at /home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:21178:9
at unbatchedUpdates (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:20459:10)
at Object.unmountComponentAtNode (/home/rhogeranacleto/repos/dale-ponto/node_modules/react-dom/cjs/react-dom.development.js:21177:7)
at Object.unmountComponentAtNode (/home/rhogeranacleto/repos/dale-ponto/src/App.spec.tsx:13:12)
at Object.asyncJestTest (/home/rhogeranacleto/repos/dale-ponto/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)
at resolve (/home/rhogeranacleto/repos/dale-ponto/node_modules/jest-jasmine2/build/queueRunner.js:43:12)
at new Promise (<anonymous>)
at mapper (/home/rhogeranacleto/repos/dale-ponto/node_modules/jest-jasmine2/build/queueRunner.js:26:19)
at promise.then (/home/rhogeranacleto/repos/dale-ponto/node_modules/jest-jasmine2/build/queueRunner.js:73:41)
at processTicksAndRejections (internal/process/task_queues.js:86:5)
console.error node_modules/react-dom/cjs/react-dom.development.js:17117
The above error occurred in the <ForwardRef(MountMotionValuesComponent)> component:
in ForwardRef(MountMotionValuesComponent)
in ForwardRef(MountMotionValuesComponent) (created by ForwardRef(MotionComponent))
in ForwardRef(MotionComponent) (at Punch.component.tsx:105)
in svg (created by RenderComponent)
in RenderComponent (created by ForwardRef(MotionComponent))
in ForwardRef(MotionComponent) (at Punch.component.tsx:104)
in div (at Punch.component.tsx:84)
in Punch (at Home.page.tsx:24)
in div (created by Styled(MuiBox))
in Styled(MuiBox) (at Home.page.tsx:23)
in div (created by Styled(MuiBox))
in Styled(MuiBox) (at Home.page.tsx:19)
in HomePage (created by Context.Consumer)
in Route (at App.tsx:26)
in Switch (at App.tsx:25)
in div (created by Styled(MuiBox))
in Styled(MuiBox) (at App.tsx:24)
in div (created by Styled(MuiBox))
in Styled(MuiBox) (at App.tsx:17)
in Router (created by BrowserRouter)
in BrowserRouter (at App.tsx:15)
in App (at App.spec.tsx:12)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
console.error node_modules/react-dom/cjs/react-dom.development.js:17117
The above error occurred in the <ForwardRef(MountMotionValuesComponent)> component:
in ForwardRef(MountMotionValuesComponent)
in ForwardRef(MountMotionValuesComponent) (created by ForwardRef(MotionComponent))
in ForwardRef(MotionComponent) (at Punch.component.tsx:112)
in svg (created by RenderComponent)
in RenderComponent (created by ForwardRef(MotionComponent))
in ForwardRef(MotionComponent) (at Punch.component.tsx:104)
in div (at Punch.component.tsx:84)
in Punch (at Home.page.tsx:24)
in div (created by Styled(MuiBox))
in Styled(MuiBox) (at Home.page.tsx:23)
in div (created by Styled(MuiBox))
in Styled(MuiBox) (at Home.page.tsx:19)
in HomePage (created by Context.Consumer)
in Route (at App.tsx:26)
in Switch (at App.tsx:25)
in div (created by Styled(MuiBox))
in Styled(MuiBox) (at App.tsx:24)
in div (created by Styled(MuiBox))
in Styled(MuiBox) (at App.tsx:17)
in Router (created by BrowserRouter)
in BrowserRouter (at App.tsx:15)
in App (at App.spec.tsx:12)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
Expected behavior
To not throw an error and pass in render test
Screenshots
Already attached
Desktop (please complete the following information):
Additional context
When I mock the component with something like, pass correctly (although I do not want to do this)
jest.mock('./pages/Home/Punch.component', () => ({
Punch: jest.fn().mockReturnValue(<div></div>)
}));
I would like to create a custom animation with my own transition setup that is not a spring transition (e.g. tween or keyframes based).
Currently useSpring
exposes a way of creating a MotionValue
that can transition to a new value when set; however, there is no way to create a MotionValue
that uses a different transition configuration. The use cases are the same for the useSpring
hook (just using a different transition).
I could be wrong but I don't think useMotionValue
does this right now, it's more of a tracking variable for animations that are occurring.
I'd imagine this would work like useSpring
except it would allow for any transition to be specified -- useSpring
could then just be derived from useTransition
. An alternative could be to expose useTween
and useKeyframes
, but that feels like it would get annoying. Something like:
// Simple transition
const x = useTransition(0, { duration: 1, delay: 0.5 });
x.set(500); // x transitions to 500 and takes 1s after a 0.5s delay
// Spring transition
const x = useTransition(0, { type: 'spring', ...});
Describe the bug
Hello, I tried copied example /dev/examples/dragPropagation.tsx which renders a red box nested within a blue box, both draggable.
What I experience is that after dragging the blue box once, I can not drag the inner red box without effecting the blue box.
When dragging the red box before touching the blue box everything works as I expected.
Somehow stopPropagation stops working after the first drag on the outer box.
To Reproduce
Expected behavior
I expected the blue box to be uneffected by the drag of the inner, red box. Regardless of the order in which I touch them.
Desktop
It would be great to be able to define how much 'elasticity' to apply to each dragConstraint
edge using dragElastic
ie- dragElastic={{ top: 0, bottom: 0.5 }}
Trying to limit drag to only down in this demo: https://codesandbox.io/s/stoic-violet-h3bwn
Describe the bug
When AnimatePresence
children unmount, the exit animation happens to completion before positionTransition animations take place. When new children mount, no such delay exists.
To Reproduce
Steps to reproduce the behavior:
AnimatePresence
parent and <motion.*>
children.<AnimatePresence>
<motion.div />
<motion.div />
</AnimatePresence>
<motion.div>
children<motion.div
animate={{ opacity: 1 }}
initial={{ opacity: 0 }}
exit={{ opacity: 0 }}
key={uniqueKey}
positionTransition
/>
<motion.div>
children.<button onClick={handleAdd}>Add Child</button>
<AnimatePresence>
<motion.div onClick={handleRemove} {...} />
</AnimatePresence>
See example: https://codesandbox.io/s/framer-motion-reorder-animation-rlojg
Expected behavior
All animations happen simultaneously unless otherwise specified via delay prop, etc.
Desktop (please complete the following information):
Describe the bug
AnimatePresence doesn't unmount "exited" children
Expected
After the exit animation is finished, the exited child unmounts
Actual
All the previously exited children stay in DOM
Version
1.2.0
Code to reproduce
import * as React from "react"
import { Frame } from "framer"
import { motion, AnimatePresence } from "framer-motion"
export function Billboard({
width,
height,
url,
background,
backgroundSize,
transitionType,
damping,
stiffness,
duration,
easing,
}) {
const animation = {
initial: { opacity: 0 },
active: { opacity: 1 },
exit: { opacity: 0 },
}
const transition =
transitionType === "spring"
? { type: "spring", damping, stiffness }
: { type: "tween", duration, ease: easing }
return (
<Frame size="100%" overflow="hidden" background={background}>
<AnimatePresence initial={false}>
<motion.div
key={url}
initial={animation.initial}
animate={animation.active}
exit={animation.exit}
transition={transition}
style={{
position: "absolute",
width,
height,
backgroundImage: `url(${url})`,
backgroundSize,
backgroundRepeat: "no-repeat",
}}
/>
</AnimatePresence>
</Frame>
)
}
I am using AnimatePresence to slide an element up from the bottom of the screen on mount, and then slide it out to the left on unmount. Here are my variants:
defaultInitial: {
position: 'fixed',
top: '100vh',
marginLeft: '0%',
},
defaultEnter: {
position: 'relative',
marginLeft: '0%',
top: '0vh',
transition: {
duration: .5
},
},
defaultExit: {
marginLeft: '-100%',
top: '0vh',
transition: {
duration: .5
}
},
Here is my component:
<motion.div
key={currPost.id}
variants={variants}
initial="defaultInitial"
animate="defaultEnter"
exit="defaultExit"
>
The problem I am having is that on mount, the component gets a left-margin value of NEGATIVE % and then animates to 0%.
Here is a snapshot of the div as it is animating in: <div style="position: relative; margin-left: -10.2873%; top: 10.2645vh;">
I have no idea where this negative value is coming from. I have tried changing units, position values, everything. I even change leftMargin to left or even x. It still gives it some negative initial value.
This only occurs on the initial load. Subsequent transitions use their proper values.
<motion.div sizeTransition
Describe the bug
I came across this bug trying to replicate the same functionality of PoseGroup in react-pose using AnimatePresence and positionTransition in framer-motion instead. In both cases, the goal is the perform layout transition when adding and removing items inside a flexbox.
react-pose (PoseGroup): https://codesandbox.io/s/elegant-sara-6htck
framer-motion: https://codesandbox.io/s/nostalgic-carson-kezqg
In the framer-motion example, positionTransition is used in AnimatePresence to animate layout change when adding and removing items inside flexbox. The codesandbox link will show the default case (which looks like a tween) and a spring type transition.
If the Red box is toggled AFTER the unmount animation starts and BEFORE the animation finishes and completely unmounts, the spring transition target veers off course for a moment before correcting itself.
I've created some BUG buttons that toggles with specific timings to replicate this bug in the codesandbox link.
To Reproduce
Expected behavior
In the documentation,
https://www.framer.com/api/motion/migrate-from-pose/#posegroup
Paired with AnimatePresence, you have all the previous functionality of PoseGroup.
The flipMove animation from PoseGroup should be replicable with AnimatePresence and positionTransition. (If not, then consider this a feature request).
It looks like PoseGroup is able to bring the exiting component outside the layout the instance it starts its exiting transition. The remaining components is therefore able to immediately transition to its new layout
However, AnimatePresence will wait for the exiting component to finish its transition before leaving the layout causing a delay in the positionTransition of the remaining components in the layout.
Implementing this feature may solve the bug described above
Desktop (please complete the following information):
OS - windows 10
Browser - chrome
Animating height from 0
to auto
not is working properly when switching to display: block
from display: none
:
According to the Migrate from Pose documentation, non-animatable properties are automatically applied at the start of an animation. Anything that you want to be applied at the end can be set to transitionEnd
.
The bug occurs with the following combination of properties:
{
open: { display: "block", opacity: 1, height: "auto" },
collapsed: { opacity: 0, height: 0, transitionEnd: { display: "none" } }
}
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Smooth animation on opening and closing the accordion:
This works fine in Pose using the following combination of properties:
{
open: { opacity: 1, height: "auto" , applyAtStart: { display: "block" } },
collapsed: { opacity: 0, height: 0, applyAtEnd: { display: "none" }
}
Hi everyone!
I want to animate children (rotate the icon to 90 degrees) when hovering at a parent element which is a button.
<motion.button type="button" whileHover={{scale: 1.1}}>
Visit our Industry
{/*Animate this Icon to rotate 90 degrees*/}
<Icon type="arrow-up" />
</motion.button>
I also posted this question on stackoverflow and surprisingly there wasn't a framer-motion
tag yet.
Couldn't create it too, my rep < 1500. ๐
Currently AnimatePresence
doesn't warn if a component doesn't have a valid key. This is to allow toggling the visibility of single components without needing one.
We can either:
2 would miss the Slideshow
- esque use-case where we have a single child with a changing key, but would enable the toggling of visibility of a single child without a key. I am leaning towards 1.
The useRelative
hook allows for complex transforms against multiple values or motion values.
const averageX = useRelative(
(a, b, c) => (a + b + c) / 3,
xA,
xB,
xC
)
The hook works by taking a computing function and one or more related values. These related values may be numbers, strings, or motion values. When any of the related values change, the hook will compute a new value for its motion value by running the current value of each of its related values through the computing function.
The computed values may be quite complex โ and they may also include other computed values. However, the resulting code is nonetheless declarative, highly efficient, and fully juices the creative plane.
You can preview the useRelative
hook on the useRelative-useBetween branch. (An earlier version of this branch also included a second hook, useBetween
).
At the moment, each related value passed to the hook must be either of the same type (e.g. all number
s) or a mix of values and motion values of the same type (e.g. number
s and MotionValue<number>
s). This is not a hard constraint: the hook should be able to take any values and pass them into the callback accordingly; however, this may be beyond the limits of my TypeScript-Fu.
The useTransform
hook is great for computing a motion value from the result of some other motion value.
const shadowX= useTransform(xA, v => v - 4)
However, the library does not support computed values that are the result of several other values. For example, if I wanted a motion value that was between two other motion values, and which would update when either of those values changed, the solution would be pretty tedious:
const betweenX = useMotionValue(0)
const calc = React.useCallback((a, b) => {
betweenX.set(a + (b - a) / 2)
}, [])
React.useEffect(() => {
const cancelA = xA.onChange(v => calc(v, xB.get()))
const cancelB = xB.onChange(v => calc(xA.get(), v))
return () => {
cancelA()
cancelB()
}
}, [])
This hook greatly simplifies this (common) part of complex interfaces/animations.
This hook could possibly be merged into the useTransform
hook.
// Simple
useTransform(xA, v => v - 4)
// Range interpolation
useTransform(xA, [0, 100], [32, 68])
// Relative
useTransform([xA, xB], (a, b) => (a + b) / 2)
Describe the bug
A clear and concise description of what the bug is.
To Reproduce
https://codesandbox.io/s/epic-hertz-u7neg
Add new items, and they're stuck in the initial variant.
Expected behavior
Newly-rendered components should use the animate
variant.
Actual behaviour
Newly-rendered components are always in the initial
variant
Is your feature request related to a problem? Please describe.
Ability to return a new animation state for each frame, inside onUpdate.
Describe the solution you'd like
const Component = props => (
<motion.div
{...props}
onUpdate={state => ({ opacity: computeOpacity(state.rotateX), ...state })}
/>
)
const Test = () => (
<Component initial={{ rotateX: 0 }} animate={{ rotateX: 90 }} />
)
Describe alternatives you've considered
Passing motionValues
to a component via props instead. But using motionValues means you miss out on using variants, whileHover etc.
const Component = ({ rotateX }) => {
const opacity = useTransform(rotateX, computeOpacity)
return <motion.div style={{ opacity, rotateX }} />
}
const Test = () => {
const rotateX = useSpring(0)
useEffect(() => {
setTimeout(() => rotateX.set(90), 50)
}, [])
return <Component rotateX={rotateX} />
}
Describe the bug
With styled-jsx a <style jsx>{
...}</style>
tag is added right before the closing element tag in a component. Adding Motion to that component breaks the styled-jsx and does not style the component.
To Reproduce
Check out this sandbox showing the issue:
https://codesandbox.io/s/hello-world-ec8og
Expected behavior
Its expected that the styles would be applied to a motion element just like it would if it wasn't a motion element.
Desktop (please complete the following information):
Is your feature request related to a problem? Please describe.
If you render a list of drag="x"
components and try to scroll down on a touch device, a small amount of horizontal drag happens on each element that your finger touches.
Describe the solution you'd like
A generic solution could be to allow the variant styles to override the styles from the drag.
let variants = {
// this would override whatever x value the drag gesture is providing
static: { x: 0 },
swiping: { },
};
let Swipeable = () => {
let [isSwiping, setIsSwiping] = useState(0);
let onDrag = (event, info) => setIsSwiping(info.offset.x > 10);
return (
<motion.div drag="x" animate={isSwiping ? "swiping" : "static"} onDrag={onDrag} />
);
}
Describe alternatives you've considered
I also tried overriding by passing transform
styles directly to the motion.div
element.
A more specific version of this might be adding a dragThreshold
prop that would specify the offsets that the gesture must pass before the onDragStart
event is called.
Another option might be having some way to cancel the animation (but not the event) from the onDrag
handler.
Describe the bug
The <motion.div>
works only, but if I'm trying to render <motion.circle>
(as well as <motion.path>
) I get the error:
Warning: The tag <circle> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
in circle (created by RenderComponent)
in RenderComponent (created by ForwardRef(MotionComponent))
in ForwardRef(MotionComponent) (at App.js:7)
in div (at App.js:6)
in App (at src/index.js:7)
My code was taken from examples:
import React from 'react';
import { motion } from 'framer-motion';
function App() {
return (
<div className="App">
<motion.circle
style={{ scale: 2, originX: "100px", originY: "100px" }}
/>
</div>
);
}
export default App;
To Reproduce
Steps to reproduce the behavior:
Expected behavior
<motion.{anything}>
shouldn't cause the error.
Desktop (please complete the following information):
Currently Framer Motion is around 24kb gzipped and minified as a whole. With tree-shaking the motion
component alone is about 22kb.
This isn't unprecedented, with Pose being around 25kb and GSAP being in the low 30s. But a low bundle size is quite (either the American or British "quite") important to me, and I've had this thought in my head for a while that it's daft that the animation part of an animation library has to load synchronously.
I've done some experiments and I think it'd be possible to crank the core library down to 10kb. The rest could either be loaded synchronously with the main bundle, but as optional bits (for instance someone who only wants to use animations). Or using import()
the rest could be loaded in asynchronously.
For ease of use I'd like the main entry point to remain the same, with something like motion/lazy
as a safe second entry point for people who want to crank down the bundle size.
Functionality is loaded in via renderless components so we don't run, for instance, draggable code on components that aren't draggable.
These are already abstracted and loaded into a single function. It could be that we allow this to be configured and loaded in via the currently private MotionPluginContext
API. So only the functionality used in the site is loaded at all.
A further step could be that users could dynamically import this configuration, re-rendering MotionPluginContext
and its subscribers when functionality has downloaded. This could be used to defer the loading of dynamic functionality until after the initial render has finished.
At this point all animations have been abstracted behind a single function that returns a promise. As all composition also works via Promises it might work quite neatly that calls to startAnimation
occuring before Popmotion has loaded in simply wait for it to load before running.
Currently motion
components are created by iterating over two lists of tag names. Pose used to use a Proxy
to do this without maintaining lists but I had to replace it because Googlebot would crash on Pose-powered pages. Proxy
is now supported by Googlebot, which means we can support it too.
This would also theoretically reduce memory usage and start times, and allow us to support arbitrary web components out of the box.
Motion performs a step of preprocessing on animation definitions to make the unanimatable animatable.
Specifically, it reads CSS variable definitions from the DOM and makes them numbers/colors, and it detects incompatible from/tos like "100vh"
-> "100px"
and converts those to pixel values by measuring the DOM. This function is only called when we start an animation. This wouldn't be as neat to abstract as startAnimation
as it doesn't currently live behind a Promise
. But ValueAnimationControls.animate
does - and maybe we can do something there to defer until this functionality is present.
See the motion.polyline
component here: https://codesandbox.io/s/late-cherry-qpfsn
Expected: No transform origin if the user has set their own transform
. This is probably a bug in Stylefire.
Removing strokeWidth from the example initial variant:
Describe the bug
When I don't define default/initial values as attributes, the component fails with the error:
Uncaught TypeError: Cannot read property 'red' of null
To Reproduce
As an example, this component/animation fails. This should be a looping spinner.
const animation = {
strokeDasharray: ['1px, 200px', '100px, 200px', '100px, 200px'],
strokeDashoffset: [0, -15, -125],
transition: { duration: 1.4, ease: 'linear' },
};
const Spinner: FC = (): ReactElement => {
const controls = useAnimation();
const handleAnimationComplete = useCallback(() => {
controls.start(animation);
}, [controls]);
useEffect(() => {
controls.start(animation);
}, [controls]);
return (
<svg viewBox='22 22 44 44'>
<Circle
animate={controls}
onAnimationComplete={handleAnimationComplete}
cx='44'
cy='44'
r='20.2'
fill='none'
strokeWidth='3.6'
/>
</svg>
);
};
Expected behavior
Modifing the circle to the below works, but this is the only way to resolve the issue. Setting the styles in CSS (with styled-components as an example) does not help.
<Circle
animate={controls}
onAnimationComplete={handleAnimationComplete}
strokeDasharray='80px, 200px'
strokeDashoffset='0'
cx='44'
cy='44'
r='20.2'
fill='none'
strokeWidth='3.6'
/>
Desktop (please complete the following information):
Additional context
I had the same issue when trying to add a rotate
animation to an SVG element. I could not find any workaround for this one, so any help would be greatly appreciated.
const Spinner: FC= (): ReactElement => {
return (
<motion.svg viewBox='22 22 44 44' animate={{ rotate: 100 }}>
<Circle />
</motion.svg>
);
};
Other than this, I'm loving Framer Motion - amazing work!
Is your feature request related to a problem? Please describe.
I can't figure out how to implement a basic parallax on viewport scroll, so a simple and clear example in the docs would be awesome.
Describe the solution you'd like
A simple example of a few different divs moving around in relationship to viewport scroll position.
Describe alternatives you've considered
I'm reading through the MotionValue API docs but it's not really clicking for me yet.
Additional context
I mean, any other use cases for MotionValue I can think of I will add, I guess.
XD
in the Pose Migration docs it could be worth explaining how to migrate the passive values feature of Pose to Motion using MotionValues?
Is your feature request related to a problem? Please describe.
useViewportScroll
only works with the body
element.
Describe the solution you'd like
I'd like if useViewportScroll
could optionally accept a ref to an element and use the closest scroll container.
Describe alternatives you've considered
I noticed that the docs suggest rolling this yourself, but I think it could be helpful to provide out of the box.
I'd be happy to submit a PR with this functionality, please let me know ๐.
When rendering components with positionTransition
server-side, React complains about useLayoutEffect
.
We're not doing anything that would affect the first render but we do need useLayoutEffect
for this specific use-case.
As this functionality is loaded in via a renderless component, we can add the presence of window
to the check as to whether or not this component should be rendered.
Hi! Cool library, great design ๐
https://www.framer.com/api/motion/examples/
https://github.com/framer/api-docs/blob/master/pages/motion/examples.mdx
Position transitions codesandbox link is pointing to https://codesandbox.io/s/framer-motion-drag-with-constraints-pjn6t?fontsize=14&module=%2Fsrc%2FExample.tsx instead of the expected one.
edit: you're even using the brand colours for your labels! too good ๐
Hi there,
Apologies in advance if this isn't to correct place to ask for help.
I'm working on adding framer-motion
into a react project I'm working on and can't seem to get the useViewportScroll
feature to work properly in my project.
I've created an isolated component within my app to test out this feature called DivTest
you can find the project here: https://codesandbox.io/s/github/h-jennings/portfolio-2019 and the test component is in the src/js/components/
folder in the project. Here's a public github repo link if that's easier: https://github.com/h-jennings/portfolio-2019.
Anyway, by following the docs I'm expecting the <motion.div className="divTest" style={{ scale }} />
components scale value to increase on scroll. This is the codeSandbox that I referenced: https://codesandbox.io/s/c4ww4?module=%2Fsrc%2FExample.tsx
I've been poking away at this component for an hour or 2, plus reading the docs and I'm just not sure at this point if I'm using the syntax correctly, or importing the library incorrect etc.
Any help or advice would be appreciated!
Describe the bug
Width gets stuck at 100% when hovering in a basic example
To Reproduce
Expected behavior
It should animate back to the initial width on mouse out.
Codesandbox
https://codesandbox.io/s/variants-k9vfb
Desktop (please complete the following information):
Let's say you need to get x from 0 to 100 over the course of 7.5 seconds. For the first 2 seconds, you want to use a cubic bezier ease, then for the next 4 seconds you want to use a linear ease, and then for the remaining time, you want to use another cubic bezier ease. You could split this up into 3 separate animations, but you'd need to know what the value of x should be at 2s and 6s. That's not easy to calculate, so turning transition into an array would take care of it. It might look something like this:
x: 100,
transition: [
{
duration: 2,
ease: [.3,0,.3,1]
},
{
duration: 4,
ease: 'linear'
},
{
duration: 1.5,
ease: [.6,0,1,.7]
}
]
Describe the bug
I am trying to use AnimatePresence in Menu example.
To Reproduce
https://codesandbox.io/s/framer-motion-side-menu-erz68?from-embed
Expected behavior
Is there a way to animate whole tree on exit or only top children ?
Add scale: 0.5
to collapsed
and scale: 1
to open
in https://codesandbox.io/s/framer-motion-viewport-scroll-and-svg-path-animation-9r68o - you can see the open/collapse animations jump at the end.
This is because we're using getBoundingClientRect
to measure the element before and after we apply height: auto
. We need to do this because we're also measuring unit type conversion for x
and y
too - otherwise we could probably just use offsetHeight
etc.
It might be that we can first set scale
and rotate
to their defaults before measuring the before/after bounding boxes. And then restore them to their previous values.
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
Calling .set and passing a value seems to snap the element into place instead of animating, is this expected behaviour?
A motion
prop for HTML elements, sizeTransition
, that enables content to animate between layout sizes.
Mirroring positionTransition
, sizeTransition
would animate components when they change width
/height
as the result of a re-render.
<motion.div sizeTransition>
<Content />
</motion.div>
sizeTransition
can be defined either a boolean:
<motion.div sizeTransition />
or a Transition
:
<motion.div sizeTransition={{ duration: 1 }} />
width
/height
In the first iteration, it'll animate width
and height
from their previous to their new measured dimension.
scaleX
/scaleY
By default, animating width
and height
will trigger layout. This can be slow and is better avoided for consistent 60fps animations. A more performant way would be animate scale
.
This will necessitate either an inversion prop or component that can "undo" the scaling effect (so only the container visually scales).
Prop:
<motion.div sizeTransition>
<motion.div invertScale>{contents}</motion.div>
</motion.div>
Component:
<motion.div sizeTransition>
<InvertScale>{contents}</InvertScale>
</motion.div>
At parent scale
s of < ~0.05 - ~0.1 we can fade this element out to prevent scaling to Infinity
.
Is the presence of an inversion prop/component a pre-requisite to enable the scale
performance animation? And/or the signal to use scale
over width
/height
?
positionTransition
(prospective)width
and height
will naturally reflow-components every frame, but it isn't performant. But scale
doesn't effect layout, so its surrounding components would "jump" into their new layout.
It'd be good if at least sibling components could respond to each other's scale
resizing with a co-ordinated animation. So for instance this code:
<motion.div style={{ height: isOpen ? 'auto' : 0 }} sizeTransition positionTransition>
<InvertScale>{contents}</InvertScale>
</motion.div>
<motion.div style={{ height: isOpen ? 'auto' : 0 }} sizeTransition positionTransition>
<InvertScale>{contents}</InvertScale>
</motion.div>
As one component animate in size via scale
, its surrounding components would animate in position using x
/y
.
As sizing isn't abstracted the way positional layout is to x/y, this should drop-in to Frame
. Animating the position of surrounding components would require them to be in a DOM layout, ie Stack
.
I want to do this, passing the gatsby-image component `Img into a styled component, while animating it, like so:
const AnimatedImage = styled(motion(Img))`
width: 200px;
height: auto;
`
but this does not seem to work, giving me this error:
TypeError: Object(...) is not a function
Module.<anonymous>
src/pages/index.js:81
78 | }
79 | `
80 |
> 81 | const LaxImg = styled(motion(Img))`
82 | width: 200px;
83 | height: auto;
84 | `
it seems to work with regular html tags, just not react components, which is no bueno for me :-(
Am i doing something wrong? Is something like this not supported? It really needs to be supported, so hopefully I am doing something wrong or it's on the way.
Im struggling to figure out how i might rewrite the following example if there was an indefinite number of cards in the UI.
https://codesandbox.io/s/happy-bhabha-i3q10
As you can see Ive manually declared springs at the top for each of my cards, each using the last as a base:
const frontX = useMotionValue(0)
const middleX = useSpring(frontX, spring)
const backX = useSpring(middleX, spring)
My initial thought was to map through an array of cards and create a spring for each one to later iterate through in my return, but quickly remembered that you cant use hooks inside closures.
Does something like useSprings
exist in the API where you might be able to pass a base motionValue
& springConfig
and returns an array of springs, each based on the last? Another use case for something like this might be chatheads.
Thanks!
Describe the bug
When the onDragStart
callback updates a state (and schedules a render) the dragConstraints are initially ignored.
https://codesandbox.io/s/determined-meitner-zufuz
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The dragConstraints should be always respected
Desktop (please complete the following information):
Describe the bug
When creating a simple button like this: <motion.button animate={{opacity: 1}}>Test</motion.button>
I get the following error:
/Users/bjoern/projects/CoolPlaces/frontend/node_modules/react-ssr-prepass/dist/react-ssr-prepass.development.js:546
throw error;
^
TypeError: Component is not a function
at renderWithHooks (/Users/bjoern/projects/CoolPlaces/frontend/node_modules/react-ssr-prepass/dist/react-ssr-prepass.development.js:271:18)
at render$1 (/Users/bjoern/projects/CoolPlaces/frontend/node_modules/react-ssr-prepass/dist/react-ssr-prepass.development.js:543:12)
at mount$1 (/Users/bjoern/projects/CoolPlaces/frontend/node_modules/react-ssr-prepass/dist/react-ssr-prepass.development.js:566:10)
at render$3 (/Users/bjoern/projects/CoolPlaces/frontend/node_modules/react-ssr-prepass/dist/react-ssr-prepass.development.js:804:82)
at visitElement (/Users/bjoern/projects/CoolPlaces/frontend/node_modules/react-ssr-prepass/dist/react-ssr-prepass.development.js:860:23)
at visitLoop (/Users/bjoern/projects/CoolPlaces/frontend/node_modules/react-ssr-prepass/dist/react-ssr-prepass.development.js:912:22)
at resumeVisitChildren (/Users/bjoern/projects/CoolPlaces/frontend/node_modules/react-ssr-prepass/dist/react-ssr-prepass.development.js:954:20)
at Immediate.<anonymous> (/Users/bjoern/projects/CoolPlaces/frontend/node_modules/react-ssr-prepass/dist/react-ssr-prepass.development.js:978:9)
To Reproduce
I am using Next.js together with urql, so I also use react-ssr-prepass, which is probably causing the problem
To reproduce just take this example repo: https://github.com/FormidableLabs/urql/tree/master/examples/3-ssr-with-nextjs
install framer motion and create a basic button
Desktop (please complete the following information):
Go to this example: https://codesandbox.io/s/framer-motion-directional-stagger-effect-grid-f127v
Remove the variants={{}}
prop from the parent - the animation breaks.
Variants should always propagate until they meet a child with its own animate
prop.
Describe the bug
Somewhere between 1.3 and 1.4 the combination of <AnimatePresence>
and positionTransition
on its children has stopped working - the children no longer animate their position after the exit
animation of the removed component.
To Reproduce
See https://codesandbox.io/s/framer-motion-reorder-animation-z0esb - clicking a button animates the button away, but there is no animation when reordering the other components.
If you change the framer-motion
dependency back to 1.3 the position animations work again.
Additional context
I thought I was going crazy because the example sandboxes showed this working (they're pinned to a much older version of framer), and at some point during my debugging I observed that point where the position measurement was happening was getting different results in 1.3 and 1.4. It seemed like the measuring in 1.4 was happening before the exit animation had finished, so the components position didn't seem to have changed.
Is your feature request related to a problem? Please describe.
I wanted to make a sortable grid (like this) but figured out that there is support for either x
or y
direction only
It would be amazing to have xy
Describe the solution you'd like
Add support for xy
drag
Describe the bug
When moving the mouse FAST over this animation, the animated alpha value becomes negative when the hovering ends.
<motion.div style={{ border: "solid", borderColor:"rgba(0,0,0,0)" }} whileHover={{ borderColor:"rgba(0,0,0,1)" }} > Test </div>
The result is the following error: Uncaught (in promise) Error: Complex values 'rgba(1, 0, 0, -0.00038)' and 'rgba(1, 0, 0, 0)' too different to mix. Ensure all colors are of the same type.
To Reproduce
Past the animation above into an react app.
Expected behavior
The border should become visible while hovering and invisible again after endHover.
The error-message should not tell me about different color types.
Desktop:
Describe the bug
onClick event is not registered on touch screens if the button is inside a draggable element
To Reproduce
https://codesandbox.io/s/interesting-elbakyan-on2k1
Expected behavior
Button click event should be triggered even if inside a draggable element
Smartphone (please complete the following information):
Additional context
Probably has something to do with event propogation. Setting dragPropogation={ true } does not help
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.