We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
Animate any HEEx element with a single attribute. Sem CSS manual, sem JavaScript, sem dependências externas.
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 →
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
Três passos para animar qualquer elemento no HEEx
defp deps do
[
{:enguia, "~> 0.1"}
]
end
import EnguiaHook
from "../../deps/enguia/
priv/static/enguia.js"
new LiveSocket("/live", Socket, {
hooks: { EnguiaHook }
})
use Enguia
<.motion
animate={slide_up(
trigger: :visible)}>
<p>Slides up!</p>
</.motion>
Projetado para o lifecycle do LiveView, desde o início
Um atributo animate={…}
substitui dezenas de classes Tailwind e CSS customizado.
animate={slide_up()} vs "animate-slide-up delay-150 ease-out duration-700 ..."
Nada de IntersectionObserver,
addEventListener,
ou lógica de animação à mão.
Usa a Web Animations API nativa do browser internamente
Zero dependências de runtime. Nada de framer-motion, GSAP, ou Alpine.js.
Apenas CSS + Web Animations API — nativos e universais
Funciona perfeitamente com patches do LiveView, streams, live components e navegação com patch.
Sem conflitos com o DOM diffing do morphdom
11 motion presets + 4 text effects — clique em ▶ para ver
| Preset | Demo |
|---|---|
fade_in
|
|
fade_out
|
|
slide_up
|
|
slide_down
|
|
slide_left
|
|
slide_right
|
|
scale_in
|
|
scale_out
|
|
shake
|
|
pulse
|
|
bounce
|
|
typewriter
|
— |
split_words
|
— |
blur_in
|
— |
letter_spacing_in
|
— |
Cada animação é um struct Elixir simples. Você pode compor, extender, e passar como prop para qualquer componente Phoenix.
duration,
delay,
easing,
repeat
attr :animation, Enguia.Animation
em qualquer componente com type checking nativo
%Enguia.Animation{} diretamente
<.motion animate={slide_up(
duration: 800,
delay: 200,
easing: "cubic-bezier(0.34, 1.56, 0.64, 1)")}>
<div>Spring-like motion!</div>
</.motion>
# 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>
%Enguia.Animation{
keyframes: [
%{"opacity" => 0, "transform" => "scale(0.9)"},
%{"opacity" => 1, "transform" => "scale(1)"}
],
duration: 500,
easing: "ease-out",
trigger: :visible
}