Skip to content

Pagination

Pages to move between, HeroUI's on Kobalte's buttons.

Solidtype_heroui.Pagination is HeroUI’s <nav> of pages, each page, Previous and Next a button on Kobalte’s Button, with the classes HeroUI’s own paginationVariants gives. As in HeroUI, it keeps no page of its own: which pages show, which is active and what a press does are the application’s, in a signal.

pagination_usage.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module For = Solidtype.For
module Pagination = Solidtype_heroui.Pagination
let total_pages = 3
let make () =
let page, set_page = S.create_signal 1 in
<Pagination class_="justify-center">
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous
is_disabled=(fun () -> S.get page = 1)
on_press=(fun () -> S.update set_page pred)>
<Pagination.Previous_icon /> <span>"Previous"</span>
</Pagination.Previous>
</Pagination.Item>
<For each=(fun () -> Array.init total_pages succ)>
(fun p _ ->
<Pagination.Item>
<Pagination.Link
is_active=(fun () -> p = S.get page)
on_press=(fun () -> S.set set_page p)>
(fun () -> Jsx.int p)
</Pagination.Link>
</Pagination.Item>)
</For>
<Pagination.Item>
<Pagination.Next
is_disabled=(fun () -> S.get page = total_pages)
on_press=(fun () -> S.update set_page succ)>
<span>"Next"</span> <Pagination.Next_icon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>
<Pagination>
<Pagination.Summary>"Showing 1-10 of 100 results"</Pagination.Summary>
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous>
<Pagination.Previous_icon /> <span>"Previous"</span>
</Pagination.Previous>
</Pagination.Item>
<Pagination.Item>
<Pagination.Link is_active=true>"1"</Pagination.Link>
</Pagination.Item>
<Pagination.Item><Pagination.Ellipsis /></Pagination.Item>
<Pagination.Item><Pagination.Link>"10"</Pagination.Link></Pagination.Item>
<Pagination.Item>
<Pagination.Next>
<span>"Next"</span> <Pagination.Next_icon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>
sm
md
lg
pagination_sizes.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module For = Solidtype.For
module Pagination = Solidtype_heroui.Pagination
let total_pages = 3
let size_pagination (size, name) =
let page, set_page = S.create_signal 1 in
<div class_="flex flex-col gap-2">
<span class_="text-xs font-medium text-muted capitalize">
(fun () -> Jsx.string name)
</span>
<Pagination class_="justify-center" size=(fun () -> size)>
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous
is_disabled=(fun () -> S.get page = 1)
on_press=(fun () -> S.update set_page pred)>
<Pagination.Previous_icon /> <span>"Previous"</span>
</Pagination.Previous>
</Pagination.Item>
<For each=(fun () -> Array.init total_pages succ)>
(fun p _ ->
<Pagination.Item>
<Pagination.Link
is_active=(fun () -> p = S.get page)
on_press=(fun () -> S.set set_page p)>
(fun () -> Jsx.int p)
</Pagination.Link>
</Pagination.Item>)
</For>
<Pagination.Item>
<Pagination.Next
is_disabled=(fun () -> S.get page = total_pages)
on_press=(fun () -> S.update set_page succ)>
<span>"Next"</span> <Pagination.Next_icon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>
</div>
let make () =
<div class_="flex flex-col gap-6">
<For each=(fun () -> [| (`sm, "sm"); (`md, "md"); (`lg, "lg") |])>
(fun size _ -> size_pagination size)
</For>
</div>
pagination_disabled.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module For = Solidtype.For
module Pagination = Solidtype_heroui.Pagination
let total_pages = 3
let make () =
let page, set_page = S.create_signal 1 in
<Pagination class_="justify-center">
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous
is_disabled=true on_press=(fun () -> S.update set_page pred)>
<Pagination.Previous_icon /> <span>"Previous"</span>
</Pagination.Previous>
</Pagination.Item>
<For each=(fun () -> Array.init total_pages succ)>
(fun p _ ->
<Pagination.Item>
<Pagination.Link
is_active=(fun () -> p = S.get page)
on_press=(fun () -> S.set set_page p)>
(fun () -> Jsx.int p)
</Pagination.Link>
</Pagination.Item>)
</For>
<Pagination.Item>
<Pagination.Next
is_disabled=true on_press=(fun () -> S.update set_page succ)>
<span>"Next"</span> <Pagination.Next_icon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>
pagination_simple.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module Pagination = Solidtype_heroui.Pagination
let total_pages = 10
let items_per_page = 5
let total_items = 50
let make () =
let page, set_page = S.create_signal 1 in
let start_item () = ((S.get page - 1) * items_per_page) + 1 in
let end_item () = Int.min (S.get page * items_per_page) total_items in
<Pagination class_="w-full">
<Pagination.Summary>
(fun () -> Jsx.int (start_item ()))
" to "
(fun () -> Jsx.int (end_item ()))
" of "
(fun () -> Jsx.int total_items)
" invoices"
</Pagination.Summary>
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous
is_disabled=(fun () -> S.get page = 1)
on_press=(fun () -> S.update set_page pred)>
<Pagination.Previous_icon /> <span>"Prev"</span>
</Pagination.Previous>
</Pagination.Item>
<Pagination.Item>
<Pagination.Next
is_disabled=(fun () -> S.get page = total_pages)
on_press=(fun () -> S.update set_page succ)>
<span>"Next"</span> <Pagination.Next_icon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>
pagination_controlled.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module Index = Solidtype.Index
module Pagination = Solidtype_heroui.Pagination
type shown = Page of int | Ellipsis
let total_pages = 12
let items_per_page = 10
let total_items = 120
let page_numbers page =
if total_pages <= 7 then List.init total_pages (fun i -> Page (i + 1))
else
let start = Int.max 2 (page - 1) in
let stop = Int.min (total_pages - 1) (page + 1) in
[ Page 1 ]
@ (if page > 3 then [ Ellipsis ] else [])
@ List.init (stop - start + 1) (fun i -> Page (start + i))
@ (if page < total_pages - 2 then [ Ellipsis ] else [])
@ [ Page total_pages ]
let make () =
let page, set_page = S.create_signal 1 in
let start_item () = ((S.get page - 1) * items_per_page) + 1 in
let end_item () = Int.min (S.get page * items_per_page) total_items in
<Pagination>
<Pagination.Summary>
"Showing "
(fun () -> Jsx.int (start_item ()))
"-"
(fun () -> Jsx.int (end_item ()))
" of "
(fun () -> Jsx.int total_items)
" results"
</Pagination.Summary>
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous
is_disabled=(fun () -> S.get page = 1)
on_press=(fun () -> S.update set_page pred)>
<Pagination.Previous_icon /> <span>"Previous"</span>
</Pagination.Previous>
</Pagination.Item>
<Index each=(fun () -> Array.of_list (page_numbers (S.get page)))>
(fun shown _ ->
<Pagination.Item>
(fun () ->
match S.get shown with
| Ellipsis -> Jsx.element <Pagination.Ellipsis />
| Page p ->
Jsx.element
<Pagination.Link
is_active=(fun () -> p = S.get page)
on_press=(fun () -> S.set set_page p)>
(fun () -> Jsx.int p)
</Pagination.Link>)
</Pagination.Item>)
</Index>
<Pagination.Item>
<Pagination.Next
is_disabled=(fun () -> S.get page = total_pages)
on_press=(fun () -> S.update set_page succ)>
<span>"Next"</span> <Pagination.Next_icon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>
pagination_with_ellipsis.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module Index = Solidtype.Index
module Pagination = Solidtype_heroui.Pagination
type shown = Page of int | Ellipsis
let total_pages = 12
let page_numbers page =
let start = Int.max 2 (page - 1) in
let stop = Int.min (total_pages - 1) (page + 1) in
[ Page 1 ]
@ (if page > 3 then [ Ellipsis ] else [])
@ List.init (stop - start + 1) (fun i -> Page (start + i))
@ (if page < total_pages - 2 then [ Ellipsis ] else [])
@ [ Page total_pages ]
let make () =
let page, set_page = S.create_signal 1 in
<div class_="w-full max-w-2xs overflow-x-auto sm:max-w-full">
<Pagination class_="justify-center">
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous
is_disabled=(fun () -> S.get page = 1)
on_press=(fun () -> S.update set_page pred)>
<Pagination.Previous_icon /> <span>"Previous"</span>
</Pagination.Previous>
</Pagination.Item>
<Index each=(fun () -> Array.of_list (page_numbers (S.get page)))>
(fun shown _ ->
<Pagination.Item>
(fun () ->
match S.get shown with
| Ellipsis -> Jsx.element <Pagination.Ellipsis />
| Page p ->
Jsx.element
<Pagination.Link
is_active=(fun () -> p = S.get page)
on_press=(fun () -> S.set set_page p)>
(fun () -> Jsx.int p)
</Pagination.Link>)
</Pagination.Item>)
</Index>
<Pagination.Item>
<Pagination.Next
is_disabled=(fun () -> S.get page = total_pages)
on_press=(fun () -> S.update set_page succ)>
<span>"Next"</span> <Pagination.Next_icon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>
</div>
pagination_with_summary.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module Index = Solidtype.Index
module Pagination = Solidtype_heroui.Pagination
type shown = Page of int | Ellipsis
let total_pages = 12
let items_per_page = 10
let total_items = 120
let page_numbers page =
let start = Int.max 2 (page - 1) in
let stop = Int.min (total_pages - 1) (page + 1) in
[ Page 1 ]
@ (if page > 3 then [ Ellipsis ] else [])
@ List.init (stop - start + 1) (fun i -> Page (start + i))
@ (if page < total_pages - 2 then [ Ellipsis ] else [])
@ [ Page total_pages ]
let make () =
let page, set_page = S.create_signal 1 in
let start_item () = ((S.get page - 1) * items_per_page) + 1 in
let end_item () = Int.min (S.get page * items_per_page) total_items in
<Pagination class_="w-full">
<Pagination.Summary>
"Showing "
(fun () -> Jsx.int (start_item ()))
"-"
(fun () -> Jsx.int (end_item ()))
" of "
(fun () -> Jsx.int total_items)
" results"
</Pagination.Summary>
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous
is_disabled=(fun () -> S.get page = 1)
on_press=(fun () -> S.update set_page pred)>
<Pagination.Previous_icon /> <span>"Previous"</span>
</Pagination.Previous>
</Pagination.Item>
<Index each=(fun () -> Array.of_list (page_numbers (S.get page)))>
(fun shown _ ->
<Pagination.Item>
(fun () ->
match S.get shown with
| Ellipsis -> Jsx.element <Pagination.Ellipsis />
| Page p ->
Jsx.element
<Pagination.Link
is_active=(fun () -> p = S.get page)
on_press=(fun () -> S.set set_page p)>
(fun () -> Jsx.int p)
</Pagination.Link>)
</Pagination.Item>)
</Index>
<Pagination.Item>
<Pagination.Next
is_disabled=(fun () -> S.get page = total_pages)
on_press=(fun () -> S.update set_page succ)>
<span>"Next"</span> <Pagination.Next_icon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>

Previous_icon and Next_icon draw the icon they are given in place of HeroUI’s chevrons.

pagination_custom_icons.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module For = Solidtype.For
module Pagination = Solidtype_heroui.Pagination
let total_pages = 3
let make () =
let page, set_page = S.create_signal 1 in
<Pagination class_="justify-center">
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous
is_disabled=(fun () -> S.get page = 1)
on_press=(fun () -> S.update set_page pred)>
<Pagination.Previous_icon>
<Gravity.Arrow_left />
</Pagination.Previous_icon>
<span>"Back"</span>
</Pagination.Previous>
</Pagination.Item>
<For each=(fun () -> Array.init total_pages succ)>
(fun p _ ->
<Pagination.Item>
<Pagination.Link
is_active=(fun () -> p = S.get page)
on_press=(fun () -> S.set set_page p)>
(fun () -> Jsx.int p)
</Pagination.Link>
</Pagination.Item>)
</For>
<Pagination.Item>
<Pagination.Next
is_disabled=(fun () -> S.get page = total_pages)
on_press=(fun () -> S.update set_page succ)>
<span>"Forward"</span>
<Pagination.Next_icon><Gravity.Arrow_right /></Pagination.Next_icon>
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>

class_ is added after HeroUI’s classes.

pagination_tailwind.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module For = Solidtype.For
module Pagination = Solidtype_heroui.Pagination
let link_class = "text-muted hover:bg-surface hover:text-foreground"
let active_class = "bg-accent text-accent-foreground hover:bg-accent-hover"
let make () =
let page, set_page = S.create_signal 2 in
<Pagination class_="justify-center">
<Pagination.Content class_="gap-1 rounded-xl bg-default p-1">
<Pagination.Item>
<Pagination.Previous
class_=(fun () -> link_class)
is_disabled=(fun () -> S.get page = 1)
on_press=(fun () -> S.update set_page pred)>
<Pagination.Previous_icon />
</Pagination.Previous>
</Pagination.Item>
<For each=(fun () -> [| 1; 2; 3 |])>
(fun p _ ->
<Pagination.Item>
<Pagination.Link
class_=(fun () ->
if p = S.get page then active_class else link_class)
is_active=(fun () -> p = S.get page)
on_press=(fun () -> S.set set_page p)>
(fun () -> Jsx.int p)
</Pagination.Link>
</Pagination.Item>)
</For>
<Pagination.Item>
<Pagination.Next
class_=(fun () -> link_class)
is_disabled=(fun () -> S.get page = 3)
on_press=(fun () -> S.update set_page succ)>
<Pagination.Next_icon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>

HeroUI’s classes are global, so a stylesheet restyles every one, as with HeroUI in React:

@layer components {
.pagination {
@apply gap-8;
}
.pagination__link {
@apply rounded-md;
}
.pagination__summary {
@apply text-xs font-semibold;
}
}
  • .pagination, .pagination__summary, .pagination__content, .pagination__item, .pagination__link, .pagination__link--nav, .pagination__ellipsis
  • .pagination--sm, .pagination--md, .pagination--lg
  • Active page: [data-active="true"] or [aria-current="page"]
  • Hover: :hover or [data-hovered="true"]
  • Focus: :focus-visible or [data-focus-visible="true"]
  • Disabled: :disabled or [data-disabled="true"]
  • Pressed: :active or [data-pressed="true"]

Kobalte’s Pagination keeps the page and draws its own items from a count, which is not how HeroUI’s is used; HeroUI’s own is no pagination component of React Aria’s either, but parts and React Aria’s buttons. So the port is HeroUI’s parts, and its buttons Kobalte’s. A button disabled while it is hovered, pressed or focused – Next, pressed onto the last page – shows none of those, as React Aria’s does.

Each prop beside the name HeroUI’s React component gives it.

React solidtype Type Default Description
size size `sm | `md | `lg `md Size of its items
className class_ string Added after HeroUI’s classes
children children elements Its summary and content

Pagination.Summary, Pagination.Content, Pagination.Item

Section titled “Pagination.Summary, Pagination.Content, Pagination.Item”
React solidtype Type Description
className class_ string Added after HeroUI’s classes
children children elements What it holds
React solidtype Type Default Description
isActive is_active bool false Whether it is the page shown
isDisabled is_disabled bool false Whether it is disabled
onPress on_press unit -> unit Called as it is pressed
className class_ string Added after HeroUI’s classes
children children elements Its page’s number
React solidtype Type Default Description
isDisabled is_disabled bool false Whether it is disabled
onPress on_press unit -> unit Called as it is pressed
className class_ string Added after HeroUI’s classes
children children elements Its icon and label

Pagination.Previous_icon, Pagination.Next_icon

Section titled “Pagination.Previous_icon, Pagination.Next_icon”
React solidtype Type Description
className class_ string Its class
children children elements Its icon; HeroUI’s chevron when none is given
React solidtype Type Description
className class_ string Added after HeroUI’s class

Original HeroUI documentation: Pagination.

The same HeroUI Pagination twice, under the same props, each keeping its own page: in solidtype on the left, in React on the right. Below them, every attribute of each Next button: a marked row is one they disagree on, and a dimmed row is a framework’s own, which no style reads.

solidtype — OCaml, on Solid and Kobalte
React — TypeScript, on React Aria
attributesolidtypeReact