react-flip-toolkit

repository·master·Indexed 26 days ago

https://github.com/aholachek/react-flip-toolkit

A high-performance React library for FLIP (First, Last, Invert, Play) animations. It enables animations of position, scale, and opacity using the Flipper and Flipped components, featuring spring-based stagger effects and tools to prevent child warping during scale transforms. Includes a spring utility for non-FLIP animations and global configuration functions to enable or disable animations across the application.

Tokens
6K
Snippets
12
Records
35
Agent score
87%

What's inside react-flip-toolkit

  1. Prevent child warping with inverseFlipId

    master

    When animating the scale of a parent element, children can appear warped. To prevent this, wrap the child in a Flipped component and provide an inverseFlipId matching the parent's flipId.

    To limit the adjustment specifically to scale (allowing position to follow the parent), add the scale prop to the inverted Flipped component.

    Note: The element with the inverse transform should lie flush against its parent container. Apply layout styles (padding, flexbox, etc.) to the inverted container rather than the parent Flipped container.

    <Flipped flipId={id}>
      <div>
        <Flipped inverseFlipId={id} scale>
          <div>some text that will not be warped</div>
        </Flipped>
      </div>
    </Flipped>
  2. Quick start with Flipper and Flipped

    master

    To perform animations, follow these two steps:

    1. Wrap all animated children with a single Flipper component. Provide a flipKey prop that changes whenever you want animations to trigger.
    2. Wrap the individual elements that should be animated with Flipped components. Each must have a flipId prop that remains consistent across renders to identify the element.
  3. Use react-flip-toolkit with React Router

    master

    To provide route-driven transitions, wrap your routes in a Flipper and use a flipKey that combines the current location.pathname and location.search.

    <Route
      render={({ location, search }) => {
        return (
          <Flipper
            flipKey={`${location.pathname}-${location.search}`}
          >
          {/* Child routes that contain Flipped components go here... */}
          </Flipper>
        )
      }}
    />
  4. Optimize animation performance

    master

    For complex animations involving many elements or large images, use these strategies to maintain performance:

    Memoization

    To prevent React reconciliation delays when an animation is triggered, memoize your animated elements using React.memo or PureComponent. This minimizes unnecessary prop updates to animated children.

    CSS will-change

    You can hint to the browser that an element's transform will change using the will-change property. Use this cautiously as it increases resource usage.

    .box {
      will-change: transform;
    }
  5. Wrap React components with Flipped

    master

    To wrap a custom React component, use the render prop pattern to pass flippedProps to your component, or ensure your component spreads unrecognized props onto its underlying DOM element.

    // Option 1: Render Prop
    <Flipped>
      {flippedProps => <MyCoolComponent flippedProps={flippedProps} />}
    </Flipped>
    
    const MyCoolComponent = ({ flippedProps }) => <div {...flippedProps} />
    
    // Option 2: Spreading props (works for styled components)
    <Flipped>
      <MyCoolComponent />
    </Flipped>
    
    const MyCoolComponent = ({ knownProp, ...rest }) => <div {...rest} />
  6. Troubleshoot animations not triggering

    master

    If animations are not occurring, check the following:

    1. Update flipKey: Ensure you are updating the flipKey attribute on the Flipper component whenever an animation should be triggered.
    2. DOM Element vs React Component: If a Flipped component wraps a React component instead of a raw DOM element, you must use a render prop to pass the Flipped props down to the underlying DOM element.
    3. Visibility: react-flip-toolkit optimizes performance by skipping elements that are off-screen or have no width/height. Ensure the element is visible in the DOM.
    4. Display Property: display:inline elements cannot be animated. Change them to display:inline-block.
    5. Reduced Motion: As of v7.1.0, the browser's prefers-reduced-motion setting will automatically disable all animations.
  7. Troubleshoot unexpected animation behavior

    master

    If animations look incorrect or behave strangely, check these common causes:

    1. Unique flipIds: Ensure every flipId is unique. There must never be more than one element with the same flipId on the page at any time.
    2. Target Element: Ensure you are animating the intended element and not a wrapper. For example, animating a div around text might result in unexpected widths. Use inline-block on the target if necessary.
    3. CSS Conflicts: Check for competing CSS transitions on the element being animated.
    4. Image Dimensions: If animating images, provide hard-coded dimensions to ensure the browser has measured the dimensions before the animation starts.
  8. Animate an expanding div

    master

    To animate a single element changing size or position (e.g., expanding to full screen), use a Flipper with a flipKey that tracks the state of the expansion, and a Flipped component with a constant flipId.

    import React, { useState } from 'react'
    import { Flipper, Flipped } from 'react-flip-toolkit'
    
    const AnimatedSquare = () => {
      const [fullScreen, setFullScreen] = useState(false)
      const toggleFullScreen = () => setFullScreen(prevState => !prevState)
    
      return (
        <Flipper flipKey={fullScreen}>
          <Flipped flipId="square">
            <div
              className={fullScreen ? 'full-screen-square' : 'square'}
              onClick={toggleFullScreen}
            />
          </Flipped>
        </Flipper>
      )
    }
  9. Configure staggerConfig in Flipper

    master

    Use staggerConfig to define different staggering behaviors for different groups of elements within a Flipper.

    staggerConfig={{
      // the "default" config will apply to staggered elements without explicit keys
          default: {
            // default direction is forwards
            reverse: true,
            // default is .1, 0 < n < 1
            speed: .5
          },
      // this will apply to Flipped elements with the prop stagger='namedStagger'
        namedStagger : { speed: .2 }
      }}
  10. Animate list shuffles

    master

    To animate items moving within a list (like a shuffle), wrap the list container in a Flipper using a flipKey derived from the list data (e.g., data.join('')). Wrap each list item in a Flipped component using the item's unique ID as the flipId.

    import React, { useState } from 'react'
    import { Flipper, Flipped } from 'react-flip-toolkit'
    import shuffle from 'lodash.shuffle'
    
    const ListShuffler = () => {
      const [data, setData] = useState([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
      const shuffleList = () => setData(shuffle(data))
    
      return (
        <Flipper flipKey={data.join('')}>
          <button onClick={shuffleList}> shuffle</button>
          <ul className="list">
            {data.map(d => (
              <Flipped key={d} flipId={d}>
                <li>{d}</li>
              </Flipped>
            ))}
          </ul>
        </Flipper>
      )
    }
  11. Customize spring animations in Flipper

    master

    Animations in react-flip-toolkit use springs. You can customize the animation behavior by passing a preset name or a custom configuration object to the spring prop on the Flipper component.

    Presets: "stiff", "noWobble", "gentle", "veryGentle", or "wobbly".