dj-transition / dj-remove — declarative animations
Phoenix JS.transition parity. Apply a class for the duration of a state change. The framework handles the timing.
@action
dj-form-pending
@server_function
dj-transition
ActivityMixin
WizardMixin
dj_suspense
defer()
DataTableMixin
dj-virtual
dj-viewport
UploadMixin
Tasks
dj-transition-group Wire up the WebSocket consumer
Style the dashboard
Read the @action docs
The whole pattern
dj-transition-group="ENTER | LEAVE" wires dj-transition onto each new child and dj-remove onto every child for exit. The framework cycles classes and waits for transitionend automatically — no JS needed in your view.
{# pipe-separated short form: ENTER | LEAVE #}
<ul dj-transition-group="fade-in | fade-out">
{% for task in tasks %}
<li class="task">
{{ task.title }}
<button dj-click="remove" dj-value-id:int="{{ task.id }}">×</button>
</li>
{% endfor %}
</ul>
/* CSS — single-class transitionend-driven animations */
.fade-in { animation: t-fade-in 300ms ease both; }
.fade-out { opacity: 0; transition: opacity 300ms ease; }
Compare to React's <TransitionGroup> / <CSSTransition> from react-transition-group — three packages, build-time install, runtime overhead. Here it's an HTML attribute.