---
source_hash: "692e9f3f"
title: "Page Animations"
weight: 50
---

# Page Animations

SmartCommon uses **Framer Motion** to animate transitions between pages. Animations are configurable per route.

## Basic Configuration

In the Provider configuration:

```javascript
const config = {
  pages: {
    "*": "fade" // Default animation for all pages
  }
};
```

## Available Animations

| Animation | Description | Effect |
| --- | --- | --- |
| `fade` | Crossfade | Opacity 0 -> 1 |
| `slideLeft` | Slide left | Enters from the right |
| `slideRight` | Slide right | Enters from the left |
| `zoom` | Zoom effect | Scale 0.9 -> 1 |

## Configuration by Route

You can define different animations based on the source and destination routes:

```javascript
const config = {
  pages: {
    // From home page
    "/": {
      "/dashboard": "slideLeft",  // To dashboard: slides left
      "/settings": "slideLeft",   // To settings: slides left
      "*": "fade"                 // To others: fade
    },

    // From dashboard
    "/dashboard": {
      "/": "slideRight",          // Back to home: slides right
      "/details": "slideLeft",    // To details: slides left
      "*": "fade"
    },

    // From settings
    "/settings": {
      "/": "slideRight",
      "*": "fade"
    },

    // For all other pages
    "*": "fade"
  }
};
```

## Navigation Logic

Animations are chosen according to this scheme:

1. Look for a config for the current page
2. If found, look for an animation for the previous page
3. If not found, use `*` for the current page
4. If no config for the current page, use global `*`

### Example

Navigation from `/dashboard` to `/`:

```javascript
pages: {
  "/": {
    "/dashboard": "slideRight", // <- This animation will be used
    "*": "fade"
  },
  "/dashboard": {
    "/": "slideRight",
    "*": "fade"
  }
}
```

The page `/` displays with `slideRight` because we came from `/dashboard`.

## Disable Slide Animations on Desktop

By default, slide animations are replaced by `fade` on desktop for better UX:

```javascript
// In the Page component (internal behavior)
if (device?.type === "desktop") {
  return "fade";
}
```

## Using the Page Component

The `Page` component automatically manages animations:

```javascript
import { Page, Block } from '@cap-rel/smartcommon';
import { useLocation } from 'react-router-dom';

const Dashboard = () => {
  const location = useLocation();

  return (
    <Page location={location}>
      <Block>
        Dashboard content
      </Block>
    </Page>
  );
};
```

> [!IMPORTANT]
> The `location` prop is required for animations to work correctly.

## Customizing Animations

You can create custom animations by modifying Framer Motion variants:

```javascript
// Default animations in SmartCommon
const animations = {
  slideRight: {
    initial: { x: "50%", opacity: 0 },
    animate: { x: 0, opacity: 1, transition: { duration: 0.15, ease: "easeInOut" } },
    exit: { x: "50%", opacity: 0, transition: { duration: 0.15, ease: "easeInOut" } }
  },
  slideLeft: {
    initial: { x: "-50%", opacity: 0 },
    animate: { x: 0, opacity: 1, transition: { duration: 0.15, ease: "easeInOut" } },
    exit: { x: "-50%", opacity: 0, transition: { duration: 0.15, ease: "easeInOut" } }
  },
  fade: {
    initial: { opacity: 0 },
    animate: { opacity: 1, transition: { duration: 0.15, ease: "easeOut" } },
    exit: { opacity: 0, transition: { duration: 0.15, ease: "easeOut" } }
  },
  zoom: {
    initial: { scale: 0.9, opacity: 0 },
    animate: { scale: 1, opacity: 1 },
    exit: { scale: 0.9, opacity: 0 },
    transition: { duration: 0.2, ease: "easeOut" }
  }
};
```

## useAnimation Hook

For custom animations in your components:

```javascript
import { useAnimation } from '@cap-rel/smartcommon';

const MyComponent = () => {
  const { start, animations, setAnimations } = useAnimation({
    fadeIn: { value: false, state: null },
    slideIn: { value: false, state: null }
  });

  useEffect(() => {
    if (start) {
      // Trigger animation after first render
      setAnimations(prev => ({
        ...prev,
        fadeIn: { ...prev.fadeIn, state: 'visible' }
      }));
    }
  }, [start]);

  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={animations.fadeIn.value ? { opacity: 1 } : {}}
    >
      Animated content
    </motion.div>
  );
};
```

## Animations with Framer Motion

For more complex animations, use Framer Motion directly:

```javascript
import { motion, AnimatePresence } from 'framer-motion';

const MyList = ({ items }) => (
  <AnimatePresence>
    {items.map(item => (
      <motion.div
        key={item.id}
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        exit={{ opacity: 0, y: -20 }}
        transition={{ duration: 0.2 }}
      >
        {item.name}
      </motion.div>
    ))}
  </AnimatePresence>
);
```

## Configuration Examples

### Classic Mobile Application

Hierarchical navigation (list -> detail -> sub-detail):

```javascript
pages: {
  "/": {
    "*": "slideLeft"
  },
  "/items": {
    "/": "slideRight",
    "/items/*": "slideLeft",
    "*": "fade"
  },
  "/items/*": {
    "/items": "slideRight",
    "*": "fade"
  },
  "*": "fade"
}
```

### Tab-based Application

Navigation between tabs without slide animations:

```javascript
pages: {
  "/home": { "*": "fade" },
  "/search": { "*": "fade" },
  "/profile": { "*": "fade" },
  "/settings": {
    "*": "slideLeft" // Only settings has a different animation
  },
  "*": "fade"
}
```

### Disable All Animations

```javascript
pages: {
  "*": "fade" // Use only fade (most subtle)
}

// Or set duration to 0
// (requires modifying animations in code)
```

## See Also
- [Configuration](/front/configuration) - Provider Configuration
- [SmartCommon](/front/smartcommon) - Page Component
- [Framer Motion](https://www.framer.com/motion/) - Official Documentation
