Core
Tamagui
Extras
Guides
Community
Pluggable animation drivers.
Pluggable drivers, fully typed and easy to swap.
Support hover, press, and focus animations.
Supports enter animation on mount.
Supports exit animation with AnimatePresence.
Add animations to Tamagui with an animation driver.
Animation drivers are designed to be swappable, so you can use lightweight CSS animations or other web-focused animation libraries on the web, while using larger but more advanced libraries like reanimated
on native - all without having to change a line outside of configuration.
The @tamagui/animations-css
package works with the tamagui compiler and runtime to give you simple ways to share typed animations across all your components.
To install it add to your package.json:
yarn add @tamagui/animations-css
Then add it to your config:
import { createAnimations } from '@tamagui/animations-css'import { createTamagui } from 'tamagui'export default createTamagui({animations: createAnimations({fast: 'ease-in 150ms',medium: 'ease-in 300ms',slow: 'ease-in 450ms',}),// ...})
At runtime, the plugin does very little except to set the transition
property in CSS. At compile-time, the compiler do the same, ensuring you get all the benefits of prop removal and view flattening even when using animations.
React Native's Animated library is the animation library that comes built into React Native and React Native Web.
To install it add to your package.json:
yarn add @tamagui/animations-react-native
Then add it to your config:
import { createAnimations } from '@tamagui/animations-react-native'import { createTamagui } from 'tamagui'export default createTamagui({animations: createAnimations({fast: {damping: 20,mass: 1.2,stiffness: 250,},medium: {damping: 10,mass: 0.9,stiffness: 100,},slow: {damping: 20,stiffness: 60,},}),// ...})
Reanimated is an animation library that targets React Native and React Native Web. It runs off-thread animations, and provides nicer syntax and hooks. It weighs over 100Kb minified though, which makes it not always useful for the web.
To install it add to your package.json:
yarn add @tamagui/animations-reanimated
Then add it to your config:
import { createAnimations } from '@tamagui/animations-reanimated'import { createTamagui } from 'tamagui'export default createTamagui({animations: createAnimations({fast: {type: 'spring',damping: 20,mass: 1.2,stiffness: 250,},medium: {type: 'spring',damping: 10,mass: 0.9,stiffness: 100,},slow: {type: 'spring',damping: 20,stiffness: 60,},}),// ...})
At runtime, this plugin parses animatable style properties and hands them over to reanimated off-thread, using worklets. It doesn't do anything at compile time - reanimated must run via JS.
Note the keys match between CSS and reanimated, so you can swap them out.
Save bundle size by removing Animated
and AnimatedFlatList
from react-native-web. On
Next.js, use the excludeReactNativeWebExports` option config
option.
The animation
can now accept slow
as a value. By default, animations will apply to all animatable styles, a lot like setting all
in a CSS transition
. Let's test this by setting hoverStyle
:
Here's an example animating hoverStyle
:
Setting enterStyle
styles on any component tell it to start with those styles, and immediately transition into their regular styles:
The animation
prop accepts a string or a more complex object to customize animations per-property.
The basic object we'll call an AnimationConfig
, looks like this:
import { YStack } from 'tamagui'export default () => (<YStack animation={{ // only x and y will apply animations x: 'bouncy', y: { type: 'bouncy', overshootClamping: true, }, }} />)
Note that values can either map to AnimationKey
as a string, or to { type: AnimationKey, ...configuration }
You can set a default value using a two-arity array with the default in the first position:
import { YStack } from 'tamagui'export default () => (<YStack animation={[ // all attributes get "bouncy" 'bouncy', // these are customized { y: 'slow', scale: { type: 'fast', repeat: 2, }, }, ]} />)
The animateOnly
prop will limit your animation config to certain keys. It accepts an array of strings that correspond to style property names.
AnimatePresence animates direct children before they unmount. It's inspired by and forked from Framer Motion , but works with any animation in Tamagui.
To use with @tamagui/core
, install and import @tamagui/animate-presence
. It's already bundled and exported from tamagui
.
import { AnimatePresence, Square } from 'tamagui'export const MyComponent = ({ isVisible }) => (<AnimatePresence>{isVisible && (<Square key="my-square" animation="bounce" backgroundColor="green" size={50} exitStyle={{ size: 100, }} />)}</AnimatePresence>)
Wrap one or more tamagui components with AnimatePresence. This enables the use the exitStyle prop, which accepts all style properties and variants, which will be animated to using the animation
defined before the component is unmounted.
Animated child components must each have a unique key prop so AnimatePresence can track their presence in the tree.
AnimatePresence takes two optional special properties, enterVariant
and exitVariant
, which allow you to override enterStyle and exitStyle conditionally. These properties would be impossible to change otherwise. This is a simple example, hit "Show Code" for the carousel demo above to see a more practical usage of it:
import { AnimatePresence, Square, styled } from 'tamagui'const AnimatableSquare = styled(Square, {variants: {fromRight: {true: {x: 1000,},},fromLeft: {true: {x: -1000,},},},})export const MyComponent = ({ isVisible }) => (<AnimatePresence enterVariant="fromLeft" exitVariant="fromRight">{isVisible && (<Square key="my-square" animation="bounce" backgroundColor="green" size={50} exitStyle={{ opacity: 0, }} />)}</AnimatePresence>)
Note that it will always find the true
variant and use that. In the future, Tamagui may be able to add support for more flexible variants here.