chiya/lib/chiya_web/components/public_components.ex

298 lines
8 KiB
Elixir
Raw Normal View History

defmodule ChiyaWeb.PublicComponents do
use Phoenix.Component
use Phoenix.VerifiedRoutes,
endpoint: ChiyaWeb.Endpoint,
router: ChiyaWeb.Router,
statics: ChiyaWeb.static_paths()
2023-05-07 10:30:32 +02:00
import ChiyaWeb.Format
import ChiyaWeb.Markdown, only: [render: 1]
import Phoenix.HTML, only: [raw: 1]
2023-06-19 21:49:01 +02:00
@doc """
Renders a [Hero Icon](https://heroicons.com).
Hero icons come in three styles outline, solid, and mini.
By default, the outline style is used, but solid an mini may
be applied by using the `-solid` and `-mini` suffix.
You can customize the size and colors of the icons by setting
width, height, and background color classes.
Icons are extracted from your `priv/hero_icons` directory and bundled
within your compiled app.css by the plugin in your `assets/tailwind.config.js`.
## Examples
<.icon name="hero-cake" />
<.icon name="hero-cake-solid" />
<.icon name="hero-cake-mini" />
<.icon name="hero-bolt" class="bg-blue-500 w-10 h-10" />
"""
attr :name, :string, required: true
attr :class, :string, default: nil
def icon(%{name: "hero-" <> _} = assigns) do
~H"""
<span class={[@name, @class]} />
"""
end
2023-05-07 10:30:32 +02:00
2023-05-22 20:05:44 +02:00
@doc """
Renders a middot as divider
"""
def dot(assigns),
do: ~H"""
2023-05-22 20:05:44 +02:00
<span class="text-theme-primary font-bold">·</span>
"""
@doc """
Renders a horizontal line
"""
def line(assigns),
do: ~H"""
<hr class="my-6 border-theme-base/20" />
"""
2023-05-22 20:05:44 +02:00
attr :text, :string, default: ""
2023-06-03 09:27:43 +02:00
def divider(assigns) do
~H"""
2023-06-28 16:02:30 +02:00
<div class="flex items-center my-8 text-theme-primary before:flex-1 after:flex-1 before:content-[''] after:content-[''] before:p-[0.5px] after:p-[0.5px] before:bg-theme-base/25 after:bg-theme-base/25 w-full mx-auto last:hidden">
<%= assigns.text %>
</div>
"""
end
attr :note, :map, required: true
attr :class_tag, :string, default: ""
def tags(assigns) do
~H"""
<span class="inline-flex flex-row gap-1">
<%= for tag <- @note.tags do %>
<a href={~p"/tagged-with/#{tag.slug}"} class={["p-category", @class_tag]}>
<%= tag.name %>
</a>
<% end %>
</span>
"""
end
@doc """
Renders a note-header with title.
"""
attr :class, :string, default: nil
2023-07-06 21:28:56 +02:00
attr :class_title, :string, default: nil
attr :class_subtitle, :string, default: nil
2023-07-06 21:28:56 +02:00
slot :subtitle, required: false
def header(assigns) do
~H"""
2023-07-06 21:28:56 +02:00
<header class={["p-8 rounded bg-theme-background1", @class]}>
<h1 class={["text-3xl leading-10 text-theme-base", @class_title]}>
2023-07-09 20:01:03 +02:00
<%= render_slot(@inner_block) %>
</h1>
2023-07-09 20:01:03 +02:00
<p
:if={@subtitle != []}
class={["mt-4 leading-7 font-semibold text-theme-base/75", @class_subtitle]}
>
<%= render_slot(@subtitle) %>
</p>
</header>
"""
end
2023-05-07 10:30:32 +02:00
attr :layout, :atom, default: :list
attr :notes, :list, required: true
def note_list(assigns) do
case assigns.layout do
:gallery ->
2023-06-27 22:04:44 +02:00
note_list_gallery(assigns)
:microblog ->
note_list_microblog(assigns)
_ ->
note_list_headers(assigns)
end
end
2023-07-09 20:01:03 +02:00
attr :notes, :list, required: true
2023-06-27 22:04:44 +02:00
def note_list_headers(assigns) do
~H"""
<section class="note-list default | mt-6 sm:w-auto flex flex-col gap-3">
2023-06-27 22:04:44 +02:00
<%= for note <- assigns.notes do %>
2023-07-09 20:01:03 +02:00
<a
href={~p"/note/#{note.slug}"}
class="rounded-lg px-6 pt-4 pb-5 border border-theme-background1 hover:bg-theme-background1 transition"
>
2023-07-20 07:26:48 +02:00
<header class="flex flex-row items-center">
<span class="text-theme-primary text-lg font-semibold leading-8 flex-1">
<%= note.name %>
</span>
<span class="text-theme-base/75 text-sm">
<%= pretty_date(note.published_at) %>
</span>
</header>
2023-07-09 20:01:03 +02:00
<p class="text-theme-base">
<%= String.slice(note.content, 0..150) %>
</p>
2023-06-27 22:04:44 +02:00
</a>
<% end %>
</section>
"""
end
attr :note, :map, required: true
def note_list_microblog(assigns) do
~H"""
<section class="note-list microblog | mt-6 text-theme-base">
<%= for note <- assigns.notes do %>
<article class="mt-4 first:mt-0">
<.featured_images note={note} />
<div class="prose prose-gruvbox">
<%= raw(render(note.content)) %>
</div>
<footer class="mt-1">
<time class="text-theme-base/75">
<%= pretty_datetime(note.published_at) %>
</time>
<.dot />
2023-07-09 20:01:03 +02:00
<%= if not Enum.empty?(note.tags) do %>
<.tags note={note} />
<.dot />
<% end %>
2023-06-27 22:04:44 +02:00
<a href={~p"/note/#{note.slug}"} class="text-theme-base/75">Permalink</a>
<%= if not Enum.empty?(note.images) do %>
<.dot />
<.icon name="hero-photo" />
<% end %>
</footer>
</article>
<.divider />
<% end %>
</section>
"""
end
def note_list_gallery(assigns) do
~H"""
<section class="note-list gallery | mt-6">
<%= for note <- assigns.notes do %>
<article>
<section class="flex flex-wrap justify-start gap-3">
<%= for image <- note.images do %>
2023-05-07 10:30:32 +02:00
<a
2023-06-27 22:04:44 +02:00
href={ChiyaWeb.Helpers.image_url(image, :full)}
class="lightbox | w-28"
data-gallery={gallery_name(note)}
data-description={ChiyaWeb.Markdown.render(image.content)}
2023-05-07 10:30:32 +02:00
>
2023-06-27 22:04:44 +02:00
<img src={ChiyaWeb.Helpers.image_url(image, :thumb)} loading="lazy" />
2023-05-07 10:30:32 +02:00
</a>
2023-06-27 22:04:44 +02:00
<% end %>
</section>
<a
href={~p"/note/#{note.slug}"}
class="text-theme-secondary text-lg/10 font-semibold rounded-lg -mx-2 -my-0.5 px-2 py-0.5 hover:bg-theme-secondary/10 transition"
>
<%= note.name %>
<span class="text-theme-base/75 text-sm">
<%= pretty_date(note.published_at) %>
</span>
</a>
</article>
<.line />
<% end %>
</section>
"""
end
def featured_images(assigns) do
images = main_images(assigns.note)
2023-05-07 10:30:32 +02:00
2023-06-27 22:04:44 +02:00
case Enum.count(images) do
0 ->
~H"""
<figure />
2023-05-07 10:30:32 +02:00
"""
2023-06-27 22:04:44 +02:00
1 ->
assigns = assign(assigns, :image, List.first(images))
2023-05-07 10:30:32 +02:00
~H"""
2023-06-27 22:04:44 +02:00
<figure class="mb-4">
<img
src={ChiyaWeb.Helpers.image_url(assigns.image, :full)}
class="rounded"
title={assigns.image.content}
/>
</figure>
"""
2023-06-27 22:04:44 +02:00
2 ->
assigns =
assigns
|> assign(:first, Enum.at(images, 0))
|> assign(:second, Enum.at(images, 1))
~H"""
2023-06-27 22:04:44 +02:00
<figure class="flex gap-1">
<img
src={ChiyaWeb.Helpers.image_url(assigns.first, :thumb)}
class="rounded-l flex-1 w-full"
title={assigns.first.content}
/>
<img
src={ChiyaWeb.Helpers.image_url(assigns.second, :thumb)}
class="rounded-r flex-1 w-full"
title={assigns.second.content}
/>
</figure>
2023-05-07 10:30:32 +02:00
"""
2023-06-27 22:04:44 +02:00
2023-07-05 06:49:37 +02:00
3 ->
assigns =
assigns
|> assign(:first, Enum.at(images, 0))
|> assign(:second, Enum.at(images, 1))
|> assign(:third, Enum.at(images, 2))
~H"""
<figure class="flex gap-1">
<img
src={ChiyaWeb.Helpers.image_url(assigns.first, :thumb)}
class="flex-1 w-full rounded-l"
title={assigns.first.content}
/>
<img
src={ChiyaWeb.Helpers.image_url(assigns.second, :thumb)}
class="flex-1 w-full"
title={assigns.second.content}
/>
<img
src={ChiyaWeb.Helpers.image_url(assigns.third, :thumb)}
class="flex-1 w-full rounded-r"
title={assigns.third.content}
/>
</figure>
"""
2023-05-07 10:30:32 +02:00
end
end
defp gallery_name(note), do: "gallery-#{note.id}"
2023-06-27 22:04:44 +02:00
defp main_images(note),
do: Enum.filter(note.images, fn image -> image.featured end)
end