PhoenixIconify

Hex.pmDocumentation

Inline Iconify SVGs for Phoenix and LiveView. Write a normal Phoenix component, let the compiler discover the icons you use, and ship only those icons with your app.

<.icon name="lucide:settings" class="size-5" />

PhoenixIconify gives Phoenix apps access to 200,000+ icons from 150+ icon sets without a client-side icon runtime. Browse icons at icon-sets.iconify.design.

Why PhoenixIconify

Most Iconify integrations load icons in JavaScript. PhoenixIconify keeps icons on the server:

It pairs naturally with Tailwind and Volt-powered Phoenix projects:

<button class="inline-flex items-center gap-2">
<.icon name="lucide:settings" class="size-4" />
Settings
</button>

Installation

Add the dependency:

def deps do
[
{:phoenix_iconify, "~> 0.1.0"}
]
end

Add the compiler:

def project do
[
compilers: Mix.compilers() ++ [:phoenix_iconify]
]
end

Import the component in your web module:

# lib/my_app_web.ex
defp html_helpers do
quote do
import PhoenixIconify, only: [icon: 1]
end
end

Now use icons in HEEx:

<.icon name="lucide:settings" class="size-5" />

Usage

Use Iconify's standard prefix:name format:

<.icon name="lucide:home" class="size-5" />
<.icon name="mdi:account" class="size-6 text-blue-600" />
<.icon name="heroicons:check" class="size-4" />

Phoenix-style Heroicons names are supported too:

<.icon name="hero-user" class="size-6" />
<.icon name="hero-sun-mini" class="size-5" />
<.icon name="hero-sun-micro" class="size-4" />

Global attributes are forwarded to the SVG, including phx-*, data-*, and aria-*:

<.icon name="lucide:x" class="size-4" phx-click="close" data-testid="close" />

Accessibility

Icons are decorative by default and render with aria-hidden="true":

<.icon name="lucide:settings" class="size-5" />

For meaningful icons, provide label or title:

<.icon name="lucide:settings" label="Settings" />
<.icon name="lucide:settings" title="Settings" />

Sizing

Use Tailwind's size-* utilities when possible:

<.icon name="lucide:settings" class="size-5" />

Or set SVG dimensions directly:

<.icon name="lucide:settings" size="20" />
<.icon name="lucide:settings" width="1em" height="1em" />

Transformations

Iconify aliases can include transformations, and you can transform at render time:

<.icon name="lucide:arrow-right" rotate={1} />
<.icon name="lucide:arrow-right" flip="horizontal" />
<.icon name="lucide:arrow-right" h_flip />
<.icon name="lucide:arrow-right" v_flip />

How it works

  1. You write <.icon name="lucide:settings" />
  2. The :phoenix_iconify compiler scans HEEx and ~H sigils
  3. Literal icon names are collected
  4. Missing icons are fetched through Iconify
  5. A JSON manifest is written to priv/iconify/manifest.json
  6. At runtime, the component reads icons from the manifest and renders inline SVG

There is no client-side icon runtime and no JavaScript bundle impact.

Dynamic icons

Compile-time discovery only works for literal names. If an icon name comes from assigns, a database, or user configuration, register the possible values:

# config/config.exs
config :phoenix_iconify,
extra_icons: [
"lucide:check",
"lucide:x",
"lucide:alert-triangle"
]

Then dynamic usage works at runtime:

<.icon name={@status_icon} class="size-4" />

Configuration

config :phoenix_iconify,
extra_icons: ["lucide:check", "lucide:x"],
fallback: "lucide:circle-help",
warn_on_missing: true

Options:

Cache and manifest

PhoenixIconify stores:

Useful tasks:

mix phoenix_iconify.prefetch # scan and fetch discovered icons
mix phoenix_iconify.audit # report discovered icons missing from the manifest
mix phoenix_iconify.clean # remove manifest icons no longer used
mix phoenix_iconify.list # list manifest icons
mix phoenix_iconify.stats # show manifest and cache stats

Cache tasks:

mix phoenix_iconify.cache fetch
mix phoenix_iconify.cache list
mix phoenix_iconify.cache clear

Volt projects

For projects created with Volt, PhoenixIconify is the server-rendered option:

<.icon name="lucide:settings" class="size-5" />

It does not use Volt's JavaScript pipeline. If you want client-side icon components instead, use the official npm packages (iconify-icon, @iconify/react, @iconify/vue, etc.) through Volt's normal package handling.

License

MIT