mix phia.icons (phia_ui v0.1.5)

Copy Markdown View Source

Generates the Lucide SVG sprite used by PhiaUi.Components.Icon.

PhiaUI's <.icon> component renders icons by referencing symbols inside an inline SVG sprite. This task reads individual SVG files from the lucide-static npm package and combines them into a single sprite file at priv/static/icons/lucide-sprite.svg.

The sprite uses <symbol> elements with id="icon-{name}" so that icons can be rendered with <use href="#icon-chevron-down" /> without any extra HTTP requests.

Prerequisites

Install the lucide-static package in your assets/ directory:

cd assets && npm install lucide-static

Usage

mix phia.icons

Run this command from the root of your Phoenix project. The generated sprite is written to priv/static/icons/lucide-sprite.svg by default.

Options

--source PATH   Directory containing Lucide SVG source files.
                Defaults to `assets/node_modules/lucide-static/icons`.

--output PATH   Destination path for the generated sprite file.
                Defaults to `priv/static/icons/lucide-sprite.svg`.

--help          Print this help message.

Examples

# Default: read from node_modules, write to priv/static/icons/
$ mix phia.icons

# Custom source and output paths
$ mix phia.icons --source assets/node_modules/lucide-static/icons \
                 --output priv/static/icons/lucide-sprite.svg

Included icons

The following icons are always included when present in the source directory. These are the icons used internally by PhiaUI components:

menu, chevron-down, chevron-right, check, x, plus, search, pencil,
trash-2, upload-cloud, image, bold, italic, underline, heading, list,
list-ordered, quote, code-2, link, trending-up, trending-down, minus,
eye, eye-off, calendar, tag, loader-circle

Missing icon files are skipped with a warning rather than failing the task, so a partial icon set is still functional.

Sprite format

The generated file is a hidden SVG container (style="display:none") with each icon wrapped in a <symbol> element:

<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
  <symbol id="icon-check" viewBox="0 0 24 24" fill="none"
          stroke="currentColor" stroke-width="2"
          stroke-linecap="round" stroke-linejoin="round">
    <polyline points="20 6 9 12 4 9"/>
  </symbol>
  ...
</svg>

Include the sprite once in your root layout (e.g., root.html.heex) before any icon references, or serve it as a static asset and reference it with an external href.

Summary

Functions

Generates the SVG sprite from source_dir and writes it to output_path.

Functions

generate(source_dir, output_path)

@spec generate(Path.t(), Path.t()) :: :ok

Generates the SVG sprite from source_dir and writes it to output_path.

Iterates over each icon name in @minimum_icons, reads the corresponding .svg file from source_dir, strips the outer <svg> wrapper, and wraps the inner elements in a <symbol> with a namespaced id="icon-{name}".

All symbols are combined into a single hidden SVG container and written to output_path. Intermediate directories are created if they do not exist.

Missing icon files produce a yellow warning and are skipped — the task does not fail for partial icon sets.

Example

iex> Mix.Tasks.Phia.Icons.generate(
...>   "assets/node_modules/lucide-static/icons",
...>   "priv/static/icons/lucide-sprite.svg"
...> )
:ok