Pagination
Pagination with page navigation, next and previous links.
Installation
Add the component to your project:
rails generate shadcn:component pagination
Usage
There are three ways to use the Pagination component:
1. Slot-based API (Full Control)
<%= render Shadcn::PaginationComponent.new do |pagination| %>
<% pagination.with_pagination_content do |content| %>
<% content.with_previous(href: "/page/1") %>
<% content.with_item(href: "/page/1") { "1" } %>
<% content.with_item(href: "/page/2", active: true) { "2" } %>
<% content.with_item(href: "/page/3") { "3" } %>
<% content.with_ellipse %>
<% content.with_item(href: "/page/10") { "10" } %>
<% content.with_next_page(href: "/page/3") %>
<% end %>
<% end %>
2. Collection-based API (Kaminari/will_paginate)
<%= render Shadcn::PaginationComponent.new(collection: @posts) %>
3. Pagy-based API
<%= render Shadcn::PaginationComponent.new(pagy: @pagy) %>
Examples
Basic
With Ellipsis
<% content.with_ellipse %>
Disabled Navigation
On the first or last page, disable the previous/next buttons:
<% content.with_previous(disabled: true) %>
<% content.with_next_page(disabled: true) %>
Gem Integration
The pagination component works seamlessly with popular pagination gems. Just pass your paginated collection or Pagy object directly.
Kaminari
Kaminari is the most popular pagination gem for Rails.
class PostsController < ApplicationController
def index
@posts = Post.page(params[:page]).per(10)
end
end
<%= render Shadcn::PaginationComponent.new(
collection: @posts,
url_builder: ->(page) { posts_path(page: page) }
) %>
will_paginate
will_paginate is a classic pagination library.
class PostsController < ApplicationController
def index
@posts = Post.paginate(page: params[:page], per_page: 10)
end
end
<%= render Shadcn::PaginationComponent.new(
collection: @posts,
url_builder: ->(page) { posts_path(page: page) }
) %>
Pagy
Pagy is the fastest pagination gem with the smallest memory footprint.
class PostsController < ApplicationController
include Pagy::Backend
def index
@pagy, @posts = pagy(Post.all, items: 10)
end
end
<%= render Shadcn::PaginationComponent.new(
pagy: @pagy,
url_builder: ->(page) { posts_path(page: page) }
) %>
Custom URL Builder
The url_builder lambda receives the page number
and should return the URL for that page. This gives you full control over URL generation.
<%# With additional query params %>
<%= render Shadcn::PaginationComponent.new(
collection: @posts,
url_builder: ->(page) { posts_path(page: page, sort: params[:sort], filter: params[:filter]) }
) %>
<%# With URL helpers %>
<%= render Shadcn::PaginationComponent.new(
collection: @posts,
url_builder: ->(page) { url_for(page: page) }
) %>
<%# With namespaced routes %>
<%= render Shadcn::PaginationComponent.new(
collection: @posts,
url_builder: ->(page) { admin_posts_path(page: page) }
) %>
Window Size
Control how many pages are shown around the current page with the window option.
<%# Show 1 page on each side of current (default is 2) %>
<%= render Shadcn::PaginationComponent.new(
collection: @posts,
window: 1,
url_builder: ->(page) { posts_path(page: page) }
) %>
<%# Show 3 pages on each side of current %>
<%= render Shadcn::PaginationComponent.new(
collection: @posts,
window: 3,
url_builder: ->(page) { posts_path(page: page) }
) %>
API Reference
PaginationComponent
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| collection |
Object
|
nil
|
Kaminari or will_paginate collection |
| pagy |
Pagy
|
nil
|
Pagy pagination object |
| url_builder |
Proc
|
->(page) { "?page=#{page}" }
|
Lambda to generate page URLs, receives page number |
| window |
Integer
|
2
|
Number of pages to show around current page |
PaginationContentComponent Slots
| Slot | Props | Description |
|---|---|---|
| with_previous | href:, disabled: |
Previous page link |
| with_next_page | href:, disabled: |
Next page link |
| with_item | href:, active: |
Page number link (yields page number) |
| with_ellipse | - | Ellipsis indicator for skipped pages |
Accessibility
- Uses
<nav>element withrole="navigation" - Has
aria-label="pagination"for screen readers - Current page marked with
aria-current="page" - Disabled links have
aria-disabled="true"
On This Page