Your Docusaurus site did not load properly.

A very common reason is a wrong site baseUrl configuration.

Current configured baseUrl = / (default value)

We suggest trying baseUrl =

Welcome to Moti

Moti is the universal animation package for React Native, made by Fernando Rojo.

<MotiView
from={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>

Highlights#

  • Universal: works on all platforms
  • 60 FPS animations run on the native thread
  • Mount/unmount animations, like Framer Motion
  • Powered by Reanimated 2
  • Intuitive API
  • Variant & keyframe animations
  • Strong TypeScript support
  • Highly-configurable animations
  • Sequence animations
  • Loop & repeat animations
  • Web support
  • Expo support
  • Next.js support

Motivation#

Write once, animate anywhere.#

First and foremost, I made Moti because I need animations and transitions that work well on both websites & native apps.

In my opinion, React Native has the best mental model for building products. But when it comes to designing a multi-platform product at scale, you end up using Platform.select all over the place. I consider this an anti-pattern.

If you find yourself writing Platform.OS === 'web' when building UI inside of your app, something is wrong. Platform inconsistencies should be handled by third-party libraries that provide a centralized API. That's what makes (the ideal behind) React Native's mental model so great: write once, run anywhere.

I've spent most of my open source time on such inconsistencies. For example, Dripsy encourages you to design products based on screen size, not platform.

After months of trying different animation solutions on web and native, I decided I should make my own. Then Reanimated released v2 with a hooks API, and suddenly it all made sense. What we need is a performant animation library that lets us use component props to define different animation states. Hooks shouldn't be necessary. Styles should automatically transition the way CSS transitions do.

Adding an animation should be as easy as adding a background color. It should feel like play.

I started abstracting Reanimated's hooks into a single component. Pass it plain style objects, and it does the work for you. It feels like magic, and the animations are slick.

I've used Framer Motion, React Native Animatable, React Spring, CSS transitions / keyframes throughout the years, and I wanted to combine the best of these approaches into one.

The funny part of all of this is, React web already has great solutions for animations. And yet, I'm spending my time building a solution for React Native, and then making sure it also works on web. It may seem a bit odd and circular.

A final thought#

The fact that React Native works on all platforms is great. But it's more of a consequence of its greatness than the greatness itself. What makes React Native so interesting as a technology is that it's so intuitive. Its simplicity lets you focus on the only thing that really matters: building great products, quickly. Thanks to its intuitive mental model, React Native lends itself to use on any platform.

With React Native, we have an instrument to turn ideas into great user experiences, without getting bogged down by the concept of "what platform someone is using."

Today, it might be an iPhone.

Tomorrow, it might be a virtual browser running on a cloud server.

If we get this right, it won't matter.

Background#

If you want to learn more about the Motivations behind the creation of Moti, you can read this GitHub issue that I created on Dripsy.

These tweets also preview some of the features:

Author#

Moti was created by Fernando Rojo. Follow me on Twitter to stay up to date.

Also, please star the repo on Github.

Videos#

There are a number of videos on the videos page.

Contributing to React Native#

If you're wondering how you can contribute to the React Native community, I encourage you to create packages that solve platform inconsistences. Help us give people a delightful user experience, regardless of what "device" they're using.

Here are some problems in React Native (+ Web) that are exciting to work on:

  • Popovers

December 2021 update: there are now a number of libraries tackling this. I'm also working on a secret-ish menu library that looks like Radix UI. Stay tuned on Twitter.

  • This is missing in React Native, especially with web compatibility. We need something like react-popover.

  • Tooltips, popovers, etc. are crucial to building a good app, namely on web.

  • For popover menus, the typical expected experience is likely a bottom sheet on mobile screens, and an inline menu (or maybe a modal dialogue) on larger screens.

  • The best cross-platform solution would be a portal at the root of your app (see react-native-portal). It should measure items and overlay them accordingly.

  • If you're interested in solving this problem, it would be a huge contribution.

  • This would also allow us to make simple Toast/Notification components, etc.

  • React Native is ideal for building this. Instead of interacting with the DOM, you can just use a JS-based API.

  • Reanimated 2's measure function could be an interesting use case (but I'm not sure how stable it is.)

  • Navigation

December 2021 update: I'm so close to cracking the code for fully sharing Navigation code between Web and Native. See this thread for more: https://github.com/axeldelafosse/expo-next-monorepo-example/pull/1

  • There have been great strides from React Navigation on web, but this remains an open question in many ways. React Navigation alone should be a good solution if you don't need server side rendering.
  • I've spent a lot of time thinking about cross-platform navigation and finding quirky solutions. I use Next.js, so I combine that with expo-next-react-navigation.
  • I'll likely write a full post about my experience with cross-platform navigation down the line.
    • My main solution is to create Next.js pages, put a modal stack navigator in each page, use React Navigation for opening modals, and next/router for page changes.
    • On native, I have a single native-stack, and I change the initialRouteName depending on which tab I'm in.
    • All screens are shared across platforms.
    • Keeping URL query parameters in sync (for instance, when using them as search state) can be a challenge here. I'm still trying to get to the bottom of that.
  • All in all, I feel positively about the direction navigation is going. There are really smart people working on it. The last piece to solve is a standardized thought process.

Disclaimer#

This is a new library, so there might be bugs. I'm using it in my app, so I expect that solving any issues will be in my interest.

That said, I'm busy with a startup and made this public to contribute to the community. If you find something that doesn't work, please keep this in mind, and see if you can solve the problem before spamming the repository's issues. Open source projects can get derailed easily when people expect free work, so I want to avoid that.

For example, please investigate if an issue you're facing is due to Reanimated or Moti.

Thanks#

It's hard to name all the people I should credit for Moti. There are the obvious ones, like Software Mansion and the Expo team, who do the hard work that makes a library like this easy to build. Everyone who contributes to Reanimated has been really helpful.

Then there are the people behind great projects Framer Motion and React Spring, who gave me both guidance and inspiration on the best APIs to use.

Chadwick Maycumber has been especially helpful making Moti and Dripsy happen.

Matt Perry helped me integrate AnimatePresence, giving Moti a huge boost.

Terry Sahaidak offered useful ideas for integrating a performant API.