animateClassTo(element, oldClass, newClass) swaps CSS classes on an
element and returns a promise that resolves when the resulting CSS
animation finishes — or immediately, if none runs. Part of
pota/use/animate; for part tokens use
animatePartTo.
| Argument | Type | Description |
|---|---|---|
element |
Element |
The element whose classes to swap |
oldClass |
string |
The class to remove |
newClass |
string |
The class to add |
Returns: a Promise that resolves once the triggered animation
ends, or immediately if element.getAnimations() reports none.
requestAnimationFrame so the class change
is observed by the next paint.oldClass and adds newClass.element.getAnimations() reports at least one running
animation, waits for animationend on that element; otherwise
resolves immediately — so it's safe to await even when the swap
triggers no animation at all.Note that getAnimations() also reports CSS transitions, but a
transition fires transitionend, not animationend — so a swap whose
only effect is a transition leaves the promise unresolved. Pair it
with @keyframes animations.
Chains class swaps, awaiting each animation before triggering the next
— the final swap declares no animation, so its await resolves
immediately.
import { ref, render, signal } from 'pota'
import { animateClassTo } from 'pota/use/animate'
function App() {
const box = ref()
const state = signal('idle')
const toggle = async () => {
if (state.read() !== 'idle') return
state.write('out')
await animateClassTo(box(), 'idle', 'out')
state.write('back')
await animateClassTo(box(), 'out', 'back')
state.write('idle')
// `.idle` runs no animation — this resolves immediately
await animateClassTo(box(), 'back', 'idle')
}
return (
<>
<style>{`
.idle { background: #2a9d8f; }
.out { background: #e76f51; animation: slide .4s forwards; }
.back { background: #f4a261; animation: slide-back .4s forwards; }
@keyframes slide { to { transform: translateX(120px); } }
@keyframes slide-back {
from { transform: translateX(120px); }
to { transform: translateX(0); }
}
`}</style>
<button on:click={toggle}>animate</button>
<div
use:ref={box}
class="idle"
style={{
width: '120px',
padding: '1rem',
color: 'white',
'margin-top': '1rem',
}}
>
state: {state.read}
</div>
</>
)
}
render(App)