react-dip
Version:
Simple & declarative transition animations for React
281 lines (194 loc) โข 10.5 kB
Markdown
# react-dip
**Simple & declarative** transition animations for [React](https://facebook.github.io/react).
## DISCLAIMER
**THIS IS EARLY WORK IN PROGRESS AND NOT "RELEASED TO PUBLIC" YET, THOUGH THIS SHOULD HAPPEN ANYTIME SOON.**
**FEEL FREE TO WATCH ๐, STAR โญ OR CONTACT ME TO BE NOTIFIED ABOUT PROGRESS**.
_TODO: Video / gif here_
[](https://www.npmjs.com/package/react-dip)
[](https://unpkg.com/react-dip/dist/)
[](https://unpkg.com/react-dip/dist/)
[](https://greenkeeper.io/)
<a href="https://codeclimate.com/github/mdugue/react-dip/maintainability"><img src="https://api.codeclimate.com/v1/badges/2392b912933a753b4b5b/maintainability" /></a>
[](https://www.codefactor.io/repository/github/mdugue/react-dip)
[](https://bettercodehub.com/)
[](https://snyk.io/test/github/mdugue/react-dip)
[](https://travis-ci.org/mdugue/react-dip)
## Why?
Ever wanted to implement one of those incredible designs you find on [dribble](http://dribbble.com/) or [Muzli](https://muz.li/) where one element beautifully transforms into another upon page transition? And then realized _"But I want my code to stay statefull, decoupled, scalable, declarative"_, so you ended up with regular "hard cuts" instead? โ **To me this happend very very often!**
`react-dip` solves this by providing animated transisions in an effortless way, that _just works<sup>TM</sup>_, by using the [FLIP technique](https://aerotwist.com/blog/flip-your-animations/#the-general-approach).
## Table of contents
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
* [Installation](#installation)
* [Quick Start](#quick-start)
* [Props](#props)
* [dipId](#dipid)
* [children](#children)
* [render](#render)
* [duration](#duration)
* [easing](#easing)
* [element](#element)
* [optInCssStyles](#optincssstyles)
* [className, id, style, aria-..., role, etc.](#classname-id-style-aria--role-etc)
* [Polyfill](#polyfill)
* [Examples](#examples)
* [Dip-WHAT???](#dip-what)
* [How it works (TODO)](#how-it-works-todo)
* [Browser Compatiblity](#browser-compatiblity)
* [Caveats (TODO)](#caveats-todo)
* [Inspired by](#inspired-by)
* [Huge Thanks to](#huge-thanks-to)
* [TODOs](#todos)
* [To be done before anouncing](#to-be-done-before-anouncing)
* [For some near future milestone](#for-some-near-future-milestone)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Installation
Using [yarn](https://yarnpkg.com) or [npm](https://www.npmjs.com/):
```bash
$ yarn add react-dip
# or using npm
$ npm install --save react-dip
```
Using a module bundler like [webpack](webpack.js.org) or [parcel](https://parceljs.org/), import your depency just as any other:
```javascript
// Using ES6 modules
import Dip from 'react-dip'
// or using CommonJS modules
var Dip = require('react-dip')
```
UMD builds are also available via [unpkg](https://unpkg.com):
```javascript
<script src="https://unpkg.com/react-dip/dist/react-dip.umd.min.js" />
```
## Quick Start
The API is as small as possible, almost everything is optional, so you see results immediately. Just wrap your Items in a `Dip`
```jsx
import React, {Component} from 'react'
import Dip from 'react-dip'
function Component1() {
return (
<Dip dipId="quickStart" style={{background: 'red'}}>
some content
</Dip>
)
}
function Component2() {
return (
<Dip
dipId="quickStart"
style={{position: 'absolute', top: '100px', background: 'green'}}
>
some other content <br />
etc...
</Dip>
)
}
// use complex state here
// or a routing solution such as react-router
// or connect it to redux, or ustated
export default class MyStatefulParent extends Component {
state = {currentStep: 0}
toggleState = () =>
this.setState(state => ({
currentStep: (state.currentStep + 1) % 2,
}))
render() {
return (
<section>
<h1> Quick Start example </h1>
<button onClick={this.toggleState}>toggle me</button>
{this.state.currentStep === 0 ? <Component1 /> : <Component2 />}
</section>
)
}
}
```
_Note: Using `inline styles` as well as `absolute` positioning is usually not considered a good way and is applied here for the sake of simplicity.
You can use any type `CSS` or `CSS-in-JS` styling and `fluid` / `flex` / `grid` layout._
[](https://codesandbox.io/s/20jlowo9rp)
## Props
The API surface is intetended to be as simple as possible. Only `dipId` and `children` (or `render`) are required props. The rest is optional and helps you fine tuning your animations.
### dipId
> `string` | **Required!**
The `id` that groups two different dip elements. React-dip will only create animated transitions between to Elements with the same `dipId`, consider them as potential _from_- and _to_-hints.
### children
> `React Element` | **Required unless using `render`-prop!**
Content that is rendered as part of that `Dip`.
### render
> `function({ref: function(), styles: {}})` | **Required unless using `children`-prop!**
Function that should return the content that is rendered as part of that `Dip`. Allows for more advanced pattern and skips the wrapping Element. See [render prop](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce) for further details.
**Warning:** `<Dip render>` takes precedence over `<Dip children>` so donโt use both in the same `<Dip />`.
### duration
> `number` | _**optional**_, defaults to `200`
Time in milliseconds the animation will take when transitioning _to_ this dip.
### easing
> `string` | _**optional**_, defaults to `"ease-out"`
Specifies the desired timing function. Accepts the pre-defined values `linear`, `ease`, `ease-in`, `ease-out`, and `ease-in-out`, or a custom `cubic-bezier` value like `cubic-bezier(0.42, 0, 0.58, 1)`.
### element
> `string` | _**optional**_, defaults to `"div"`
Specify the desired HTML-tag here (eg. `<Dip element="li">`) in case you don't want your children wrapped in a `div`.
### optInCssStyles
> `Array(string)` | _**optional**_, defaults to an empty `array`
By default `react-dip` will morph your components _only_ regarding their sizes and positions using `css transforms` which is usually a good default regarding performance.
In case you want to morph more css properties you can specify them here, such as `optInCssStyles={["borderRadius", "backgroundColor"]}`. _**optional**_
### className, id, style, aria-..., role, etc.
> default `react` / `HTML attributes` | _**optional**_
Any provided standard attribute is passed to the child-container.
## Polyfill
As some browsers do not support the [Web Animations API](https://caniuse.com/#feat=web-animation), we recommend using the [web-animations-js Polyfill](https://github.com/web-animations/web-animations-js).
1. Install the dependency
```bash
$ yarn add web-animations-js
# or using npm
$ npm install --save web-animations-js
```
2. include the dependency into your project.
```javascript
import('web-animations-js') // We recommend dynamic imports to keep initial bundlesize small
```
## Examples
* [Quick Start Example](https://codesandbox.io/s/20jlowo9rp)
* [Styled Components, render Props & beautiful images](https://codesandbox.io/s/l5qlnjo1v7)
* [With React Router and Material-UI](https://codesandbox.io/s/mmnn5k0nx8)
## Dip-WHAT???
No _DEEEE-EYE-PEEE_, just **dip** your taco into some tasty salsa. ๐ฎ
## How it works (TODO)
* Dip-Communication, dipId, from & to
* FLIP
## Browser Compatiblity
| Chrome | Firefox | Safari | Edge | IE | iOS |
| ------ | ------- | --------------- | --------------- | --------------- | --------------- |
| โ
| โ
| โ
<sup>\*</sup> | โ
<sup>\*</sup> | โ
<sup>\*</sup> | โ
<sup>\*</sup> |
<sup>\*</sup> [(requires polyfill)](#polyfill)
## Caveats (TODO)
* Block-Elements h1 etc
* nested Elements
* transitioning to elements in scrolled lists (via browser back)
* text can get distorted
* styles from nested queries eg: animating `h1` which is styled via `section h1` (might be fixable _a little bit_, not sure if it is worth though, as it is somehow considered bad practices anyhow?)
## Inspired by
* https://github.com/joshwcomeau/react-flip-move
## Huge Thanks to
* [Kent C. Dodds](https://github.com/kentcdodds/) for his inspiring work, such as [kcd-scripts](https://github.com/kentcdodds/kcd-scripts)
* [Ives van Horne](https://github.com/compuives) amongst other for [CodeSandbox](codesandbox.io)
## TODOs
There are tons of ideas for improving `react-dip` such as adding fine grained control to your transitions, but the primary goal will stay to keep the API as symple as possible.
### To be done before anouncing
* [x] add chapter about polyfilling
* [x] render props (of course)
* [x] add support for custom timing functions
* [ ] add complex examples with renderProps, routing etc.
* [ ] add possibility of declaring alternative components that are shown whilst animating
* [ ] export types for flow and typescript
* [ ] add contributing guide lines
* [x] add error handling for props
* [ ] add error handling for refs
* [x] move animation to proper element, allowing for parents with `overflow: hidden` and avoiding z-index issues
### For some near future milestone
* [ ] add support for staggering
* [ ] add real tests
* [ ] export types for flowtyped and typescript
* [ ] add optional `placeholder` component that is shown whilst animating
* [ ] add documentation, (maybe even abstractions) for image transitions from low-res to high-res
* [ ] make animation-layer custmizable, so regular items _can_ be in front of them (`z`-wise)
* [ ] investigate possible optimizations for the scrolling issues