JSPM

  • Created
  • Published
  • Downloads 59879
  • Score
    100M100P100Q171808F
  • License MIT

Effortless animation between DOM changes (eg. list reordering) using the FLIP technique.

Package Exports

  • react-flip-move

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-flip-move) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

React Flip Move

build status npm version

Animations library for React that automagically handles animations when a DOM element gets reordered or moved.

< Insert GIF of what I'm talking about >

The implementation couldn't be simpler. Just wrap the items you'd like to move in a FlipMove:

class TopArticles extends Component {
  renderTopArticles() {
    return this.props.articles.map( (article, i) => {
      return <Article {...article} key={i} />;
    });
  }
  render() {
    return (
      <div className="top-articles">
        <FlipMove transition="300" easing="ease-in-out">
          { this.renderTopArticles() }
        </FlipMove>
      </div>
    );
  }
}

Installation

TODO

Examples

TODO

Credit

This library was heavily inspired by Ryan Florence's MagicMove, with a few key differences:

  • Works with React 0.14+, and will be maintained.
  • Uses transform CSS properties for 60+ FPS animations, instead of expensive positioning properties like top/left/right/bottom. Read why this matters.
  • Much simpler implementation, does not create any additional DOM nodes.
  • Uses the Web Animations API under the hood
  • More configurable.

How It Works

FLIP technique

The general approach was adapted from the FLIP technique. FLIP stands for First, Last, Invert, and Play.

To understand, let's take a simplified example: Two items in a list that trade places. Here's the HTML output after React renders based on its props:

Note: I'm inlining CSS in these examples purely for illustrative purposes. This isn't how the code actually works =)

First
<ul id="article-titles">
  <li id="article-one" style="height: 100px;">List Item 1</li>
  <li id="article-two" style="height: 100px;">List Item 2</li>
</ul>

Before the animation has happened, List Item 1 is at 0px from the top. List item 2 is at 100px from the top, because it's underneath an item that is 100px tall. These values are our first position.

Last

Our articles change places. This could be the result of React sending new props, with our articles in a different order.

<ul id="article-titles">
  <li id="article-two" style="height: 100px;">List Item 2</li>
  <li id="article-one" style="height: 100px;">List Item 1</li>
</ul>

So now, List Item 1 is 100px from the top, and List Item 2 is 0px from the top. These values are our last position.

Invert

Now, the fun bit. We want to take the difference in their positions, so that they APPEAR to not have moved. In order for that to happen:

  • List Item 1 needs to be artificially raised by 100px.
  • List Item 2 needs to be artificially lowered by 100px.
<ul id="article-titles">
  <li id="article-two" style="height: 100px; transform: translateY(100px)">
    List Item 2
  </li>
  <li id="article-one" style="height: 100px; transform: translateY(-100px)">
    List Item 1
  </li>
</ul>

Do you see what that does? Even though their position in the DOM has changed, the user would see these two items in their original position: with List Item 1 on top of List Item 2. This is our invert stage.

Note: this transform is NOT animated. It happens instantly, and as far as the user is concerned, nothing has happened yet. The two list items are just sitting there, in their original positions.

Play

Finally, we play them. This involves animating both elements to have a transform: translateY of 0px:

<ul id="article-titles">
  <li id="article-two" style="height: 100px; transform: translateY(0px); transition: 500ms">
    List Item 2
  </li>
  <li id="article-one" style="height: 100px; transform: translateY(0px); transition: 500ms">
    List Item 1
  </li>
</ul>

The user sees List Item 1 drop by 100px over half a second, as List Item 2 raises over the same interval. The two appear to slide into their new positions.

Implementing FLIP and React.

The original FLIP technique by Google's Paul Lewis is made to transition an element between two CSS classes. In our case, we don't have two CSS classes, but we have two moments in the component lifecycle that will work.

TODO: Finish this thought.

API

TODO

Planned functionality

I don't have many plans for this module aside from maintenance. The one feature I feel like it's missing is the ability for changes in size/opacity to be animated (eg. list items become increasingly transparent the further down the list you go).

Got other ideas? Open an issue =) Happy to explore possibilities.

Contributions

Contributors welcome! Please discuss new features with me ahead of time, and submit PRs for bug fixes with tests.

License

MIT