Saltar al contenido principal

Pagination

Navegación entre páginas con enlaces anterior y siguiente, números y elipsis.

1'use client';
2
3import * as React from 'react';
4import { Pagination } from '@/components/ui/pagination';
5
6const TOTAL_PAGES = 8;
7
8function pageList(current: number): (number | 'ellipsis')[] {
9 const pages = new Set([1, TOTAL_PAGES, current - 1, current, current + 1]);
10 const sorted = [...pages]
11 .filter((page) => page >= 1 && page <= TOTAL_PAGES)
12 .sort((a, b) => a - b);
13
14 const result: (number | 'ellipsis')[] = [];
15 let previous = 0;
16 for (const page of sorted) {
17 if (page - previous > 1) result.push('ellipsis');
18 result.push(page);
19 previous = page;
20 }
21 return result;
22}
23
24export function Default() {
25 const [page, setPage] = React.useState(4);
26
27 return (
28 <Pagination>
29 <Pagination.Content className="flex-wrap justify-center">
30 <Pagination.Item>
31 <Pagination.Previous
32 disabled={page === 1}
33 onClick={() => setPage((current) => Math.max(1, current - 1))}
34 className="max-sm:w-9 max-sm:px-0 max-sm:[&>span]:sr-only"
35 />
36 </Pagination.Item>
37 {pageList(page).map((item, index) =>
38 item === 'ellipsis' ? (
39 <Pagination.Item key={`ellipsis-${index}`}>
40 <Pagination.Ellipsis />
41 </Pagination.Item>
42 ) : (
43 <Pagination.Item key={item}>
44 <Pagination.Link isActive={item === page} onClick={() => setPage(item)}>
45 {item}
46 </Pagination.Link>
47 </Pagination.Item>
48 ),
49 )}
50 <Pagination.Item>
51 <Pagination.Next
52 disabled={page === TOTAL_PAGES}
53 onClick={() => setPage((current) => Math.min(TOTAL_PAGES, current + 1))}
54 className="max-sm:w-9 max-sm:px-0 max-sm:[&>span]:sr-only"
55 />
56 </Pagination.Item>
57 </Pagination.Content>
58 </Pagination>
59 );
60}

Instalación

pnpm dlx nachui add pagination

Anatomía

1import { Pagination } from '@/components/ui/pagination';
1<Pagination>
2 <Pagination.Content>
3 <Pagination.Item>
4 <Pagination.Previous href="#">Anterior</Pagination.Previous>
5 </Pagination.Item>
6 <Pagination.Item>
7 <Pagination.Link href="#">1</Pagination.Link>
8 </Pagination.Item>
9 <Pagination.Item>
10 <Pagination.Link href="#" isActive>
11 2
12 </Pagination.Link>
13 </Pagination.Item>
14 <Pagination.Item>
15 <Pagination.Ellipsis />
16 </Pagination.Item>
17 <Pagination.Item>
18 <Pagination.Next href="#">Siguiente</Pagination.Next>
19 </Pagination.Item>
20 </Pagination.Content>
21</Pagination>
Pagination.Link renderiza un ancla cuando pasas href y un botón cuando lo omites, así el mismo markup sirve para páginas con rutas y para estado del cliente. Con Next.js, envuelve las partes de enlace o cambia el ancla por next/link en tu copia del componente.

Composición

Usa la siguiente composición para construir una Pagination:
Pagination
└── Pagination.Content
├── Pagination.Item
│ └── Pagination.Previous
├── Pagination.Item
│ └── Pagination.Link
├── Pagination.Item
│ └── Pagination.Ellipsis
└── Pagination.Item
└── Pagination.Next

Variantes

Compacta

Anterior y siguiente solo con iconos alrededor de un indicador de página, para barras de herramientas y espacios reducidos.
1'use client';
2
3import * as React from 'react';
4import { Pagination } from '@/components/ui/pagination';
5
6const TOTAL_PAGES = 12;
7
8export function Compact() {
9 const [page, setPage] = React.useState(3);
10
11 return (
12 <Pagination>
13 <Pagination.Content>
14 <Pagination.Item>
15 <Pagination.Previous
16 iconOnly
17 disabled={page === 1}
18 onClick={() => setPage((current) => Math.max(1, current - 1))}
19 />
20 </Pagination.Item>
21 <Pagination.Item>
22 <span className="text-muted-foreground px-2 text-sm tabular-nums">
23 Page {page} of {TOTAL_PAGES}
24 </span>
25 </Pagination.Item>
26 <Pagination.Item>
27 <Pagination.Next
28 iconOnly
29 disabled={page === TOTAL_PAGES}
30 onClick={() => setPage((current) => Math.min(TOTAL_PAGES, current + 1))}
31 />
32 </Pagination.Item>
33 </Pagination.Content>
34 </Pagination>
35 );
36}

Referencia de API

Pagination

PropTypeDefaultDescription
labelstring'Pagination'Nombre accesible del nav
classNamestring-Clases CSS adicionales
PropTypeDefaultDescription
hrefstring-Renderiza un ancla; omítelo para un botón
isActivebooleanfalseMarca la página actual con aria-current
disabledbooleanfalseDeshabilita el control
size'default' | 'icon''icon'Número cuadrado o enlace de texto con padding
classNamestring-Clases CSS adicionales

Pagination.Previous / Pagination.Next

PropTypeDefaultDescription
iconOnlybooleanfalseOculta visualmente la etiqueta
childrenReactNode'Previous' / 'Next'Texto de la etiqueta
Ambos aceptan además todas las props de Pagination.Link excepto size.

Pagination.Ellipsis

PropTypeDefaultDescription
labelstring'More pages'Texto para lectores de pantalla
classNamestring-Clases CSS adicionales
¿Encontraste algo que mejorar?

¿Notaste un error, tipografía o detalle faltante en esta página? Ayúdanos a mejorar la documentación abriendo un issue en GitHub.

Crear un Issue
Ctrl+I