Skip to content

elixir-volt/phoenix_iconify

Repository files navigation

PhoenixIconify

Hex.pm Documentation

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:

  • Icons are discovered from HEEx at compile time
  • Only icons you use are fetched and stored
  • Rendering is plain inline SVG
  • SVG IDs are rewritten to avoid duplicate gradient/mask collisions
  • No browser-side icon loader
  • Works with LiveView diffs and phx-* attributes
  • Dynamic icons can be pre-registered in config

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.3.2"}
  ]
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" />

Use color for currentColor icon sets and inline when an icon should align with text:

<span>
  Saved <.icon name="lucide:check" color="green" inline />
</span>

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" />

PhoenixIconify follows Iconify's dimension behavior. Icons default to 1em high and preserve their aspect ratio. Set one dimension and the other is calculated from the viewBox:

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

Transformations and render modes

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 />

SVG mode is the default. CSS mask/background modes are available for Iconify-style CSS rendering:

<.icon name="lucide:settings" mode="mask" class="size-5" />
<.icon name="logos:elixir" mode="bg" class="size-5" />

SVG IDs are replaced automatically, so icons with gradients, masks, clip paths, or animation references can be rendered multiple times on the same page.

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:

  • :extra_icons - icons to include even when they are not found by static discovery
  • :fallback - icon to render when a requested icon is missing
  • :warn_on_missing - log missing icon warnings, enabled by default

Cache and manifest

PhoenixIconify stores:

  • priv/iconify/manifest.json - icons used by your app
  • priv/iconify/sets/*.json - cached icon sets

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.

Part of Elixir Volt

phoenix_iconify ships compile-time discovered, server-rendered Iconify SVGs for Phoenix — 200,000+ icons, zero client runtime.

It is part of a frontend stack that runs inside the BEAM — builds, JS runtimes, icons, and Vue-to-LiveView compilation as supervised parts of the application instead of external toolchain processes. See the Elixir Volt organization for the rest, and Building Blocks for the Future Web for the thesis, architecture, and roadmap that tie them together.

License

MIT

About

Phoenix components for compile-time discovered Iconify SVG icons

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages