Skip to content

Instantly share code, notes, and snippets.

@cblavier
Created February 2, 2023 14:18
Show Gist options
  • Save cblavier/50756b9e6585cf1a4d6d8da97fb69562 to your computer and use it in GitHub Desktop.
Save cblavier/50756b9e6585cf1a4d6d8da97fb69562 to your computer and use it in GitHub Desktop.
Phoenix pagination components
defmodule ReadableWeb.Pagination do
use Phoenix.Component
attr :page, :integer, required: true
attr :page_count, :integer, required: true
attr :path, :string, required: true
def pagination(assigns) do
~H"""
<ul class="inline-flex items-center h-8">
<li class="h-full">
<.link patch={previous_page(@path, @page)} class={[item_class(), "rounded-l-md"]}>
<span class="sr-only">Previous</span>
<i class="fa fa-chevron-left fa-xs" />
</.link>
</li>
<%= if @page < 3 do %>
<li :for={i <- 1..(@page - 1)} :if={i > 0 && i < @page} class="h-full">
<.link patch={page_path(@path, i)} class={item_class()}><%= i %></.link>
</li>
<% else %>
<li class="h-full">
<.link patch={page_path(@path, 1)} class={item_class()}>1</.link>
</li>
<li class="h-full">
<span class={item_class()}>...</span>
</li>
<% end %>
<li class="h-full">
<.link patch={page_path(@path, @page)} class={[item_class(), active_item_class()]}>
<%= @page %>
</.link>
</li>
<%= if @page_count - @page < 2 do %>
<li :for={i <- (@page + 1)..@page_count} :if={i > @page && i <= @page_count} class="h-full">
<.link patch={page_path(@path, i)} class={item_class()}><%= i %></.link>
</li>
<% else %>
<li class="h-full">
<span class={item_class()}>...</span>
</li>
<li class="h-full">
<.link patch={page_path(@path, @page_count)} class={item_class()}>
<%= @page_count %>
</.link>
</li>
<% end %>
<li class="h-full">
<.link
patch={next_page(@path, @page, @page_count)}
class={[item_class(), "border-r rounded-r-md"]}
>
<span class="sr-only">Next</span>
<i class="fa fa-chevron-right fa-xs" />
</.link>
</li>
</ul>
"""
end
defp previous_page(path, 1), do: page_path(path, 1)
defp previous_page(path, page), do: page_path(path, page - 1)
defp next_page(path, page, page), do: page_path(path, page)
defp next_page(path, page, _page_count), do: page_path(path, page + 1)
defp page_path(path, 1), do: path
defp page_path(path, page) do
if String.contains?(path, "?") do
"#{path}&page=#{page}"
else
"#{path}?page=#{page}"
end
end
defp item_class do
"flex justify-center items-center h-full px-3 border-t border-b border-l border-secondary-300 hover:bg-primary-100 hover:text-primary-600 text-sm font-medium"
end
defp active_item_class do
"bg-primary-100 text-primary-600 font-semibold"
end
attr :page, :integer, required: true
attr :page_size, :integer, required: true
attr :entry_count, :integer, required: true
def entry_count(assigns) do
~H"""
<div class="text-secondary-500 text-sm">
<span>Showing</span>
<span class="text-secondary-900 font-medium">
<%= (@page - 1) * @page_size + 1 %> - <%= min(@page * @page_size, @entry_count) %>
</span>
<span>of</span>
<span class="text-secondary-900 font-medium"><%= @entry_count %></span>
</div>
"""
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment