136 lines
3.0 KiB
Elixir
136 lines
3.0 KiB
Elixir
|
defmodule PortfolioWeb.CustomComponents do
|
||
|
use Phoenix.Component
|
||
|
|
||
|
import PortfolioWeb.CoreComponents
|
||
|
|
||
|
@doc """
|
||
|
Renders an anchor tag that opens a new tab.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
<.link_blank href="/files/tagless-final-parsing/kiselyov-interpreters.pdf">
|
||
|
PDF
|
||
|
</.link_blank>,
|
||
|
"""
|
||
|
attr :href, :string, required: true
|
||
|
slot :inner_block, required: true
|
||
|
|
||
|
def link_blank(assigns) do
|
||
|
~H"""
|
||
|
<a target="_blank" href={@href}>
|
||
|
<%= render_slot(@inner_block) %>
|
||
|
</a>
|
||
|
"""
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Renders a project description.
|
||
|
"""
|
||
|
attr :title, :string, required: true
|
||
|
attr :href, :string, required: true
|
||
|
attr :date, :string, required: true
|
||
|
slot :inner_block, required: true
|
||
|
|
||
|
def project(assigns) do
|
||
|
~H"""
|
||
|
<div>
|
||
|
<a target="_blank" href={@href} class="pr-1 font-bold text-cyan-500"><%= @title %></a>
|
||
|
<span class="text-slate-400 text-sm"><%= @date %></span>
|
||
|
<p class="pt-1">
|
||
|
<%= render_slot(@inner_block) %>
|
||
|
</p>
|
||
|
</div>
|
||
|
"""
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Renders a blog description.
|
||
|
"""
|
||
|
attr :title, :string, required: true
|
||
|
attr :href, :string, required: true
|
||
|
attr :date, :string, required: true
|
||
|
slot :inner_block, required: true
|
||
|
|
||
|
def blog(assigns) do
|
||
|
~H"""
|
||
|
<div>
|
||
|
<.link navigate={@href} class="pr-1 font-bold text-cyan-500"><%= @title %></.link>
|
||
|
<span class="text-slate-400 text-sm"><%= @date %></span>
|
||
|
<p class="pt-1">
|
||
|
<%= render_slot(@inner_block) %>
|
||
|
</p>
|
||
|
</div>
|
||
|
"""
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Renders an informational admonition.
|
||
|
"""
|
||
|
slot :inner_block, required: true
|
||
|
|
||
|
def info(assigns) do
|
||
|
~H"""
|
||
|
<div class="bg-info flex flex-col p-4 gap-2" role="alert">
|
||
|
<div class="flex items-center gap-1">
|
||
|
<.icon name="hero-information-circle" />
|
||
|
<strong>Info</strong>
|
||
|
</div>
|
||
|
<%= render_slot(@inner_block) %>
|
||
|
</div>
|
||
|
"""
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Renders a tip admonition.
|
||
|
"""
|
||
|
slot :inner_block, required: true
|
||
|
|
||
|
def tip(assigns) do
|
||
|
~H"""
|
||
|
<div class="bg-tip flex flex-col p-4 gap-2" role="alert">
|
||
|
<div class="flex items-center gap-1">
|
||
|
<.icon name="hero-pencil" />
|
||
|
<strong>Tip</strong>
|
||
|
</div>
|
||
|
<%= render_slot(@inner_block) %>
|
||
|
</div>
|
||
|
"""
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Renders a warning admonition.
|
||
|
"""
|
||
|
slot :inner_block, required: true
|
||
|
|
||
|
def warning(assigns) do
|
||
|
~H"""
|
||
|
<div class="bg-warning flex flex-col p-4 gap-2" role="alert">
|
||
|
<div class="flex items-center gap-1">
|
||
|
<.icon name="hero-exclamation-triangle" />
|
||
|
<strong>Warning</strong>
|
||
|
</div>
|
||
|
<%= render_slot(@inner_block) %>
|
||
|
</div>
|
||
|
"""
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Renders an accordion.
|
||
|
"""
|
||
|
attr :header, :string, required: true
|
||
|
slot :inner_block, required: true
|
||
|
|
||
|
def accordion(assigns) do
|
||
|
~H"""
|
||
|
<details class="border border-dashed border-color-[#rgba(155, 155, 155, 0.8)] p-4">
|
||
|
<summary>
|
||
|
<strong><%= @header %></strong>
|
||
|
</summary>
|
||
|
<div class="pt-6">
|
||
|
<%= render_slot(@inner_block) %>
|
||
|
</div>
|
||
|
</details>
|
||
|
"""
|
||
|
end
|
||
|
end
|