HextaUI

Pagination

Seitennavigation, die jeden Button an seinem Platz hält, zur aktuellen Seite gleitet und über die Auslassungspunkte zu jeder Seite springt.

Showing 1–10 of 248 results

"use client"

import * as React from "react"

import { Pagination } from "@/components/ui/pagination"

const perPage = 10
const total = 248

export function PaginationDemo() {
  const [page, setPage] = React.useState(1)
  const first = (page - 1) * perPage + 1
  const last = Math.min(page * perPage, total)

  return (
    <div className="flex w-full flex-col items-center gap-4">
      <Pagination
        page={page}
        count={Math.ceil(total / perPage)}
        onPageChange={setPage}
      />
      <p className="text-sm text-muted-foreground tabular-nums">
        Showing {first}–{last} of {total} results
      </p>
    </div>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/pagination.json

Fügt die Komponente, die HextaUI-Theme-Tokens und alle HextaUI-Komponenten hinzu, von denen sie abhängt.

import { Pagination } from "@/components/ui/pagination"
const [page, setPage] = React.useState(1)

<Pagination page={page} count={25} onPageChange={setPage} />

Gib Pagination ein count, und es baut die ganze Leiste. Sie zeigt immer gleich viele Slots, sodass Previous, Next und die Zahlen beim Durchklicken nie unter deinem Cursor wandern. Lass count weg, um die Teile selbst zusammenzusetzen.

Pagination
└── PaginationContent
    ├── PaginationItem
    │   └── PaginationPrevious
    ├── PaginationItem
    │   └── PaginationLink
    ├── PaginationItem
    │   └── PaginationEllipsis
    └── PaginationItem
        └── PaginationNext

Zu einer Seite springen

Klicke auf eine Ellipse, um eine Seitenzahl einzugeben. Enter springt, eine Zahl außerhalb des Bereichs lässt das Feld wackeln, und Esc stellt die Ellipse wieder her. Schalte es mit jump={false} ab.

"use client"

import * as React from "react"

import { Pagination } from "@/components/ui/pagination"

export function PaginationLong() {
  const [page, setPage] = React.useState(480)

  return <Pagination page={page} count={1000} onPageChange={setPage} />
}

Kompakt

Passt die Leiste nicht in ihren Container, wechselt sie zu Previous, „Page 4 of 24“ und Next und wechselt zurück, sobald Platz ist. Das Label ist auch ein Sprungfeld. Erzwinge eines der Layouts mit compact.

"use client"

import * as React from "react"

import { Pagination } from "@/components/ui/pagination"

export function PaginationCompact() {
  const [page, setPage] = React.useState(4)

  return (
    <div className="w-full max-w-72 rounded-xl border p-2">
      <Pagination page={page} count={24} onPageChange={setPage} />
    </div>
  )
}

Mit getPageHref ist jede Seite ein echter Link, der sich in einem neuen Tab öffnen lässt. Normale Klicks rufen weiterhin onPageChange auf.

"use client"

import * as React from "react"

import { Pagination } from "@/components/ui/pagination"

export function PaginationLinks() {
  const [page, setPage] = React.useState(3)

  return (
    <Pagination
      page={page}
      count={12}
      getPageHref={(target) => `#page-${target}`}
      onPageChange={setPage}
    />
  )
}

Zusammensetzbar

Ohne count baust du die Leiste wie in shadcn/ui aus den Teilen. Übergib render, um den Link deines Routers zu nutzen.

"use client"

import * as React from "react"

import {
  Pagination,
  PaginationContent,
  PaginationEllipsis,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination"

const pages = [1, 2, 3]

export function PaginationComposable() {
  const [page, setPage] = React.useState(2)

  return (
    <Pagination>
      <PaginationContent>
        <PaginationItem>
          <PaginationPrevious
            render={<button type="button" />}
            disabled={page === 1}
            onClick={() => setPage(page - 1)}
          />
        </PaginationItem>
        {pages.map((item) => (
          <PaginationItem key={item}>
            <PaginationLink
              render={<button type="button" />}
              isActive={item === page}
              onClick={() => setPage(item)}
            >
              {item}
            </PaginationLink>
          </PaginationItem>
        ))}
        <PaginationItem>
          <PaginationEllipsis />
        </PaginationItem>
        <PaginationItem>
          <PaginationNext
            render={<button type="button" />}
            disabled={page === pages.length}
            onClick={() => setPage(page + 1)}
          />
        </PaginationItem>
      </PaginationContent>
    </Pagination>
  )
}

Rechts nach links

usePagination gibt die Seiten- und Ellipsen-Items für eigene Layouts zurück. Chevrons drehen sich in rechts-nach-links-Text um.

"use client"

import * as React from "react"

import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
  usePagination,
} from "@/components/ui/pagination"

export function PaginationRtl() {
  const [page, setPage] = React.useState(2)
  const { items, hasPrevious, hasNext } = usePagination({ page, count: 3 })

  return (
    <div dir="rtl">
      <Pagination aria-label="التنقل بين الصفحات">
        <PaginationContent>
          <PaginationItem>
            <PaginationPrevious
              text="السابق"
              aria-label="الصفحة السابقة"
              render={<button type="button" />}
              disabled={!hasPrevious}
              onClick={() => setPage(page - 1)}
            />
          </PaginationItem>
          {items.map((item) =>
            item.type === "page" ? (
              <PaginationItem key={item.page}>
                <PaginationLink
                  render={<button type="button" />}
                  isActive={item.page === page}
                  onClick={() => setPage(item.page)}
                >
                  {item.page.toLocaleString("ar-EG")}
                </PaginationLink>
              </PaginationItem>
            ) : null
          )}
          <PaginationItem>
            <PaginationNext
              text="التالي"
              aria-label="الصفحة التالية"
              render={<button type="button" />}
              disabled={!hasNext}
              onClick={() => setPage(page + 1)}
            />
          </PaginationItem>
        </PaginationContent>
      </Pagination>
    </div>
  )
}
TasteAktion
TabBewegt sich in die Leiste hinein und wieder hinaus. Previous und Next bleiben an den Enden fokussierbar.
←→Wechselt zwischen Previous, den Seiten und Next. Kehrt sich in rechts-nach-links-Layouts um.
HomeEndSpringt zum ersten oder letzten Eintrag.
EnterÖffnet die fokussierte Seite oder das Seitenfeld. Im Feld springt es zu dieser Seite und fokussiert sie.
EscSchließt das Seitenfeld und gibt den Fokus an die Ellipse zurück.
  • Das Root ist ein <nav> mit dem Label „Pagination“, und die aktuelle Seite hat aria-current="page".
  • Auf der ersten und letzten Seite nutzen Previous und Next aria-disabled statt disabled, damit der Fokus nicht verloren geht, wenn du das Ende erreichst.
  • Der gleitende Indikator wird bei reduzierter Bewegung zu einem Fade.
PropTypStandard
countGesamtzahl der Seiten. Wenn gesetzt, wird die Leiste für dich gebaut; lass es weg, um die Teile selbst zusammenzusetzen.
number–
page
number–
defaultPage
number1
onPageChange
(page: number) => void–
getPageHrefRendert Seiten als Links statt als Buttons.
(page: number) => string–
siblingsSeiten, die auf jeder Seite der aktuellen angezeigt werden.
number1
boundariesSeiten, die immer am Anfang und Ende angezeigt werden.
number1
compactauto wechselt zu Previous, „Page x of y“ und Next, wenn die Leiste nicht passt.
boolean | "auto""auto"
jumpLässt die Ellipse ein Seitenfeld öffnen.
booleantrue
AttributBeschreibung
data-slot="pagination"Die Navigation.
data-slot="pagination-indicator"Der Hintergrund, der zur aktuellen Seite gleitet.
PropTypStandard
isActiveMarkiert die aktuelle Seite mit aria-current="page".
booleanfalse
disabledSetzt aria-disabled und ignoriert Klicks.
booleanfalse
render
ReactElement | (props, state) => ReactElement<a>
AttributBeschreibung
data-slot="pagination-link"Seitenlinks per CSS ansprechen.
data-activeVorhanden auf der aktuellen Seite.
PropTypStandard
textÜbergib null für einen Button nur mit Icon.
ReactNode"Previous" / "Next"
disabled
booleanfalse
PropTypStandard
onJumpMacht die Ellipse zu einem Seitenfeld. Ohne das ist die Ellipse Dekoration.
(page: number) => void–
countDie höchste Seite, die das Feld akzeptiert.
number–
PropTypStandard
page
number–
count
number–
siblings
number1
boundaries
number1

Gibt items, die begrenzte page und count sowie hasPrevious und hasNext zurück. Wie du einen eigenen Pager baust, steht im usePagination-Guide.