181 lines
4.7 KiB
Elixir
181 lines
4.7 KiB
Elixir
defmodule Liliform.Icon do
|
|
@moduledoc """
|
|
Bulma icon element.
|
|
|
|
The icon element is a container for any type of icon font.
|
|
Because the icons can take a few seconds to load,
|
|
and because you want control over the space
|
|
the icons will take, you can use the icon class
|
|
as a reliable square container that will prevent
|
|
the page to "jump" on page load.
|
|
|
|
By default, the icon container will take up
|
|
exactly 1.5rem x 1.5rem.
|
|
|
|
The icon itself is sized accordingly to the icon library you're using.
|
|
For example, Font Awesome 5 icons will inherit the font size.
|
|
"""
|
|
use Liliform.Component
|
|
alias Liliform.Colorhash
|
|
alias Freedive.Features
|
|
|
|
@doc """
|
|
Renders an icon.
|
|
|
|
## For
|
|
|
|
The icon name is set using the `for` attribute.
|
|
|
|
## Color
|
|
|
|
Set color to `auto` to automatically choose/generate color
|
|
based on the icon name.
|
|
|
|
You can also set the color to any valid CSS color value.
|
|
|
|
## Size
|
|
|
|
The icon size can be set using the `size` attribute.
|
|
By default, the size is set to `1.5rem`.
|
|
|
|
Example:
|
|
|
|
<.icon for="home" />
|
|
|
|
<.icon for="info" color="auto" />
|
|
<.icon for="alert" color="#f44" />
|
|
<.icon for="settings" color="blue" />
|
|
<.icon for="error" color="hsl(0, 100%, 50%)" />
|
|
|
|
<.icon for="info" size="2rem" />
|
|
"""
|
|
attr :for, :string, required: true, doc: "icon name"
|
|
attr :title, :string, default: nil, doc: "icon title"
|
|
attr :size, :string, default: nil, doc: "size of icon"
|
|
attr :color, :string, default: nil, doc: "color of icon"
|
|
attr :class, :string, default: "", doc: "additional classes"
|
|
attr :rest, :global
|
|
|
|
slot :inner_block, required: false
|
|
|
|
def icon(assigns) do
|
|
assigns =
|
|
assigns
|
|
|> set_bulma_classes()
|
|
|
|
assigns =
|
|
if assigns.size != nil do
|
|
Map.put(assigns, :style, "width: #{assigns.size}; height: #{assigns.size};")
|
|
else
|
|
assigns
|
|
end
|
|
|
|
~H"""
|
|
<span class="icon-text">
|
|
<span class={["icon", @class]} {@rest}>
|
|
<.icon_svg
|
|
for={@for}
|
|
title={@title}
|
|
height={@size}
|
|
width={@size}
|
|
{icon_color(assigns)}
|
|
{@rest}
|
|
/>
|
|
</span>
|
|
<%= if @inner_block != [] do %>
|
|
<span>
|
|
<%= render_slot(@inner_block) %>
|
|
</span>
|
|
<% end %>
|
|
</span>
|
|
"""
|
|
end
|
|
|
|
@doc """
|
|
Renders an icon without the icon-text wrapper.
|
|
"""
|
|
attr :for, :string, required: true, doc: "icon name"
|
|
attr :title, :string, default: nil, doc: "icon title"
|
|
attr :size, :string, default: nil, doc: "size of icon"
|
|
attr :color, :string, default: nil, doc: "color of icon"
|
|
attr :rest, :global
|
|
|
|
def icon_raw(assigns) do
|
|
assigns =
|
|
assigns
|
|
|> set_bulma_classes()
|
|
|
|
~H"""
|
|
<.icon_svg for={@for} title={@title} height={@size} width={@size} {icon_color(assigns)} {@rest} />
|
|
"""
|
|
end
|
|
|
|
defp icon_svg(assigns) do
|
|
base_assigns =
|
|
assigns
|
|
|> Map.reject(fn {k, _} -> k in [:for, :size, :rest] end)
|
|
|> Map.reject(fn {k, v} -> k in [:color] and v == "" end)
|
|
|
|
apply(Lucideicons, icon_name(assigns), [base_assigns])
|
|
end
|
|
|
|
defp icon_color(assigns) do
|
|
if Features.enabled?(:colorhash) do
|
|
case assigns.color do
|
|
nil ->
|
|
[]
|
|
|
|
clr ->
|
|
case String.downcase(clr) do
|
|
"auto" ->
|
|
case String.downcase(assigns.for) do
|
|
"alert" -> [class: "has-text-danger"]
|
|
"info" -> [class: "has-text-info"]
|
|
"success" -> [class: "has-text-success"]
|
|
"warning" -> [class: "has-text-warning"]
|
|
"error" -> [class: "has-text-danger"]
|
|
"all" -> [color: "magenta"]
|
|
"compute" -> [color: "blue"]
|
|
"storage" -> [color: "green"]
|
|
"network" -> [color: "orange"]
|
|
"system" -> [color: "purple"]
|
|
"account" -> [color: "darkblue"]
|
|
"running" -> [color: "lime"]
|
|
"stopped" -> [color: "gray"]
|
|
"enabled" -> [color: "blue"]
|
|
"disabled" -> [color: "gray"]
|
|
_ -> [color: Colorhash.hsl(assigns.for)]
|
|
end
|
|
|
|
_ ->
|
|
[color: assigns.color]
|
|
end
|
|
end
|
|
else
|
|
[class: "has-text-dark"]
|
|
end
|
|
end
|
|
|
|
defp icon_name(assigns) do
|
|
name =
|
|
assigns.for
|
|
|> String.trim()
|
|
|> String.downcase()
|
|
|> String.replace("-", "_")
|
|
|
|
case name do
|
|
"alert" -> :triangle_alert
|
|
"compute" -> :binary
|
|
"storage" -> :hard_drive
|
|
"network" -> :earth
|
|
"system" -> :bot
|
|
"account" -> :user
|
|
"all" -> :infinity
|
|
"running" -> :circle_play
|
|
"stopped" -> :circle_stop
|
|
"enabled" -> :circle_check
|
|
"disabled" -> :circle_x
|
|
lucide_name -> String.to_atom(lucide_name)
|
|
end
|
|
end
|
|
end
|