Although Hotwire does not currently provide animations
out of the box, it does give us hooks to add in our own.
I will show you how to add some simple animations to an example Rails app using
Turbo Streams.
TL;DR
Turbo Streams allow us to hook into a turbo:before-stream-render event.
From here we can apply animation classes to elements that are just about
to be added, or just about to be removed.
With the above snippet we can define a data-stream-enter-class and/or a
data-stream-exit-class which will apply the classes we need. All of our
animations can then be handled with CSS, without the need for any further custom
JavaScript.
Let’s work through some examples.
This is what our dummy app looks like without animation:
Before - without animation
Example #1
Let’s first try to animate the cart panel on the right hand side.
When the first ticket is added, the cart will both fade in and slide in. And when
the last ticket is removed it will fade and slide out.
Our + and - buttons trigger cart_items#create and cart_items#destroy respectively.
As per the JavaScript snippet above, we specify the animation classes we need in the cart partial:
And define our CSS animation classes:
The result:
Cart sliding and fading in and out
Example #2
Next we are going to slide down any tickets that are added (unless it is the first), and slide up any that are removed (unless it is the last).
To the create response, we need to append the cart item if it is not the first ticket:
For reference, our cart_items container partial:
Similarly to the destroy response, we remove the cart item unless it is the last ticket:
We then specify the enter and exit animation classes in our cart item partial:
And define our animation CSS classes:
Which gives us:
Cart items sliding up and down
Example #3
Finally, let’s add an animation for flashing the total price. It will flash green if the total increases, and red if the total decreases.
In this example we only need an “enter” animation class. However, this class needs to change based on whether the total is increased or decreased.
We pass in a direction variable to the partial to handle this, which will be either “increase” or “decrease”:
And then use it to set our animation classes:
Flashing the total green and red
EDIT (Oct 2021) - A change to Turbo caused the snippet above to no longer work. It has now been updated. Thanks to chrism and coderifous for highlighting the fix.
Any questions or suggestions? Please feel free to get in touch -- ed@edforshaw.co.uk