Pagination
Framework-agnostic pagination with page windowing, multiple visual styles, sizes, info text, and Pagy convenience helper.
Default Pagination
Basic pagination with prev/next buttons, page numbers, and automatic ellipsis gaps.
Page 5 of 20
First page (prev disabled)
Last page (next disabled)
<%= bui_pagination(
current_page: 5,
total_pages: 20,
url: ->(page) { users_path(page: page) }
) %>
Variants
All 9 semantic color variants applied to the pagination component.
primary
secondary
accent
success
danger
warning
info
light
dark
<%= bui_pagination(
current_page: 5,
total_pages: 15,
url: ->(page) { "#page-#{page}" },
variant: :success
) %>
Visual Styles
Four visual styles: solid fills the active page, outline adds a border, ghost uses a subtle background, soft uses a tinted background.
solid
outline
ghost
soft
<%= bui_pagination(
current_page: 5,
total_pages: 15,
url: ->(page) { "#page-#{page}" },
style: :solid
) %>
Sizes
Five sizes from extra-small to extra-large controlling item dimensions, text, and spacing.
xs
sm
md
lg
xl
<%= bui_pagination(
current_page: 5,
total_pages: 15,
url: ->(page) { "#page-#{page}" },
size: :lg
) %>
Border Radius
Control corner rounding of pagination items. Shown here with solid style for visibility.
none
sm
md
lg
full
<%= bui_pagination(
current_page: 5,
total_pages: 15,
url: ->(page) { "#page-#{page}" },
rounded: :full,
style: :solid
) %>
Navigation Options
Show/hide first/last buttons, use custom text labels, or display only prev/next without page numbers.
With First/Last Buttons
Custom Text Labels
Prev/Next Only (no page numbers)
<%# With first/last buttons and custom labels %>
<%= bui_pagination(
current_page: 10,
total_pages: 20,
url: ->(page) { "#page-#{page}" },
show_first_last: true,
first_label: "First",
last_label: "Last",
prev_label: "Prev",
next_label: "Next"
) %>
<%# Prev/Next only %>
<%= bui_pagination(
current_page: 5,
total_pages: 20,
url: ->(page) { "#page-#{page}" },
show_page_numbers: false,
prev_label: "Previous",
next_label: "Next"
) %>
Info Text
Display auto-generated 'Showing X-Y of Z results' text, or provide custom info via the slot.
Auto-generated Info
Custom Info Slot
Last Page (partial results)
<%# Auto-generated info text %>
<%= bui_pagination(
current_page: 3,
total_pages: 10,
url: ->(page) { "#page-#{page}" },
show_info: true,
per_page: 20,
total_count: 195
) %>
<%# Custom info slot %>
<%= bui_pagination(
current_page: 3,
total_pages: 10,
url: ->(page) { "#page-#{page}" }
) do |pg| %>
<% pg.with_info { "Showing 41-60 of 195 results" } %>
<% end %>
Edge Cases
Pagination gracefully handles small page counts, very large page counts, and various current-page positions.
2 Pages
5 Pages (no gaps)
100 Pages — First Page
100 Pages — Middle (dual gap)
100 Pages — Last Page
Combined with Table
A real-world example: data table with pagination and info text below.
| Name | Role | Status | |
|---|---|---|---|
| Alice Johnson | alice@example.com | Admin | Active |
| Bob Wilson | bob@example.com | Editor | Active |
| Carol Davis | carol@example.com | Viewer | Inactive |
| David Brown | david@example.com | Editor | Active |
| Eve Martinez | eve@example.com | Admin | Active |
<%= bui_table(collection: @users, variant: :primary, striped: true, hoverable: true) do |t| %>
<% t.with_column(key: :name, label: "Name") %>
<% t.with_column(key: :email, label: "Email") %>
<% end %>
<%= bui_pagination(
current_page: @page,
total_pages: @total_pages,
url: ->(page) { users_path(page: page) },
show_info: true,
per_page: 5,
total_count: @total_count
) %>
<%# Or with Pagy: %>
<%= bui_pagination_for(@pagy, variant: :primary) %>
Style Combinations
Mix different styles, variants, rounded, and sizes for unique looks.
Solid + Success + Full Rounded + Large
Ghost + Danger + Small
Soft + Accent + No Rounded
Outline + Dark + Full Rounded + XS