Releases: nandorojo/moti
0.23.6
0.23.4
0.23: SVG (+ more) 🎨
Fixes
MotiPressable
on iOS should now have more consistent behavior. Moti no longer uses React Native Gesture Handler'sTouchableWithoutFeedback
, instead opting forPressable
.
SVG Support
Moti now has a first-class integration with react-native-svg
, making cross-platform, performant SVG animations easier than ever.
import { motifySvg } from 'moti/svg'
A higher-order component that turns any React Native SVG component into an animated moti
component. It's the same as motify
, but for SVG elements.
import { motifySvg } from 'moti/svg'
import { Svg, Rect } from 'react-native-svg'
const MotiRect = motifySvg(Rect)()
You can now pass any SVG props to the animate
property, and they will animate there:
<MotiRect
animate={{
// height sequence animation
height: [50, 100],
x: visible ? 0 : 10,
}}
transition={{
// default all to timing
type: 'timing',
x: {
// override the transition for x
},
}}
/>
This functionality compatible with all Moti features, including exit transitions & hooks like useDynamicAnimation
:
import { Rect } from 'react-native-svg'
import { motifySvg } from 'moti/svg'
import { useDynamicAnimation } from 'moti'
const MotiRect = motifySvg(Rect)()
export default function App() {
const animation = useDynamicAnimation<ComponentProps<typeof Rect>>(() => ({
x: 0,
}))
return <MotiRect state={animation} />
}
0.22: Hermes Support 🏛️
yarn add moti
This version adds support for Hermes. It was long a mystery why this didn't work properly. (Read #214)
I suspected incrementing framer-motion
's version was the cause. Its use of Proxy
could complicate things with Hermes. But adding a resolution to older versions didn't help.
I diff'd the last version of Moti that worked with Hermes (0.17
) with the first one that didn't (0.18
) and spent hours comparing them line-by-line. To my surprise, the issue didn't lie in a lockfile – rather, it was the syntax of a for loop.
Changing for (const key in styles)
to Object.keys(styles).forEach(key
fixed it.
I have no idea why the former syntax didn't work properly. It didn't throw any sort of error. But it subtly resulted in useAnimatedStyle
's worklet going stale after the first render.
You can see the one line-ish PR here at #253.
- for (const key in exitStyle || {}) {
+ Object.keys(exitStyle || {}).forEach((key) => {
Happy Friday night 🕺
v0.21.0
yarn add moti
Resolves the question posed at #221 (comment)
Transitions per-variant
const state = useAnimationState({
from: { scale: 0.5 },
to: { scale: 1, transition: { type: 'timing' } },
open: { scale: 0.7, transition: { delay: 300 } }
})
return <MotiView state={state} transition={{ delay: 50 }} />
Dynamic transitions
Same goes for useDynamicAnimation
:
const state = useDynamicAnimation(() => ({ scale: 0.5 }))
const onPress = () => {
state.animateTo({ scale: 1, transition: { delay: 300 } })
}
return <MotiView state={state} transition={{ delay: 50 }} />
v19
Overview
- 🌲 Add Reanimated 3.0 tree shaking support for Web, reducing bundle size by 80%.
- See my PR here: software-mansion/react-native-reanimated#3278
- 👨🏻🔧 Fix sequences #195, #200
- 🩻 Add
Skeleton.Group
component - ☯️ Improve skeleton memoization deep comparison
- ✂️ Remove
@motify/
packages - 🤖 Add option to pass
worklet
function toexitTransition
, allowing for use ofAnimatePresence
'scustom
prop inexitTransition
(closing #193)
Track the PR here: #216
Docs
Install
yarn add moti
Breaking Changes
@motify/
packages have been removed, greatly simplifying installation, types, maintenance, and Expo snack support.- This change should take you under a minute to update.
- Next.js users: remove
@motify/
entries from transpile modulesnext.config.js
. You should only havemoti
there now. - Expo Web users: remove
@motify/
fromwebpack.config.js
. You should only havemoti
there now. - If your app accidentally imported from
@motify/components
somewhere, please change these imports to come frommoti
instead.command + shift + F
on VSCode, and search@motify
MotiPressable
'scontainerStyle
was changed to not apply to the container in #152. This broke styling on iOS likeflex
andposition: 'absolute'
. In0.19
,containerStyle
is changed back to its original behavior from0.17
. If you need Android shadow styles onMotiPressable
, usestyle
instead ofcontainerStyle
.- It's likely this didn't affect you, but to be sure, I recommend searching all of your uses of
containerStyle
onMotiPressable
and make sure it works after the update as expected.
- It's likely this didn't affect you, but to be sure, I recommend searching all of your uses of
Components
<Skeleton.Group />
If you have many skeleton components, you can now wrap them with a single <Skeleton.Group show={loading} />
component. This will help you achieve this type of effect.
0.18
yarn add moti
Fixes
Features
- Performance improvements with faster for-loops
- Pass shared values & derived values from reanimated directly to the
animate
prop - Integration with React Native Gesture Handler using the
animate
function prop - Pass function child to
MotiPressable
- 🍿 Finally! VSCode Autoimport support for
moti/skeleton
andmoti/interactions
animate
prop as derived value
✅ This feature is working! You can pass the result of
useDerivedValue
.
const x = useSharedValue(0)
return (
<MotiView
animate={useDerivedValue(() => {
return { translateX: x.value }
})}
/>
)
This also works for transition
and exitTransition
:
const x = useSharedValue(0)
return (
<MotiView
transition={useDerivedValue(() => {
return { type: x.value > 0 ? 'timing' : 'spring' }
})}
/>
)
Breaking Changes
There are zero breaking changes in Moti 0.18
.
In the next version, the already-deprecated @motify/skeleton
will be removed in favor of moti/skeleton
. The same goes for @motify/interactions
→ moti/interactions
.
In the next release, @motify/components
and @motify/core
will be deprecated, so if you import from those (which you shouldn't anyway), please change those imports to come from moti
directly.
Future ideas
(Coming Soon) animate
prop factory function
This next feature doesn't work yet, due to a limitation from Reanimated. I opened an issue here: software-mansion/react-native-reanimated#3123. Subscribe to #185 to find out when it's available. In the meantime, you can use a derived value instead of a plain factory function.
In addition to a plain object, you can pass a function to the animate
prop. As long as it has worklet
at the top of the function, you can now use any shared/derived values inside of the animate prop!
These values will automatically animate for you, so you don't need to use withTiming
or import any hooks like useAnimatedStyle
.
const x = useSharedValue(0)
return (
<MotiView
animate={() => {
'worklet'
return { translateX: x.value }
}}
/>
)
This will work with React Native Gesture Handler gestures too!
(Coming Soon) Pass function child to MotiPressable
This next feature doesn't work yet, due to a limitation from Reanimated. I opened an issue here: software-mansion/react-native-reanimated#3123. Subscribe to #185 to find out when it's available.
As a consequence of the animate
function supporting a worklet, I added a function as children of MotiPressable
. This looks a lot like the Pressable
from react-native
. As long as you read interaction.value
inside of the animate
worklet, it will update responsively.
Notice here that we aren't importing any hooks 😎
<MotiPressable>
{(interaction) => {
return (
<MotiView
animate={() => {
'worklet'
const { pressed, hovered } = interaction.value
return { opacity: pressed ? 0.9 : 1 }
}}
/>
)
}}
</MotiPressable>
v0.17.1
v0.17.0
0.17.0 (2021-12-15)
Additions
- 🚀 Reanimated 2.3 support (+ layout animations)
- 🎸 Expo SDK 44 support
- ☝️ (Breaking change) Unified all
moti
packages into a single install (moti
,moti/skeleton
,moti/interactions
) - 🕺 Add support for multiple transforms, without needing a
transform
array - 🤳🏽 Export
MotiHover
anduseMotiHover()
frommoti/interactions
to let library authors build their own hoverables
See the small breaking change at the bottom.
Bug Fixes
- TypeScript type fixes (8586b26)
- Dependencies (2495f64)
- Expo SDK 44 Example (35be5a9)
- Make
hovered
become false when you open a modal (aae7e16)
Features
- Add decay support (be6618e)
- Document the addition of dependency arrays for hooks #120 (96c01ec)
- Add
onFocus
andonBlur
toMotiPressable
(a3ec203) - Add
onContainerLayout
&onLayout
(b77bf3f) - Move skeleton into
moti/skeleton
(dab7a4f) - Pass accessibility props to
MotiPressable
(38e7ca8) - Pass worklet to MotiPressable
transition
prop (acf1981)
Breaking Changes
@motify/interactions
and @motify/skeleton
have been moved to moti/interactions
and moti/skeleton
respectively.
Please uninstall those packages if you have them, and upgrade moti
.
yarn remove @motify/interactions @motify/skeleton
yarn add moti
Next, update your imports:
@motify/interactions
→ moti/interactions
@motify/skeleton
→ moti/skeleton
If you're on VSCode, you can click command + shift + F and then find/replace all instances of from '@motify/interactions'
.
Why?
From now on, you only need to install moti
, and you get the skeleton and interactions packages alongside it. This greatly simplifies versioning and lets you more easily upgrade moti
. It's inspired by the way Next.js uses next/link
, next/router
, etc.