Animating appearance, disappearance and layout shifts of elements in a DOM can be tricky. That's why many frameworks offer utilities to handle it for you. I offer you this standards-based web-component to use with any framework (or none)!
In this simple demo there is a list of numbers, with new numbers added at the bottom every 2 seconds. The list is capped to four numbers by removing the top one when new numbers are pushed on the bottom.
The code itself only manages the logic of updating and rendering the list. The animations are managed by the <transition-group>
tag, by applying classes specfied in the entry=
, exit=
and slide=
attributes.
view-component.jsx
import "webcomponent-transition-group"
export default ({strings}) => (
<ul class="toasts">
<transition-group
entry="slide"
exit="pop"
slide="slide"
>
{strings.map(str => (
<li class="toast" key={str}>
{str}
</li>
))}
</transition-group>
</ul>
)
transition-styles.css
.slide-pre {
transform: translateY(200%);
opacity: 0;
}
.pop {
transform: scale(2, 2);
opacity: 0;
}
.slide, .pop {
transition: 0.4s;
}
Only specify the transitions you need
If you don't provide a transition-directive in the css for a specified transition-class, there will be errors.
In this example, only the slide transition is needed, so that's all we provide.
view-component.jsx
import 'webcomponent-transition-group'
export default ({ordering, images, Move}) => (
<transition-group slide="slide" class="board">
{ordering.map(index => (
<img
src={images[index]}
class={{
blank: !index,
square: !!index
}}
onclick={[Move, index]}
/>
)}
</transition-group>
)
transition-styles.jsx
.slide { transition: 0.2s; }
.board {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}
Dynamic transitions
The transition classes to use are read at the moment each transition begins. That means you can change the classes to get different transitions.
Like in this example, where the transitions can go to the left or right depending on which control you click, and which slide is currently displayed
import 'webcomponent-transition-group';
export default ({slides, current, direction}) => (
<div class="screen">
<transition-group
entry={"slide-entry-" + direction}
exit={"slide-exit-" + direction}
>
<Slide key={"slide" + current}>
{slides[current]}
</Slide>
</transition-group>
</div>
)
.slide-entry-left-pre,
.slide-exit-right {
transform: translateX(-100%);
opacity: 0;
}
.slide-exit-left,
.slide-entry-right-pre {
transform: translateX(100%);
opacity: 0;
}
.slide-entry-left,
.slide-exit-left,
.slide-entry-right,
.slide-exit-right {
transition: 0.8s;
}
Like what you've seen? Feel like giving it a go yourself?
Bring the <transition-group>
tag in to your project, either
with a script tag in your html:
<script type="module" src="https://unpkg.com/webcomponent-transition-group"></script>
...or by npm install webcomponent-transition-group
and then
import "webcomponent-transition-group"
in every component that uses
the <transition-group>
tag
Check the code, report bugs and issues, at GitHub.