Section 13.4.4 : Stimulus et animations
🎯 Objectif pédagogique
Maîtriser Stimulus, le framework JavaScript léger de Hotwire/Rails, et ajouter des animations CSS pour des interfaces fluides et réactives.
Stimulus : le JavaScript façon Rails
Stimulus est un framework JavaScript minimaliste créé par l'équipe Basecamp/Rails. Contrairement à React ou Vue qui prennent le contrôle de toute la page, Stimulus augmente le HTML existant avec du comportement JavaScript. C'est le compagnon idéal de Rails.
Les concepts Stimulus
Stimulus repose sur trois concepts : Controllers, Actions, et Targets.
<!-- HTML avec annotations Stimulus -->
<div data-controller="hello">
<input data-hello-target="name" type="text" placeholder="Votre nom">
<button data-action="click->hello#greet">Saluer</button>
<p data-hello-target="output"></p>
</div>
// controllers/hello_controller.js
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static targets = ['name', 'output']
greet() {
const name = this.nameTarget.value
this.outputTarget.textContent = `Bonjour, ${name} !`
}
}
Controller de toggle (show/hide)
<div data-controller="toggle">
<button data-action="click->toggle#toggle">Menu</button>
<div data-toggle-target="content" class="hidden">
<ul>
<li>Option 1</li>
<li>Option 2</li>
</ul>
</div>
</div>
// controllers/toggle_controller.js
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static targets = ['content']
toggle() {
this.contentTarget.classList.toggle('hidden')
}
}
Lifecycle callbacks
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
connect() {
// Appelé quand le controller est connecté au DOM
console.log('Controller connecté !')
}
disconnect() {
// Appelé quand l élément est retiré du DOM
console.log('Controller déconnecté')
}
}
Animations CSS
/* Transitions CSS */
.card {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}
/* Animations avec @keyframes */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Loader spinner */
@keyframes spin {
to { transform: rotate(360deg); }
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e2e8f0;
border-top-color: #7C3AED;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
Animations avec Stimulus
// controllers/animation_controller.js
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static targets = ['item']
connect() {
this.observer = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-fade-in')
}
})
},
{ threshold: 0.1 }
)
this.itemTargets.forEach(item => {
this.observer.observe(item)
})
}
disconnect() {
this.observer.disconnect()
}
}
Stimulus vs React vs Vue
← Scroll horizontally →
Que signifie data-action='click->toggle#toggle' en Stimulus ?
Apprendre l’IA, du premier prompt aux agents