NavegaciónServer Component
Pagination
Anterior, números con «…» y siguiente. Con links de verdad o con botones.
import { Pagination } from "sebs7n-ui/pagination"Ejemplos
Con botones
Para una lista que se pagina sin cambiar de URL: `onPageChange` recibe la página destino.
import { Pagination } from "sebs7n-ui/pagination"
import { useState } from "react"
function ConBotones() {
const [page, setPage] = useState(1)
return (
<div className="flex w-full flex-col items-center gap-4">
<p className="text-callout text-label-secondary">Página {page} de 10</p>
<Pagination onPageChange={setPage} page={page} pageCount={10} />
</div>
)
}Con links
Si la página vive en la URL, `render`: son `<a>` de verdad, el crawler los ve y se abren en una pestaña nueva.
import Link from "next/link"
import { Pagination } from "sebs7n-ui/pagination"
function ConLinks() {
return (
<Pagination
page={4}
pageCount={12}
render={(page) => <Link href={`/docs/components/pagination?page=${page}`} scroll={false} />}
/>
)
}Muchas páginas y tamaño chico
El ancho no salta: cuando un «…» desaparece, lo reemplaza un número.
import { Pagination } from "sebs7n-ui/pagination"
import { useState } from "react"
function MuchasPaginas() {
const [page, setPage] = useState(50)
return <Pagination onPageChange={setPage} page={page} pageCount={100} size="sm" />
}Props
Generadas del TypeScript del paquete. Las propias del componente, más las heredadas del primitivo que tienen algo que explicar —marcadas «heredada de Base UI»—. El resto está en la línea «hereda de».
Pagination
Hereda las props de <nav>.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
page* | number | — | La página actual, en base 1. |
pageCount* | number | — | Cuántas páginas hay en total. Con 0, no se renderiza nada. |
aria-label | string | "Paginación" | Nombre accesible del elemento. |
boundaries | number | 1 | Cuántas páginas fijas en cada punta. El mínimo real es 1: un 0 se sube a 1, porque un paginador sin la página 1 a la vista no se puede usar. |
labels | PaginationLabels | — | Textos de la interfaz, para traducir o ajustar el tono. |
onPageChange | (page: number) => void | — | Modo botones: se llama con la página destino. |
render | (page: number) => RenderElement | — | Modo links: devuelve el elemento de cada página. Clona el elemento del llamador, así que sigue siendo un <a>. |
siblings | number | 1 | Cuántas páginas a cada lado de la actual. |
size | "sm" | "md" | "md" | sm 28px · md 36px (la escala de alto de los controles). |
className | string | — | Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
Teclado
- Tab
- Recorre los controles en el orden visual. Anterior y siguiente siguen tabulables en las puntas.
- Enter
- Va a esa página. En un control sin destino no hace nada.
Accesibilidad
- Es un
<nav aria-label="Paginación">con un<ul>: un lector anuncia «navegación, lista, 7 elementos». - Cada número tiene nombre accesible propio («Página 3»), no solo el dígito suelto.
- La página actual lleva
aria-current="page". - En las puntas, anterior y siguiente usan
aria-disabledy nodisabled: si se deshabilitaran, el foco se perdería justo después de hacer click. Es la misma decisión queButton loading. - El «…» es
role="presentation"con texto solo para lectores («Más páginas»). - Sin
"use client": en modo links los<a>salen en el HTML del server.
Reglas de uso
- Si la página vive en la URL, `render`:
render={(page) => <Link href={?page=${page}} />}. Son<a>de verdad, así que el crawler los ve, se abren en una pestaña nueva y se puede copiar el link. - `onPageChange` solo para una lista que se pagina sin cambiar de URL. Si al recargar volvés a la página 1, elegiste mal.
- Qué páginas mostrar es una función pura:
paginationRange(sebs7n-ui/lib/pagination). Si necesitás el mismo cálculo en otro lado —un resumen «4 de 27»—, llamala, no la copies. - El ancho no salta al cambiar de página: cuando un «…» desaparece, lo reemplaza un número.
- Para una lista infinita o un scroll continuo esto no sirve: hace falta saber cuántas páginas hay.