# Animations de pages

SmartCommon utilise Framer Motion pour animer les transitions entre pages. Les animations sont configurables par route.

## Configuration de base

Dans la configuration du Provider :

``` const config = {

pages: {
  "*": "fade" // Animation par défaut pour toutes les pages
}

}; ```

## Animations disponibles

Animation Description Effet
fade Fondu enchaîné Opacité 0 → 1
slideLeft Glissement gauche Entrée par la droite
slideRight Glissement droite Entrée par la gauche
zoom Effet de zoom Scale 0.9 → 1

## Configuration par route

Vous pouvez définir des animations différentes selon la route d'origine et de destination :

``` const config = {

pages: {
  // Depuis la page d'accueil
  "/": {
    "/dashboard": "slideLeft",  // Vers dashboard: glisse à gauche
    "/settings": "slideLeft",   // Vers settings: glisse à gauche
    "*": "fade"                 // Vers autres: fondu
  },
  // Depuis le dashboard
  "/dashboard": {
    "/": "slideRight",          // Retour accueil: glisse à droite
    "/details": "slideLeft",    // Vers détails: glisse à gauche
    "*": "fade"
  },
  // Depuis les paramètres
  "/settings": {
    "/": "slideRight",
    "*": "fade"
  },
  // Pour toutes les autres pages
  "*": "fade"
}

}; ```

## Logique de navigation

L'animation est choisie selon ce schéma :

1. Cherche une config pour la page actuelle 2. Si trouvée, cherche une animation pour la page précédente 3. Si pas trouvée, utilise * de la page actuelle 4. Si pas de config pour la page actuelle, utilise * global

### Exemple

Navigation de /dashboard vers / :

``` pages: {

"/": {
  "/dashboard": "slideRight", // <- Cette animation sera utilisée
  "*": "fade"
},
"/dashboard": {
  "/": "slideRight",
  "*": "fade"
}

} ```

La page / s'affiche avec slideRight car on vient de /dashboard.

## Désactiver les animations sur desktop

Par défaut, les animations de glissement sont remplacées par fade sur desktop pour une meilleure UX :

``` // Dans le composant Page (comportement interne) if (device?.type === “desktop”) {

return "fade";

} ```

## Utiliser le composant Page

Le composant Page gère automatiquement les animations :

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

const Dashboard = () ⇒ {

const location = useLocation();
return (
  <Page location={location}>
    <Block>
      Contenu du dashboard
    </Block>
  </Page>
);

}; ```

<note important>Le prop location est requis pour que les animations fonctionnent correctement.</note>

## Personnaliser les animations

Vous pouvez créer des animations personnalisées en modifiant les variants Framer Motion :

``` // Animations par défaut dans 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" }
}

}; ```

## Hook useAnimation

Pour des animations personnalisées dans vos composants :

``` 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) {
    // Déclencher l'animation après le premier rendu
    setAnimations(prev => ({
      ...prev,
      fadeIn: { ...prev.fadeIn, state: 'visible' }
    }));
  }
}, [start]);
return (
  <motion.div
    initial={{ opacity: 0 }}
    animate={animations.fadeIn.value ? { opacity: 1 } : {}}
  >
    Contenu animé
  </motion.div>
);

}; ```

## Animations avec Framer Motion

Pour des animations plus complexes, utilisez directement Framer Motion :

``` 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>

); ```

## Exemples de configurations

### Application mobile classique

Navigation hiérarchique (liste → détail → sous-détail) :

``` pages: {

"/": {
  "*": "slideLeft"
},
"/items": {
  "/": "slideRight",
  "/items/*": "slideLeft",
  "*": "fade"
},
"/items/*": {
  "/items": "slideRight",
  "*": "fade"
},
"*": "fade"

} ```

### Application avec onglets

Navigation entre onglets sans animation de glissement :

``` pages: {

"/home": { "*": "fade" },
"/search": { "*": "fade" },
"/profile": { "*": "fade" },
"/settings": {
  "*": "slideLeft" // Seul settings a une animation différente
},
"*": "fade"

} ```

### Désactiver toutes les animations

``` pages: {

"*": "fade" // Utiliser uniquement fade (le plus discret)

}

// Ou modifier la durée à 0 // (nécessite de modifier les animations dans le code) ```

## Voir aussi