if Code.ensure_loaded?(Surface) do
defmodule Iconify.Icon do
@moduledoc """
A `Surface` component for rendering icons using various methods.
## Specifying what icon to use
- `iconify` or `icon`: Any icon from Iconify (https://icones.js.org)
- `solid`: Shorthand for Heroicons solid icons
- `outline`: Shorthand for Heroicons outline icons
## Extra Properties
- `svg`: Optionally pass SVG markup directly
- `mode`: Sets what rendering mode to use (see `Iconify` docs)
- `class`: Any CSS classes to apply to the icon
## Examples
iex> alias Iconify.Icon
iex> ~F"<#Icon iconify=\"heroicons-solid:user\" class=\"w-6 h-6\" />"
# Returns rendered icon HTML
iex> ~F"<#Icon solid=\"user\" class=\"w-6 h-6\" />"
iex> ~F"<#Icon svg=\"\" class=\"w-6 h-6\" />"
"""
use Surface.MacroComponent
# any icon from iconify: https://icones.js.org
prop(iconify, :string, required: false, static: true)
prop(icon, :string, required: false, static: true)
# shorthand for heroicons solid icons
prop(solid, :string, required: false, static: true)
# shorthand for heroicons outline icons
prop(outline, :string, required: false, static: true)
# pass SVG markup directly
prop(svg, :string, default: nil, required: false, static: true)
prop(mode, :atom, required: false, static: true)
prop(class, :css_class, default: nil)
@doc """
"""
def expand(attributes, _content, meta) do
static_props =
Surface.MacroComponent.eval_static_props!(__MODULE__, attributes, meta.caller)
svg = svg_icon(static_props)
icon = prepare_icon_name(static_props)
class =
Surface.AST.find_attribute_value(attributes, :class) ||
Application.get_env(:iconify_ex, :default_class, "w-4 h-4")
# TODO? simply include the phoenix component like so instead of duplicating logic, see https://github.com/surface-ui/surface/pull/685#issuecomment-1505978390
# quote_surface caller: meta.caller do
# ~F"""
#