Packages
petal_components
1.4.5
4.7.0
4.6.2
4.6.1
4.6.0
4.5.0
4.4.0
4.3.0
4.2.1
4.2.0
4.1.2
4.1.1
4.1.0
4.0.12
4.0.11
4.0.10
4.0.6
4.0.5
4.0.4
4.0.3
4.0.1
3.2.2
3.2.1
3.2.0
3.1.0
3.0.2
3.0.1
3.0.0
2.9.3
2.9.2
retired
2.9.1
retired
2.9.0
retired
2.8.4
2.8.3
2.8.2
2.8.1
2.8.0
2.7.4
2.7.3
2.7.2
2.7.1
2.7.0
2.6.1
2.6.0
2.5.2
2.5.1
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.0
2.2.1
2.2.0
2.1.2
2.1.1
2.1.0
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.9.3
1.9.2
1.9.1
1.9.0
1.8.0
1.7.1
1.7.0
1.6.2
1.6.1
1.6.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.14
1.2.13
1.2.12
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.19.10
0.19.9
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.7
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.15.0
0.14.1
0.14.0
0.13.7
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.8
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.2
0.2.1
0.2.0
0.1.0
Shadcn-style Phoenix LiveView components that AI assistants can actually use. Pair with the MCP server so AI coding tools can inspect the real component API.
Current section
Files
Jump to
Current section
Files
lib/petal_components/pagination.ex
defmodule PetalComponents.Pagination do
@moduledoc """
Pagination is the method of splitting up content into discrete pages. It specifies the total number of pages and inidicates to a user the current page within the context of total pages.
"""
use Phoenix.Component
import PetalComponents.Helpers
import PetalComponents.PaginationInternal
alias PetalComponents.Link
attr :path, :string, default: "/:page", doc: "page path"
attr :class, :string, default: "", doc: "Parent div CSS class"
attr :link_type, :string,
default: "a",
values: ["a", "live_patch", "live_redirect", "button"]
attr :event, :boolean,
default: false,
doc:
"whether to use `phx-click` events instead of linking. Enabling this will disable `link_type` and `path`."
attr :total_pages, :integer, default: nil, doc: "sets a total page count"
attr :current_page, :integer, default: nil, doc: "sets the current page"
attr :sibling_count, :integer, default: 1, doc: "sets a sibling count"
attr :boundary_count, :integer, default: 1, doc: "sets a boundary count"
attr :rest, :global
@doc """
In the `path` param you can specify :page as the place your page number will appear.
e.g "/posts/:page" => "/posts/1"
"""
def pagination(assigns) do
~H"""
<div {@rest} class={"#{@class} pc-pagination"}>
<ul class="pc-pagination__inner">
<%= for item <- get_pagination_items(@total_pages, @current_page, @sibling_count, @boundary_count) do %>
<%= if item.type == "prev" and item.enabled? do %>
<div>
<Link.a
phx-click={if @event, do: "goto-page"}
phx-value-page={item.number}
link_type={if @event, do: "button", else: @link_type}
to={if not @event, do: get_path(@path, item.number, @current_page)}
class="pc-pagination__item__previous"
>
<Heroicons.chevron_left solid class="pc-pagination__item__previous__chevron" />
</Link.a>
</div>
<% end %>
<%= if item.type == "page" do %>
<li>
<%= if item.current? do %>
<span class={get_box_class(item)}><%= item.number %></span>
<% else %>
<Link.a
phx-click={if @event, do: "goto-page"}
phx-value-page={item.number}
link_type={if @event, do: "button", else: @link_type}
to={if not @event, do: get_path(@path, item.number, @current_page)}
class={get_box_class(item)}
>
<%= item.number %>
</Link.a>
<% end %>
</li>
<% end %>
<%= if item.type == "..." do %>
<li>
<span class="pc-pagination__item__ellipsis">
...
</span>
</li>
<% end %>
<%= if item.type == "next" and item.enabled? do %>
<div>
<Link.a
phx-click={if @event, do: "goto-page"}
phx-value-page={item.number}
link_type={if @event, do: "button", else: @link_type}
to={if not @event, do: get_path(@path, item.number, @current_page)}
class="pc-pagination__item__next"
>
<Heroicons.chevron_right solid class="pc-pagination__item__next__chevron" />
</Link.a>
</div>
<% end %>
<% end %>
</ul>
</div>
"""
end
defp get_box_class(item) do
base_classes = "pc-pagination__item"
active_classes =
if item.current?,
do: "pc-pagination__item--is-current",
else: "pc-pagination__item--is-not-current"
rounded_classes =
case item do
%{first?: true, last?: true} ->
"pc-pagination__item--with-single-box"
%{first?: true, last?: false} ->
"pc-pagination__item--with-multiple-boxes--left"
%{first?: false, last?: true} ->
"pc-pagination__item--with-multiple-boxes--right"
_ ->
"pc-pagination__item--rounded-catch-all"
end
build_class([base_classes, active_classes, rounded_classes])
end
defp get_path(path, page_number, current_page) when is_binary(path) do
get_path(&String.replace(path, ":page", Integer.to_string(&1)), page_number, current_page)
end
defp get_path(fun, "previous", current_page) when is_function(fun, 1) do
get_path(fun, current_page - 1, current_page)
end
defp get_path(fun, "next", current_page) when is_function(fun, 1) do
get_path(fun, current_page + 1, current_page)
end
defp get_path(fun, page_number, _current_page) when is_function(fun, 1) do
then(page_number, fun)
end
end