CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-transition-group

A react component toolset for managing animations

Pending
Overview
Eval results
Files

switch-transition.mddocs/

Switch Transitions

The SwitchTransition component controls transitions between two states with different sequencing modes, inspired by Vue.js transition modes. It's ideal for switching between different components or states with controlled timing.

Capabilities

SwitchTransition Component

Controls the render timing between state transitions with configurable sequencing modes.

/**
 * Controls transitions between two states with different sequencing modes
 * @param props - SwitchTransition props
 * @returns JSX element managing component switching transitions
 */
function SwitchTransition({
  mode,
  children
}): JSX.Element;

interface SwitchTransitionProps {
  /** 
   * Transition mode controlling sequence timing
   * 'out-in': Current element exits first, then new element enters
   * 'in-out': New element enters first, then current element exits
   */
  mode?: 'out-in' | 'in-out';
  /** Single Transition or CSSTransition component */
  children: React.ReactElement;
}

Mode Constants

Pre-defined mode constants for transition sequencing.

/** Mode constants for SwitchTransition */
export const modes = {
  /** Current element transitions out first, then new element transitions in */
  out: 'out-in',
  /** New element transitions in first, then current element transitions out */
  in: 'in-out'
};

Usage Examples:

import React, { useState } from 'react';
import { SwitchTransition, CSSTransition } from 'react-transition-group';
import './switch.css';

function SwitchExample() {
  const [state, setState] = useState(false);
  
  return (
    <SwitchTransition mode="out-in">
      <CSSTransition
        key={state ? "goodbye" : "hello"}
        addEndListener={(node, done) => {
          node.addEventListener("transitionend", done, false);
        }}
        classNames='fade'
      >
        <button onClick={() => setState(state => !state)}>
          {state ? "Goodbye, world!" : "Hello, world!"}
        </button>
      </CSSTransition>
    </SwitchTransition>
  );
}

// Image carousel with smooth transitions
function ImageCarousel() {
  const [currentImage, setCurrentImage] = useState(0);
  const images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
  
  return (
    <div className="carousel">
      <SwitchTransition mode="out-in">
        <CSSTransition
          key={currentImage}
          timeout={300}
          classNames="slide"
        >
          <img 
            src={images[currentImage]} 
            alt={`Slide ${currentImage + 1}`}
            className="carousel-image"
          />
        </CSSTransition>
      </SwitchTransition>
      
      <button 
        onClick={() => setCurrentImage((currentImage + 1) % images.length)}
      >
        Next
      </button>
    </div>
  );
}

Transition Modes

Out-In Mode ('out-in'):

  • Current element starts exiting
  • Waits for exit to complete
  • New element starts entering
  • Prevents overlapping content during transition

In-Out Mode ('in-out'):

  • New element starts entering immediately
  • Current and new elements exist simultaneously
  • Current element starts exiting after new element enters
  • Allows for crossfade effects and overlapping animations
function ModeComparison() {
  const [content, setContent] = useState('first');
  const [mode, setMode] = useState('out-in');
  
  return (
    <div>
      <div>
        <label>
          <input 
            type="radio" 
            checked={mode === 'out-in'}
            onChange={() => setMode('out-in')}
          />
          Out-In (sequential)
        </label>
        <label>
          <input 
            type="radio" 
            checked={mode === 'in-out'}
            onChange={() => setMode('in-out')}
          />
          In-Out (overlapping)
        </label>
      </div>
      
      <SwitchTransition mode={mode}>
        <CSSTransition
          key={content}
          timeout={500}
          classNames="switch"
        >
          <div className="content-box">
            {content === 'first' ? 'First Content' : 'Second Content'}
          </div>
        </CSSTransition>
      </SwitchTransition>
      
      <button onClick={() => setContent(content === 'first' ? 'second' : 'first')}>
        Switch Content
      </button>
    </div>
  );
}

Route Transitions

SwitchTransition works well for page/route transitions:

import { useLocation } from 'react-router-dom';

function RouteTransition({ children }) {
  const location = useLocation();
  
  return (
    <SwitchTransition mode="out-in">
      <CSSTransition
        key={location.pathname}
        timeout={300}
        classNames="page"
      >
        <div className="page-container">
          {children}
        </div>
      </CSSTransition>
    </SwitchTransition>
  );
}

// Usage with router
function App() {
  return (
    <Router>
      <RouteTransition>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/contact" element={<Contact />} />
        </Routes>
      </RouteTransition>
    </Router>
  );
}

Key-Based Switching

SwitchTransition uses the key prop to determine when to switch:

// ✅ Correct - key changes trigger transitions
<SwitchTransition>
  <CSSTransition
    key={currentState} // Key changes when state changes
    timeout={200}
    classNames="switch"
  >
    <div>{currentState}</div>
  </CSSTransition>
</SwitchTransition>

// ❌ Incorrect - static key won't trigger transitions
<SwitchTransition>
  <CSSTransition
    key="static" // Key never changes
    timeout={200}
    classNames="switch"
  >
    <div>{currentState}</div>
  </CSSTransition>
</SwitchTransition>

Example CSS for Switch Transitions

/* Fade transition for out-in mode */
.fade-enter {
  opacity: 0;
}

.fade-enter-active {
  opacity: 1;
  transition: opacity 300ms ease-in-out;
}

.fade-exit {
  opacity: 1;
}

.fade-exit-active {
  opacity: 0;
  transition: opacity 300ms ease-in-out;
}

/* Slide transition for route changes */
.page-enter {
  transform: translateX(100%);
}

.page-enter-active {
  transform: translateX(0);
  transition: transform 300ms ease-out;
}

.page-exit {
  transform: translateX(0);
}

.page-exit-active {
  transform: translateX(-100%);
  transition: transform 300ms ease-in;
}

/* Scale transition for in-out mode */
.scale-enter {
  transform: scale(0.8);
  opacity: 0;
}

.scale-enter-active {
  transform: scale(1);
  opacity: 1;
  transition: all 400ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.scale-exit {
  transform: scale(1);
  opacity: 1;
}

.scale-exit-active {
  transform: scale(1.1);
  opacity: 0;
  transition: all 300ms ease-in;
}

Lifecycle Callback Integration

SwitchTransition preserves and calls lifecycle callbacks from child components:

function CallbackExample() {
  const [key, setKey] = useState('a');
  
  return (
    <SwitchTransition>
      <CSSTransition
        key={key}
        timeout={300}
        classNames="switch"
        onEnter={() => console.log('Entering:', key)}
        onExit={() => console.log('Exiting:', key)}
      >
        <div>Content {key}</div>
      </CSSTransition>
    </SwitchTransition>
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-react-transition-group

docs

css-transition.md

index.md

replace-transition.md

switch-transition.md

transition-group.md

transition.md

tile.json