Pagination
Pagination with page navigation, next and previous links.
Usage
Example
Pagination do
PaginationContent do
PaginationPrevious(href: "#")
PaginationItem(href: "#") { "1" }
PaginationItem(href: "#", active: true) { "2" }
PaginationItem(href: "#") { "3" }
PaginationEllipsis()
PaginationNext(href: "#")
end
end
Simple
Page numbers only.
Pagination do
PaginationContent do
PaginationItem(href: "#") { "1" }
PaginationItem(href: "#", active: true) { "2" }
PaginationItem(href: "#") { "3" }
PaginationItem(href: "#") { "4" }
PaginationItem(href: "#") { "5" }
end
end
Custom labels
Previous and Next take text:. Translate the aria-label along with it, using label! to replace the default. Below the sm breakpoint only the chevron shows.
Pagination do
PaginationContent do
PaginationPrevious(href: "#", text: "Anterior", aria: {label!: "Página anterior"})
PaginationItem(href: "#", size: :default) { "Página 2 de 10" }
PaginationNext(href: "#", text: "Próxima", aria: {label!: "Próxima página"})
end
end
Installation
Using RubyUI CLI
Run the install command
rails g ruby_ui:component Pagination
Manual installation
1
Add RubyUI::Pagination to app/components/ruby_ui/pagination/pagination.rb
# frozen_string_literal: true
module RubyUI
# Page navigation, styled after shadcn's Pagination (Base UI + vega).
class Pagination < Base
def view_template(&)
nav(**attrs, &)
end
private
def default_attrs
{
role: "navigation",
aria: {label: "pagination"},
data: {slot: "pagination"},
class: "mx-auto flex w-full justify-center"
}
end
end
end
2
Add RubyUI::PaginationContent to app/components/ruby_ui/pagination/pagination_content.rb
# frozen_string_literal: true
module RubyUI
class PaginationContent < Base
def view_template(&)
ul(**attrs, &)
end
private
def default_attrs
{
data: {slot: "pagination-content"},
class: "flex items-center gap-1"
}
end
end
end
3
Add RubyUI::PaginationDocs to app/components/ruby_ui/pagination/pagination_docs.rb
# frozen_string_literal: true
class Views::Docs::Pagination < Views::Base
def view_template
component = "Pagination"
div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
render Docs::Header.new(title: "Pagination", description: "Pagination with page navigation, next and previous links.")
Heading(level: 2) { "Usage" }
render Docs::VisualCodeExample.new(title: "Example", context: self) do
<<~RUBY
Pagination do
PaginationContent do
PaginationPrevious(href: "#")
PaginationItem(href: "#") { "1" }
PaginationItem(href: "#", active: true) { "2" }
PaginationItem(href: "#") { "3" }
PaginationEllipsis()
PaginationNext(href: "#")
end
end
RUBY
end
render Docs::VisualCodeExample.new(title: "Simple", description: "Page numbers only.", context: self) do
<<~RUBY
Pagination do
PaginationContent do
PaginationItem(href: "#") { "1" }
PaginationItem(href: "#", active: true) { "2" }
PaginationItem(href: "#") { "3" }
PaginationItem(href: "#") { "4" }
PaginationItem(href: "#") { "5" }
end
end
RUBY
end
render Docs::VisualCodeExample.new(title: "Custom labels", description: "Previous and Next take text:. Translate the aria-label along with it, using label! to replace the default. Below the sm breakpoint only the chevron shows.", context: self) do
<<~RUBY
Pagination do
PaginationContent do
PaginationPrevious(href: "#", text: "Anterior", aria: {label!: "Página anterior"})
PaginationItem(href: "#", size: :default) { "Página 2 de 10" }
PaginationNext(href: "#", text: "Próxima", aria: {label!: "Próxima página"})
end
end
RUBY
end
render Components::ComponentSetup::Tabs.new(component_name: component)
render Docs::ComponentsTable.new(component_files(component))
end
end
end
4
Add RubyUI::PaginationEllipsis to app/components/ruby_ui/pagination/pagination_ellipsis.rb
# frozen_string_literal: true
module RubyUI
# "More pages" marker. Renders its own <li> (shadcn wraps it in
# PaginationItem) and is hidden from assistive tech, as in shadcn.
class PaginationEllipsis < Base
def view_template
li(data: {slot: "pagination-item"}) do
span(**attrs) do
icon
span(class: "sr-only") { "More pages" }
end
end
end
private
def icon
svg(
xmlns: "http://www.w3.org/2000/svg",
width: "24",
height: "24",
viewbox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
stroke_width: "2",
stroke_linecap: "round",
stroke_linejoin: "round",
aria_hidden: "true"
) do |s|
s.circle(cx: "12", cy: "12", r: "1")
s.circle(cx: "19", cy: "12", r: "1")
s.circle(cx: "5", cy: "12", r: "1")
end
end
# aria-hidden needs the string: Phlex renders true as an empty value,
# which doesn't hide the element.
def default_attrs
{
aria: {hidden: "true"},
data: {slot: "pagination-ellipsis"},
class: "flex size-9 items-center justify-center [&_svg:not([class*='size-'])]:size-4"
}
end
end
end
5
Add RubyUI::PaginationItem to app/components/ruby_ui/pagination/pagination_item.rb
# frozen_string_literal: true
module RubyUI
# One page link: shadcn's PaginationItem (<li>) and PaginationLink (<a>) in
# one part. Attributes go to the <a>. It stays a plain link (no
# role="button"): it navigates.
#
# size: takes Button sizes. The default, :icon, makes a 36px square for a
# page number, as in shadcn; pass size: :default for a link with text.
class PaginationItem < Base
def initialize(href: "#", active: false, size: :icon, **attrs)
@href = href
@active = active
@size = size
super(**attrs)
end
def view_template(&)
li(data: {slot: "pagination-item"}) do
a(href: @href, **attrs, &)
end
end
private
def default_attrs
{
aria: {current: @active ? "page" : nil},
data: {slot: "pagination-link", active: @active ? "true" : nil},
class: [
RubyUI::Button.new(variant: @active ? :outline : :ghost, size: @size).attrs[:class]
]
}
end
end
end
6
Add RubyUI::PaginationNext to app/components/ruby_ui/pagination/pagination_next.rb
# frozen_string_literal: true
module RubyUI
# Link to the next page: text plus chevron, which collapses to the icon
# below the sm breakpoint. text: changes the label.
class PaginationNext < PaginationItem
def initialize(href: "#", text: "Next", **attrs)
@text = text
super(href: href, size: :default, **attrs)
end
def view_template
li(data: {slot: "pagination-item"}) do
a(href: @href, **attrs) do
span(class: "hidden sm:block") { @text }
svg(xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewbox: "0 0 24 24", fill: "none",
stroke: "currentColor", stroke_width: "2", stroke_linecap: "round", stroke_linejoin: "round",
aria_hidden: "true", data: {icon: "inline-end"}) do |s|
s.path(d: "m9 18 6-6-6-6")
end
end
end
end
private
def default_attrs
mix(super, {aria: {label: "Go to next page"}, class: "pr-2!"})
end
end
end
7
Add RubyUI::PaginationPrevious to app/components/ruby_ui/pagination/pagination_previous.rb
# frozen_string_literal: true
module RubyUI
# Link to the previous page: chevron plus text, which collapses to the icon
# below the sm breakpoint. text: changes the label.
class PaginationPrevious < PaginationItem
def initialize(href: "#", text: "Previous", **attrs)
@text = text
super(href: href, size: :default, **attrs)
end
def view_template
li(data: {slot: "pagination-item"}) do
a(href: @href, **attrs) do
svg(xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewbox: "0 0 24 24", fill: "none",
stroke: "currentColor", stroke_width: "2", stroke_linecap: "round", stroke_linejoin: "round",
aria_hidden: "true", data: {icon: "inline-start"}) do |s|
s.path(d: "m15 18-6-6 6-6")
end
span(class: "hidden sm:block") { @text }
end
end
end
private
def default_attrs
mix(super, {aria: {label: "Go to previous page"}, class: "pl-2!"})
end
end
end
8
Install required components
Component Pagination relies on the following RubyUI components. Refer to their individual installation guides for setup instructions:
Components
| Component | Built using | Source |
|---|---|---|
Pagination | Phlex | |
PaginationContent | Phlex | |
PaginationDocs | Phlex | |
PaginationEllipsis | Phlex | |
PaginationItem | Phlex | |
PaginationNext | Phlex | |
PaginationPrevious | Phlex |