Packages
petal_components
4.7.0
4.7.0
4.6.2
4.6.1
4.6.0
4.5.0
4.4.0
4.3.0
4.2.1
4.2.0
4.1.2
4.1.1
4.1.0
4.0.12
4.0.11
4.0.10
4.0.6
4.0.5
4.0.4
4.0.3
4.0.1
3.2.2
3.2.1
3.2.0
3.1.0
3.0.2
3.0.1
3.0.0
2.9.3
2.9.2
retired
2.9.1
retired
2.9.0
retired
2.8.4
2.8.3
2.8.2
2.8.1
2.8.0
2.7.4
2.7.3
2.7.2
2.7.1
2.7.0
2.6.1
2.6.0
2.5.2
2.5.1
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.0
2.2.1
2.2.0
2.1.2
2.1.1
2.1.0
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.9.3
1.9.2
1.9.1
1.9.0
1.8.0
1.7.1
1.7.0
1.6.2
1.6.1
1.6.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.14
1.2.13
1.2.12
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.19.10
0.19.9
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.7
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.15.0
0.14.1
0.14.0
0.13.7
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.8
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.2
0.2.1
0.2.0
0.1.0
Shadcn-style Phoenix LiveView components that AI assistants can actually use. Pair with the MCP server so AI coding tools can inspect the real component API.
Current section
Files
Jump to
Current section
Files
lib/petal_components/aurora.ex
defmodule PetalComponents.Aurora do
use Phoenix.Component
alias PetalComponents.Helpers
@default_colors ["#3b82f6", "#a5b4fc", "#93c5fd", "#ddd6fe", "#60a5fa"]
@doc """
A soft animated aurora glow behind your content - the hero-section
backdrop. Pure CSS (blurred repeating gradients blended over a stripe
texture); the optional `PetalAurora` hook pauses the animation while the
section is off-screen.
The wrapper sizes to its content, so a padded hero just works:
<.aurora class="rounded-2xl">
<div class="px-8 py-24 text-center">
<h1>Ship your SaaS this weekend</h1>
<.button label="Get started" />
</div>
</.aurora>
Pass any palette and the gradient is built for you:
<.aurora colors={["#f97316", "#f43f5e", "#fbbf24"]}>...</.aurora>
By default the effect auto-adapts: inverted on light backgrounds,
un-inverted in dark mode (`invert="always"` / `invert="none"` to force).
Respects `prefers-reduced-motion` (the drift freezes, the glow stays).
"""
attr :id, :string, doc: "defaults to a generated id (needed by the pause-offscreen hook)"
attr :colors, :list,
default: @default_colors,
doc: "3-6 CSS colors; the aurora gradient is built from them in order"
attr :invert, :string,
default: "auto",
values: ["auto", "none", "always"],
doc: "auto inverts on light and not in dark; none/always force one look"
attr :speed, :string, default: "60s", doc: "duration of one drift cycle"
attr :opacity, :string, default: "0.5", doc: "strength of the glow"
attr :blur, :string, default: "10px", doc: "softness of the glow"
attr :mask_position, :string,
default: "100% 0",
doc: "where the glow concentrates (radial mask origin), e.g. \"50% 0\" for top-centre"
attr :mask_coverage, :string,
default: "10%, 70%",
doc: "inner/outer stops of the radial mask - widen to flood more of the container"
attr :class, :any, default: nil, doc: "CSS class"
attr :rest, :global
slot :inner_block
def aurora(assigns) do
assigns =
assigns
|> assign_new(:id, fn -> Helpers.uniq_id("pc-aurora") end)
|> assign(:style, build_style(assigns))
~H"""
<div
id={@id}
class={[
"pc-aurora",
@invert == "always" && "pc-aurora--invert",
@invert == "none" && "pc-aurora--no-invert",
@class
]}
style={@style}
phx-hook="PetalAurora"
{@rest}
>
<div class="pc-aurora__backdrop" aria-hidden="true">
<div class="pc-aurora__lights" data-pc-aurora></div>
</div>
<div class="pc-aurora__content">
{render_slot(@inner_block)}
</div>
</div>
"""
end
defp build_style(assigns) do
[
"--pc-aurora-gradient: #{gradient(assigns.colors)};",
"--pc-aurora-speed: #{assigns.speed};",
"--pc-aurora-opacity: #{assigns.opacity};",
"--pc-aurora-blur: #{assigns.blur};",
"--pc-aurora-mask-position: #{assigns.mask_position};",
"--pc-aurora-mask-coverage: #{assigns.mask_coverage};"
]
|> Enum.join(" ")
end
# ["#a", "#b", "#c"] -> repeating-linear-gradient(100deg, #a 10%, #b 15%, #c 20%)
defp gradient(colors) do
stops =
colors
|> Enum.with_index()
|> Enum.map_join(", ", fn {color, i} -> "#{color} #{10 + i * 5}%" end)
"repeating-linear-gradient(100deg, #{stops})"
end
end