v0.1 · hex.pm/packages/enguia MIT License

Declarative
animations for
Phoenix LiveView

Animate any HEEx element with a single attribute. Sem CSS manual, sem JavaScript, sem dependências externas.

home_live.html.heex
use Enguia

# Anima no mount
<.motion animate={slide_up()}>
  <h1>Hello, world!</h1>
</.motion>

# Anima no hover
<.motion animate={fade_in(trigger: :hover)}>
  <button>Hover me</button>
</.motion>

# Efeito de texto
<.motion animate={typewriter()} tag="p">
  Hello, LiveView!
</.motion>

Preview →

Hello, world! slide_up · mount
Hover me fade_in · hover
Hello, LiveView! typewriter

Live demos interativas

Clique em ▶ Replay para ver cada animação ao vivo

fade_in
fade_out
slide_up
slide_down
slide_left
slide_right
scale_in
scale_out
shake
pulse
bounce

Como funciona

Três passos para animar qualquer elemento no HEEx

1

Instala a dep

mix.exs
defp deps do
  [
    {:enguia, "~> 0.1"}
  ]
end
2

Registra o hook

assets/js/app.js
import EnguiaHook
from "../../deps/enguia/
priv/static/enguia.js"

new LiveSocket("/live", Socket, {
hooks: { EnguiaHook }
})
3

Usa <.motion> no HEEx

home_live.html.heex
use Enguia

<.motion
animate={slide_up(
trigger: :visible)}>
<p>Slides up!</p>
</.motion>

Por que Enguia?

Projetado para o lifecycle do LiveView, desde o início

🚫

Sem classes CSS gigantes

Um atributo animate={…} substitui dezenas de classes Tailwind e CSS customizado.

animate={slide_up()} vs "animate-slide-up delay-150 ease-out duration-700 ..."
🚫

Sem JavaScript manual

Nada de IntersectionObserver, addEventListener, ou lógica de animação à mão.

Usa a Web Animations API nativa do browser internamente
🚫

Sem dependências externas

Zero dependências de runtime. Nada de framer-motion, GSAP, ou Alpine.js.

Apenas CSS + Web Animations API — nativos e universais
♻️

LiveView lifecycle nativo

Funciona perfeitamente com patches do LiveView, streams, live components e navegação com patch.

Sem conflitos com o DOM diffing do morphdom

Todos os presets

11 motion presets + 4 text effects — clique em ▶ para ver

Motion Presets
Preset Demo
fade_in
fade_out
slide_up
slide_down
slide_left
slide_right
scale_in
scale_out
shake
pulse
bounce
Text Effects
typewriter
split_words
blur_in
letter_spacing_in

Customização total

Cada animação é um struct Elixir simples. Você pode compor, extender, e passar como prop para qualquer componente Phoenix.

  • Override qualquer parâmetro: duration, delay, easing, repeat
  • Declare como attr :animation, Enguia.Animation em qualquer componente com type checking nativo
  • Crie presets customizados construindo o struct %Enguia.Animation{} diretamente
Override com keyword list
<.motion animate={slide_up(
  duration: 800,
  delay: 200,
  easing: "cubic-bezier(0.34, 1.56, 0.64, 1)")}>
  <div>Spring-like motion!</div>
</.motion>
Passe como attr de componente
# Declara o attr no componente
attr :animation, Enguia.Animation,
default: nil

# Usa no template HEEx
<.motion animate={@animation || slide_up()}>
<div class="card">...</div>
</.motion>
Struct direto para animações custom
%Enguia.Animation{
keyframes: [
%{"opacity" => 0, "transform" => "scale(0.9)"},
%{"opacity" => 1, "transform" => "scale(1)"}
],
duration: 500,
easing: "ease-out",
trigger: :visible
}