Icon library for Phoenix LiveView that scans your templates at compile time, downloads only the icons you actually use, and inlines the SVGs as compiled function clauses. Zero runtime overhead, no unused icons bundled, no Node.js required.
def deps do
[{:phx_icons, "~> 0.1.0"}]
endAdd use PhxIcons to your component module:
defmodule MyAppWeb.CoreComponents do
use Phoenix.Component
use PhxIcons
endUse icons in your templates:
<.icon name="heroicons:heart" class="size-6 text-red-500" />
<.icon name="lucide:search" class="size-4" />
<.icon name="flagpack:at" class="size-8" />That's it. The icons are discovered, downloaded, and compiled automatically.
use PhxIconsscans all.heexand.exfiles forname="provider:icon"references at compile time- Missing icons are downloaded from the provider's GitHub release archive (ZIP
files are cached in
/tmp/icons/) - Each icon becomes a pattern-matched function clause with the SVG inlined
__mix_recompile__?/0triggers recompilation when new icon references appear
Configure providers in config/config.exs:
config :phx_icons,
providers: %{
"heroicons" => {PhxIcons.Providers.Heroicons, "2.2.0"},
"heroicons-solid" => {PhxIcons.Providers.Heroicons, "2.2.0", style: "solid"},
"heroicons-mini" => {PhxIcons.Providers.Heroicons, "2.2.0", style: "mini"},
"heroicons-micro" => {PhxIcons.Providers.Heroicons, "2.2.0", style: "micro"},
"lucide" => {PhxIcons.Providers.Lucide, "0.469.0"},
"tabler" => {PhxIcons.Providers.Tabler, "3.41.1"},
"phosphor" => {PhxIcons.Providers.Phosphor, "2.0.8"},
"simple-icons" => {PhxIcons.Providers.SimpleIcons, "16.16.0"},
"flagpack" => {PhxIcons.Providers.Flagpack, "2.1.0"},
"lineicons" => {PhxIcons.Providers.Lineicons, "5.0"}
}You can also pre-download all icons from a provider or a specific list:
config :phx_icons,
providers: %{
# Download all icons upfront
"heroicons" => {PhxIcons.Providers.Heroicons, "2.2.0", download: :all},
# Download a specific set
"lucide" => {PhxIcons.Providers.Lucide, "0.469.0", download: ~w(search check x)}
}| Provider | Prefix | Variants |
|---|---|---|
| Heroicons | heroicons |
outline (default), -solid, -mini, -micro |
| Lucide | lucide |
single style |
| Tabler | tabler |
outline (default), -filled |
| Phosphor | phosphor |
regular (default), -bold, -thin, -light, -fill, -duotone |
| Simple Icons | simple-icons |
brand logos |
| Flagpack | flagpack |
country flags |
| Lineicons | lineicons |
single style |
<.icon name="heroicons:heart" class="size-6" />
<.icon name="heroicons-solid:heart" class="size-6" />
<.icon name="heroicons-mini:heart" class="size-5" />
<.icon name="tabler:star" class="size-6" />
<.icon name="tabler-filled:star" class="size-6" />
<.icon name="phosphor:bell" class="size-6" />
<.icon name="phosphor:bell-duotone" class="size-6" />
<.icon name="simple-icons:github" class="size-6 fill-current" />
<.icon name="flagpack:us" class="h-6 w-auto" />
<.icon name="lineicons:github" class="size-6" />Implement the PhxIcons.Provider behaviour:
defmodule MyApp.Providers.CustomIcons do
@behaviour PhxIcons.Provider
@impl true
def release_url(version) do
"https://github.com/org/repo/archive/refs/tags/v#{version}.zip"
end
@impl true
def svg_path(version, icon_name, _opts) do
"repo-#{version}/icons/#{icon_name}.svg"
end
endThen register it in your config:
config :phx_icons,
providers: %{
"custom" => {MyApp.Providers.CustomIcons, "1.0.0"}
}PhxIcons ships with test helpers to assert icons are rendered:
import PhxIcons.Test
html = render_component(&MyAppWeb.CoreComponents.icon/1, name: "heroicons:heart")
assert_icon(html, "heroicons:heart")
refute_icon(html, "heroicons:x-mark")MIT — see LICENSE.