1.0.7 • Published 2 years ago

react-crossfade-simple v1.0.7

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

react-crossfade-simple

React component to crossfade between two states with no additional CSS

This component provides a simple crossfade transition between two React component states.

There are plenty of animation libraries out there that can perform a "fade" transition between two React components. However, most of these libraries tend to only fade new content in rather than seamlessly fading between two states. To accomplish a true crossfade, you need to handle both states simultaneously which can be a pain to manage.

Although there are a few crossfade libraries out there, my inspiration for this was the Material UI transition components that work simply by supplying children and props to control the animation.

Features

  • ✅ The animation is fully managed by this component so no additional CSS is required.
  • ✅ Works with any React node, making it suitable for both whole page navigation or just a bit of text.
  • ✅ Transition state is managed using a simple contentKey prop.
  • ✅ Transition callback includes underlying DOM elements to allow for more advanced transitions.
  • ✅ Small & simple - does not require any additional animation libraries.

Installation

npm install --save react-crossfade-simple

Using the demo

  1. Checkout this repository

  2. Run the below command to start the server on port 3010.

npm run demo

Docs

Props

PropTypeDefaultDefinition
contentKeystringREQUIREDA string that triggers the crossfade transition when it changes
onTransition(from: HTMLElement, to: HTMLElement) => voidNoneCalled when the transition begins with the source and destination elements
timeoutnumber400How long to perform the transition for (in milliseconds)
styleReact.CSSProperties{}Additional CSS styles to apply to the transition container
childrenReact.ReactNodeREQUIREDThe React node that will transition when contentKey changes.

Detailed props

contentKey string

This prop controls the crossfade transition. When it changes, the content of the previous render will crossfade to the content of the current render. A transition will never occur if this value does not change. If you're using this for navigation, you might put some sort of page id here.

onTransition function

This callback function is emitted when a transition is about to occur. It is provided both the "from" and "to" underlying DOM elements as parameters. This can be used for instance to trigger additional transitions during the crossfade. The example below shows how you might animate a variable height header between two transition states.

const App = () => {
    const currentNavId = 'home';
    const headerHeight = 100; // this would change per page to animate

    return (
        <CrossFade
            contentKey={currentNavId}
            onTransition={(from, to) => {
                const fromHeader = from.querySelector<HTMLElement>('.header');
                const toHeader = to.querySelector<HTMLElement>('.header');

                // update header height on fade transition to begin 'slide' animation
                if (fromHeader) {
                    fromHeader.style.minHeight = headerHeight.toString() + 'px';
                    fromHeader.style.height = headerHeight.toString() + 'px';
                }
                if (toHeader) {
                    toHeader.style.minHeight = headerHeight.toString() + 'px';
                    toHeader.style.height = headerHeight.toString() + 'px';
                }
            }}
        >
            <div 
                className="header" 
                style={{
                    minHeight: headerHeight + 'px',
                    height: headerHeight + 'px',
                    transition: 'height .4s, min-height .4s',
                    backgroundColor: 'navy',
                }}
            >
                Header content here
            </div>
        </CrossFade>
    );
}

timeout number

The number of milliseconds to perform the transition for. Defaults to 400 milliseconds.

style React.CSSProperties

Additional CSS styles to apply to the transition container.

children React.ReactNode

The content to render. You can put any React node here though I would recommend keeping the height/width of the content consistent. See below under Known issues for more information.

Example

The following example transitions between two emojis every 3 seconds.

import React from 'react';
import { CrossFade } from "react-crossfade-simple";

const App = () => {
    const [swapped, setSwapped] = React.useState(false);

    React.useEffect(() => {
        const intervalId = setInterval(() =>
                setSwapped(swapped => !swapped),
            3000 // every 3 seconds
        );
        return () => clearTimeout(intervalId);
    }, []);

    return (
        <CrossFade contentKey={swapped.toString()} timeout={2000}>
            <p style={{ fontSize: '64px' }}>{swapped ? '😭' : '😀'}</p>
        </CrossFade>
    );
}

The result looks like the following:

react-crossfade-simple

Edit react-crossfade-simple example

Known issues 😭

  • Because the transition requires two component states to be visible at once, it is generally best if all children conform to the same height/width. Otherwise, the parent container will expand to fit the larger of the two component states, possibly leaving unnecessary space. Note, this is certainly solvable so PRs are welcomed!

  • Since opacity is used to perform the transition, you might notice a "fade out" effect when transitioning content with a higher contrast background. The example below has a white background behind the gray header which bleeds through during the transition. I'd recommend setting the background color of the parent container to minimize contrast with the transitioning content.

react-crossfade-simple

Note

Feel free to submit issues/PR's and I will do my best to respond. I'm sure there are plenty of improvements that can be made :-)

License

This project is licensed under the terms of the MIT license.

1.0.7

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago