Text Animation
Animated text effects for hero sections and landing pages. Gradient and shimmer are pure CSS. Word rotate and the typing effect use small JS hooks but render their full text server-side, so they still work without JavaScript and search engines see real text.
Gradient text
Text filled with a gradient that sweeps from end to end. Pure CSS, no hook required. Set the font size and weight with the class attr.
<.gradient_text class="text-4xl font-bold">Build Phoenix apps faster</.gradient_text>
Change the colors with color_from and color_to, and the sweep time with duration.
<.gradient_text color_from="#38bdf8" color_to="#818cf8" duration="4s" class="text-4xl font-bold">
From idea to production
</.gradient_text>
Shimmer text
Muted text with a band of light passing over it, the classic "✨ Introducing ..." pill treatment. Pure CSS. Control the speed with duration.
<div class="rounded-full border border-gray-200 px-5 py-2 dark:border-white/10">
<.shimmer_text class="text-lg font-medium">✨ Introducing Petal Components v4</.shimmer_text>
</div>
Word rotate
Cycles through a list of words with a smooth roll-up transition. Requires the PetalWordRotate hook from the petal_components JS bundle, and the id attr is required. The first word is rendered server-side, so there's no layout jump and crawlers see a complete sentence.
<div class="text-3xl font-bold">
Petal makes your app
<.word_rotate
id="word-rotate-example"
words={["beautiful.", "fast.", "accessible."]}
class="text-primary-600"
/>
</div>
Typing effect
Types text out character by character with a blinking caret. Requires the PetalTypingEffect hook from the petal_components JS bundle, and the id attr is required. The full text is rendered server-side and replayed on mount, so it reads fine without JavaScript and stays visible to search engines. Set loop to delete and retype forever.
<.typing_effect
id="typing-effect-example"
text="shadcn for Phoenix"
loop
class="font-mono text-lg"
/>
Properties
| Attribute | Type | Default | Description |
|---|---|---|---|
class
|
any |
nil
|
extra classes (set font size/weight here) |
color_from
|
string |
"#ffaa40"
|
start color of the gradient |
color_to
|
string |
"#9c40ff"
|
end color of the gradient |
duration
|
string |
"8s"
|
time for one full gradient sweep |
rest
|
global |
||
:inner_block
slot
|
slot |
| Attribute | Type | Default | Description |
|---|---|---|---|
class
|
any |
nil
|
extra classes (set font size/weight here) |
duration
|
string |
"2.5s"
|
time for one full shimmer pass |
rest
|
global |
||
:inner_block
slot
|
slot |
| Attribute | Type | Default | Description |
|---|---|---|---|
class
|
any |
nil
|
extra classes (set font size/weight here) |
cursor
|
boolean |
true
|
show a blinking caret |
id*
|
string |
||
loop
|
boolean |
false
|
delete the text and type it again, forever |
rest
|
global |
||
speed
|
integer |
60
|
milliseconds per character |
start_delay
|
integer |
0
|
milliseconds to wait before typing starts |
text*
|
string |
the text to type out |
| Attribute | Type | Default | Description |
|---|---|---|---|
class
|
any |
nil
|
extra classes (set font size/weight here) |
id*
|
string |
||
interval
|
integer |
2500
|
milliseconds each word stays on screen |
rest
|
global |
||
words*
|
list |
the words to cycle through |