This project is only compatible with hyperapp v1, and I do not intend to maintain it any longer. Hence, I am archiving it.
Hyperapp Transitions lets you animate your Hyperapp components as they are appear, dissapear and move around on the page. Use it to provide your user with important cues and a smoother experience.
- CSS Based — Anything you can
transition
with CSS can be animated, including background-color, opacity, position and scale. - Animate Layouts — Reorder nodes in a list or flexbox-layout, and watch them gracefully slide into place
- Composable — Stack multiple transitions with different delay and duration for complex animation effects.
Simply wrap your component in one of the decorator components exported from Hyperapp Transitions:
import {Enter} from "@hyperapp/transitions"
const Notification = ({key, message}) => (
<Enter css={{opacity: "0", transform: "translateX(100%)"}}>
<div key={key} class="notification">
{message}
</div>
</Enter>
)
Use it as you would any component. The difference is, now your newly added Notifications
will not just suddenly appear, but rather fade and slide in from the right.
Install with npm or Yarn.
npm i @hyperapp/transitions
Then with a module bundler like Rollup or Webpack, use as you would anything else.
import {Enter, Exit, Move} from "@hyperapp/transitions"
If you don't want to set up a build environment, you can download Hyperapp Transitions from a CDN like unpkg.com and it will be globally available through the window.transitions object.
<script src="https://unpkg.com/@hyperapp/transitions"></script>
Hyperapp Transitions exports three components: Enter
, Exit
and Move
described below. Each take a number of attributes for defining the animation.
The components are decorator-components (a.k.a "higher-order components"), which means that they do not add anything to the virtual DOM tree, but rather modify and return their children.
Use the Enter component to make elements appear in an animated fashion, when they are added to the DOM.
The Enter component takes the following attributes:
The css overrides the element should have before it begins to appear. This can also be a function, allowing you to defer the decision until right before the animation starts.
Default: {}
The duration of the transition in milliseconds.
Default: 300
.
A string with the timing function of the transition.
Default: "linear"
.
Wait this amount of milliseconds before starting the transition.
Default: 0
.
//make messages pop and fade in:
<Enter time={200} easing="ease-in-out" css={{
opacity: "0",
transform: "scale(0.1, 0.1)",
}}>
<p class="message">some message</p>
</Enter>
Use the Exit component to animate out elements before they are removed from the DOM.
The Exit component takes the following attributes:
The css overrides the element should have after it has left. This can also be a function, allowing you to defer the decision until right before the animation starts.
Default: {}
The duration of the transition in milliseconds.
Default: 300
.
A string with the timing function of the transition.
Default: "linear"
Wait this amount of milliseconds before beginning the transition.
Default: 0
.
When composing multiple Exit-transition components, set this to true
on all but the last one, in order to prevent previous ones from removing the element when complete.
Default: false
.
//make messages slide and fade out, and change backgroundcolor
<Exit time={200} easing="ease-in-out" css={{
transform: "translateY(-100%)",
opacity: "0",
}}>
<p class="message">some message</p>
</Exit>
When the order of sibling nodes (items in a list, for example) changes, their elements are laid out in new positions on the page. When the sibling nodes are wrapped with the Move
transition-component, they will glide smoothly to their new positions.
Remember to key the nodes you wish to apply the Move
transition to, so that the vdom engine is able to detct that it is the order that has changed, and not just all the attributes.
The Move
component takes the following attributes:
The duration of the transition in milliseconds.
Default: 300
.
A string with the timing function of the transition.
Default: "linear"
.
<ul class="todo-list">
<Move time={200} easing="ease-in-out">
{state.todos.map(todo => (
<li class="todo-item" key={todo.id}>
...
</li>
))}
</Move>
</ul>
The transition components work by adding handlers for the oncreate
, onremove
and/or onupdate
lifecycle events to their children. If a child already has a handler for those lifecycle events, it is not overwritten. Rather, we compose the transition-handlers with existing lifecycle event handlers.
This makes it possible to compose multiple transition components on top of eachother.
const FadeInPopOut = (props, children) => (
<Enter css={{opacity: "0"}}>
<Exit css={{opacity: "0", transform: "scale(2.0,2.0)"}}>
{children}
</Exit>
</Enter>
)
As a general rule: make sure to have keys on all nodes you apply transitions to.
The lifecycle events which trigger the transitions, are based on elements - not virtual nodes. Without keys, Hyperapp's virtual DOM engine will often associate the a nodes with an unintended element in the real DOM, with unexpected transition-behavior as a consequence.
Please have a look at these live, editable examples, for some ideas of what is possible:
- Toasts - Combining Enter, Exit and Move transitions for an elegant notification display.
- 15-puzzle - Slide squares around a grid using the Move transition
- Carousel - A situation you'll need deferred css for the Exit transition.
Do you have questions? Or think you've found a bug? Please file an issue att https://github.com/hyperapp/transitions
Or come join the us on the Hyperapp Slack!
Hyperapp Transitions is MIT licensed. See LICENSE.