Components Pagination

Petal Pro is the full SaaS app this is built for

Auth, billing, admin, and Claude Code integration included. One purchase, unlimited projects.

Pagination

Discrete page buttons with an outlined current page. Works as links (path templates) or pure events.

path takes a template and each page renders a real link - crawlable, middle-clickable. The current page carries the outline surface (border + wash, the outline-button recipe); everything else is quiet ghost chrome. sibling_count and boundary_count control the windowing around the ellipses. One style by design.

Simple variant

variant="simple" trades the page window for Previous/Next outline buttons with disabled boundary states - fewer decisions on short lists, and the honest form when a total is unreliable (cursor-style paging). previous_label/next_label are attrs, so localization is a prop away; link and event modes work unchanged. The second rail sits on page 1, so Previous renders disabled.

heex
<div class="flex flex-col items-center gap-5">
<.pagination variant="simple" path="/users/:page" total_pages={12} current_page={5} />
<.pagination variant="simple" path="/users/:page" total_pages={12} current_page={1} />
</div>
Event mode

event mode skips links and fires goto-page with phx-value-page instead - for LiveViews that page in place without URL changes.

heex
<.pagination event total_pages={12} current_page={5} sibling_count={1} boundary_count={1} />
Properties
Attribute Type Default Description
aria_label string "Pagination" names the navigation landmark, localizable
boundary_count integer 1 sets a boundary count
class any nil parent div CSS class
current_page integer nil sets the current page
event any false use `phx-click` events instead of linking (disables `link_type` and `path`). `true` fires the classic "goto-page" event; a STRING fires that event name instead - how the data table routes page changes through its single on_change grammar.
event_values map %{} extra phx-value-* pairs sent with event-mode clicks, e.g. %{"op" => "page"}
link_type string "a"
one of: "a", "live_patch", "live_redirect", "button"
next_label string "Next" the next button's label - visible in the simple variant, announced in the numbered one
path string "/:page" page path
previous_label string "Previous" the previous button's label - visible in the simple variant, announced in the numbered one
rest global
show_boundary_chevrons boolean false whether to show prev & next buttons at boundary pages
sibling_count integer 1 sets a sibling count
target any nil the LiveView/LiveComponent to send the event to. Example: `@myself`. Will be ignored if `event` is not enabled.
total_pages integer nil sets a total page count
variant string "numbered" numbered renders the windowed page list; simple renders Previous/Next outline buttons only - fewer decisions on short lists, and the honest form when a total is unreliable
one of: "numbered", "simple"