Files
2026-09-04 09:04:51 -07:00

4.5 KiB

Animations Reference

Animation Drivers

Gui supports multiple animation drivers. Choose based on your platform:

Driver Package Best For
CSS @hanzogui/animations-css Web-only apps, smallest bundle
React Native @hanzogui/animations-react-native Native apps, basic animations
Reanimated @hanzogui/animations-reanimated Native apps, best performance
Motion @hanzogui/animations-motion Cross-platform spring physics

Configuration

// v5 config - import driver separately
import { defaultConfig } from '@hanzogui/config/v5'
import { animations } from '@hanzogui/config/v5-css'
// or: '@hanzogui/config/v5-motion'
// or: '@hanzogui/config/v5-rn'
// or: '@hanzogui/config/v5-reanimated'

export const config = createGui({
  ...defaultConfig,
  animations,
})

Defining Animations

CSS Driver

Uses CSS transition strings:

import { createAnimations } from '@hanzogui/animations-css'

const animations = createAnimations({
  fast: 'ease-in 150ms',
  medium: 'ease-in-out 300ms',
  slow: 'ease-out 500ms',
  bouncy: 'cubic-bezier(0.68, -0.55, 0.265, 1.55) 400ms',
})

Spring-Based Drivers (RN, Reanimated, Motion)

Use spring physics config:

import { createAnimations } from '@hanzogui/animations-react-native'

const animations = createAnimations({
  fast: {
    type: 'spring',
    damping: 20,
    stiffness: 300,
  },
  medium: {
    type: 'spring',
    damping: 15,
    stiffness: 200,
  },
  bouncy: {
    type: 'spring',
    damping: 8,
    mass: 0.8,
    stiffness: 100,
  },
})

Using Animations

Basic Animation

<View animation="medium" opacity={isVisible ? 1 : 0} y={isVisible ? 0 : 10} />

Enter/Exit Styles

<View
  animation="fast"
  enterStyle={{
    opacity: 0,
    y: -20,
    scale: 0.9,
  }}
  exitStyle={{
    opacity: 0,
    y: 20,
    scale: 0.9,
  }}
  opacity={1}
  y={0}
  scale={1}
/>

AnimatePresence (Required for Exit)

Exit animations only work inside AnimatePresence:

import { AnimatePresence } from '@hanzo/gui'

;<AnimatePresence>
  {show && (
    <View
      key="unique-key" // key is required
      animation="medium"
      enterStyle={{ opacity: 0 }}
      exitStyle={{ opacity: 0 }}
      opacity={1}
    />
  )}
</AnimatePresence>

Per-Property Animation

Override animation for specific properties:

<View
  animation={[
    'fast',
    {
      opacity: { type: 'timing', duration: 500 },
      scale: { overshootClamping: true },
    },
  ]}
  opacity={1}
  scale={1}
/>

Animatable Properties

Common animatable style properties:

  • opacity
  • x, y (translateX/Y)
  • scale, scaleX, scaleY
  • rotate, rotateX, rotateY, rotateZ
  • width, height
  • backgroundColor
  • borderColor
  • borderRadius

Hover/Press States

State-based animations:

<Button
  animation="fast"
  hoverStyle={{
    scale: 1.05,
    backgroundColor: '$blue9',
  }}
  pressStyle={{
    scale: 0.95,
    backgroundColor: '$blue11',
  }}
/>

Animation with Variants

const AnimatedCard = styled(View, {
  animation: 'medium',

  variants: {
    visible: {
      true: {
        opacity: 1,
        y: 0,
      },
      false: {
        opacity: 0,
        y: 20,
      },
    },
  } as const,
})

<AnimatedCard visible={isVisible} />

Common Patterns

Fade In

<View animation="medium" enterStyle={{ opacity: 0 }} opacity={1} />

Slide Up

<View animation="fast" enterStyle={{ opacity: 0, y: 20 }} opacity={1} y={0} />

Scale In

<View animation="bouncy" enterStyle={{ opacity: 0, scale: 0.8 }} opacity={1} scale={1} />

Modal Overlay

<Dialog.Overlay
  animation="fast"
  enterStyle={{ opacity: 0 }}
  exitStyle={{ opacity: 0 }}
  opacity={0.5}
/>

Modal Content

<Dialog.Content
  animation={['medium', { opacity: { overshootClamping: true } }]}
  enterStyle={{ opacity: 0, y: -20, scale: 0.95 }}
  exitStyle={{ opacity: 0, y: 10, scale: 0.98 }}
  opacity={1}
  y={0}
  scale={1}
/>

Tips

  1. Always provide key in AnimatePresence children
  2. Set final values on the component, not just in enterStyle
  3. Use overshootClamping for opacity to prevent negative values
  4. CSS driver doesn't support spring physics - use easing strings
  5. Test on device - animation feel differs between web and native