refactor: store icons as .svg.heex files

This commit is contained in:
Ivan R. 2024-07-28 17:52:11 +05:00
parent a38d13a16a
commit 8040c38edf
Signed by: lumin
GPG key ID: E0937DC7CD6D3817
12 changed files with 108 additions and 186 deletions

View file

@ -41,13 +41,13 @@ defmodule ComfycampWeb.Flash do
{@rest}
>
<p :if={@title} class="flash-title">
<.icon :if={@kind == :error} name="hero-exclamation-circle" />
<.icon :if={@kind == :info} name="hero-information-circle" />
<.exclamation_circle_icon :if={@kind == :error} />
<.information_circle_icon :if={@kind == :info} />
<%= @title %>
</p>
<p class="flash-body"><%= msg %></p>
<button type="button" class="flash-close-button" aria-label={gettext("close")}>
<.icon name="hero-x-mark" class="flash-close-button-icon" />
<.x_mark_icon class="flash-close-button-icon" />
</button>
</div>
"""

View file

@ -1,191 +1,17 @@
defmodule ComfycampWeb.Icons do
@moduledoc """
Provides reusable svg icons.
I would like to store icons as .svg files,
but I dont want to write a custom loader.
When trying to use the img element, we lose the ability to inherit color.
For now, I find this approach tolerable.
"""
use Phoenix.Component
@doc """
Icon component.
embed_templates "icons/*"
The default icon is face-frown from heroicons.
## Examples
<.icon name="hero-x-mark" />
<.icon name="si-mastodon" class="custom-class" />
"""
attr :name, :string, required: true
attr :name, :string, default: nil
attr :class, :string, default: nil
def icon(%{name: "hero-exclamation-circle"} = assigns) do
~H"""
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class={["icon", @class]}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
"""
end
def icon(%{name: "hero-information-circle"} = assigns) do
~H"""
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class={["icon", @class]}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"
/>
</svg>
"""
end
def icon(%{name: "hero-x-mark"} = assigns) do
~H"""
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class={["icon", @class]}
>
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
"""
end
def icon(%{name: "hero-code-bracket"} = assigns) do
~H"""
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class={["icon", @class]}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5"
/>
</svg>
"""
end
def icon(%{name: "hero-envelope"} = assigns) do
~H"""
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class={["icon", @class]}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"
/>
</svg>
"""
end
def icon(%{name: "si-mastodon"} = assigns) do
~H"""
<svg
role="img"
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
class={["icon", @class]}
>
<path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z" />
</svg>
"""
end
def icon(%{name: "si-xmpp"} = assigns) do
~H"""
<svg
role="img"
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
class={["icon", @class]}
>
<path d="m3.401 4.594 1.025.366 3.08.912c-.01.18-.016.361-.016.543 0 3.353 1.693 7.444 4.51 10.387 2.817-2.943 4.51-7.034 4.51-10.387 0-.182-.006-.363-.016-.543l3.08-.912 1.025-.366L24 3.276C23.854 8.978 19.146 14.9 13.502 18.17c1.302 1.028 2.778 1.81 4.388 2.215v.114l.004.001v.224a14.55 14.55 0 0 1-4.829-1.281A20.909 20.909 0 0 1 12 18.966c-.353.17-.708.329-1.065.477a14.55 14.55 0 0 1-4.829 1.281V20.5l.004-.001v-.113c1.61-.406 3.086-1.188 4.389-2.216C4.854 14.9.146 8.978 0 3.276l3.401 1.318Z" />
</svg>
"""
end
def icon(%{name: "si-matrix"} = assigns) do
~H"""
<svg
role="img"
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
class={["icon", @class]}
>
<path d="M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.314.448.208.785.582 1.02 1.108.254-.374.6-.706 1.034-.992.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.245.489.559.646.951.152.392.23.863.23 1.417v5.728h-2.349V11.52c0-.286-.01-.559-.032-.812a1.755 1.755 0 0 0-.18-.66 1.106 1.106 0 0 0-.438-.448c-.194-.11-.457-.166-.785-.166-.332 0-.6.064-.803.189a1.38 1.38 0 0 0-.48.499 1.946 1.946 0 0 0-.231.696 5.56 5.56 0 0 0-.06.785v4.768h-2.35v-4.8c0-.254-.004-.503-.018-.752a2.074 2.074 0 0 0-.143-.688 1.052 1.052 0 0 0-.415-.503c-.194-.125-.476-.19-.854-.19-.111 0-.259.024-.439.074-.18.051-.36.143-.53.282-.171.138-.319.337-.439.595-.12.259-.18.6-.18 1.02v4.966H5.46V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z" />
</svg>
"""
end
def icon(%{name: "yggdrasil"} = assigns) do
~H"""
<svg
viewBox="0 0 22.5 22.5"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
class={["icon", @class]}
>
<path d="M2.662 22.31c.065-.264.833-2.14 1.51-3.685.692-1.58.68-1.518.486-2.31-.24-.986-.226-2.594.032-3.447.93-3.081 3.344-5.17 8.587-7.426 1.708-.736 2.646-1.207 3.357-1.689 1.254-.849 2.559-2.321 2.976-3.36.088-.218.187-.395.22-.393.102.007.051 3.11-.069 4.192-.745 6.696-3.016 11.05-6.755 12.955-2.158 1.1-5.56 1.507-7.144.856-.224-.092-.46-.168-.524-.168-.241 0-1.106 2.31-1.355 3.618-.076.405-.194.962-.21 1.047-.387-.003-.026 0-.575 0h-.583z" />
</svg>
"""
end
def icon(assigns) do
~H"""
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class={["icon", @class]}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.182 16.318A4.486 4.486 0 0 0 12.016 15a4.486 4.486 0 0 0-3.198 1.318M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0ZM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Z"
/>
</svg>
Missing icon
"""
end
end

View file

@ -0,0 +1,14 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="icon"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5"
/>
</svg>

After

Width:  |  Height:  |  Size: 294 B

View file

@ -0,0 +1,14 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="icon"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"
/>
</svg>

After

Width:  |  Height:  |  Size: 478 B

View file

@ -0,0 +1,14 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="icon"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 299 B

View file

@ -0,0 +1,14 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="icon"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 376 B

View file

@ -0,0 +1,9 @@
<svg
role="img"
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
class="icon"
>
<path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,9 @@
<svg
role="img"
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
class="icon"
>
<path d="M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.314.448.208.785.582 1.02 1.108.254-.374.6-.706 1.034-.992.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.245.489.559.646.951.152.392.23.863.23 1.417v5.728h-2.349V11.52c0-.286-.01-.559-.032-.812a1.755 1.755 0 0 0-.18-.66 1.106 1.106 0 0 0-.438-.448c-.194-.11-.457-.166-.785-.166-.332 0-.6.064-.803.189a1.38 1.38 0 0 0-.48.499 1.946 1.946 0 0 0-.231.696 5.56 5.56 0 0 0-.06.785v4.768h-2.35v-4.8c0-.254-.004-.503-.018-.752a2.074 2.074 0 0 0-.143-.688 1.052 1.052 0 0 0-.415-.503c-.194-.125-.476-.19-.854-.19-.111 0-.259.024-.439.074-.18.051-.36.143-.53.282-.171.138-.319.337-.439.595-.12.259-.18.6-.18 1.02v4.966H5.46V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z" />
</svg>

After

Width:  |  Height:  |  Size: 968 B

View file

@ -0,0 +1,10 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="icon"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>

After

Width:  |  Height:  |  Size: 230 B

View file

@ -0,0 +1,9 @@
<svg
role="img"
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
class="icon"
>
<path d="m3.401 4.594 1.025.366 3.08.912c-.01.18-.016.361-.016.543 0 3.353 1.693 7.444 4.51 10.387 2.817-2.943 4.51-7.034 4.51-10.387 0-.182-.006-.363-.016-.543l3.08-.912 1.025-.366L24 3.276C23.854 8.978 19.146 14.9 13.502 18.17c1.302 1.028 2.778 1.81 4.388 2.215v.114l.004.001v.224a14.55 14.55 0 0 1-4.829-1.281A20.909 20.909 0 0 1 12 18.966c-.353.17-.708.329-1.065.477a14.55 14.55 0 0 1-4.829 1.281V20.5l.004-.001v-.113c1.61-.406 3.086-1.188 4.389-2.216C4.854 14.9.146 8.978 0 3.276l3.401 1.318Z" />
</svg>

After

Width:  |  Height:  |  Size: 627 B

View file

@ -0,0 +1,3 @@
<svg viewBox="0 0 22.5 22.5" xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="icon">
<path d="M2.662 22.31c.065-.264.833-2.14 1.51-3.685.692-1.58.68-1.518.486-2.31-.24-.986-.226-2.594.032-3.447.93-3.081 3.344-5.17 8.587-7.426 1.708-.736 2.646-1.207 3.357-1.689 1.254-.849 2.559-2.321 2.976-3.36.088-.218.187-.395.22-.393.102.007.051 3.11-.069 4.192-.745 6.696-3.016 11.05-6.755 12.955-2.158 1.1-5.56 1.507-7.144.856-.224-.092-.46-.168-.524-.168-.241 0-1.106 2.31-1.355 3.618-.076.405-.194.962-.21 1.047-.387-.003-.026 0-.575 0h-.583z" />
</svg>

After

Width:  |  Height:  |  Size: 560 B

View file

@ -12,28 +12,28 @@
<div class="limiter">
<div class="link-list">
<a href="http://[201:80ed:6eeb:aea4:cdc0:c836:2831:f2dd]">
<.icon name="yggdrasil" /> Yggdrasil
<.yggdrasil_icon /> Yggdrasil
</a>
<a href="https://git.comfycamp.space/lumin/comfycamp" target="_blank">
<.icon name="hero-code-bracket" /> Исходный код
<.code_bracket_icon /> Исходный код
</a>
</div>
<div class="link-list">
<a href="https://m.comfycamp.space/@lumin" rel="me" target="_blank">
<.icon name="si-mastodon" /> Mastodon
<.mastodon_icon /> Mastodon
</a>
<a href="mailto:admin@comfycamp.space" target="_blank">
<.icon name="hero-envelope" /> admin@comfycamp.space
<.envelope_icon /> admin@comfycamp.space
</a>
</div>
<div class="link-list">
<a href="https://matrix.to/#/@lumin:matrix.comfycamp.space" target="_blank">
<.icon name="si-matrix" /> @lumin:matrix.comfycamp.space
<.matrix_icon /> @lumin:matrix.comfycamp.space
</a>
<a href="xmpp://lumin@xmpp.comfycamp.space" target="_blank">
<.icon name="si-xmpp" /> lumin@xmpp.comfycamp.space
<.xmpp_icon /> lumin@xmpp.comfycamp.space
</a>
</div>
</div>