Pagination
Navegação entre páginas de uma tabela ou listagem, com reticências e botões Anterior/Próxima.
'use client';
import * as React from 'react';
import { Pagination } from '@/components/ui/pagination';
export default function PaginationDemo() {
const [page, setPage] = React.useState(1);
return <Pagination page={page} totalPages={12} onPageChange={setPage} />;
}Instalação
npx shadcn@latest add @lenstech/paginationUso
import { Pagination } from "@/components/ui/pagination"const [page, setPage] = React.useState(1)
<Pagination page={page} totalPages={12} onPageChange={setPage} />Componente controlado
A paginação não guarda estado nem corta os dados: você informa page e totalPages e atualiza a página
em onPageChange. As páginas começam em 1.
Exemplos
Páginas vizinhas
siblingCount define quantas páginas aparecem de cada lado da atual. Primeira e última estão sempre visíveis.
siblingCount=0 (compacto)
siblingCount=2
'use client';
import * as React from 'react';
import { Pagination } from '@/components/ui/pagination';
export default function PaginationSiblings() {
const [page, setPage] = React.useState(10);
return (
<div className="flex flex-col items-center gap-6">
<div className="flex flex-col items-center gap-2">
<p className="text-sm text-muted-foreground">siblingCount=0 (compacto)</p>
<Pagination page={page} totalPages={20} onPageChange={setPage} siblingCount={0} />
</div>
<div className="flex flex-col items-center gap-2">
<p className="text-sm text-muted-foreground">siblingCount=2</p>
<Pagination page={page} totalPages={20} onPageChange={setPage} siblingCount={2} />
</div>
</div>
);
}Somente ícones
Com showLabels={false} os textos "Anterior" e "Próxima" somem (em telas pequenas isso já acontece automaticamente).
'use client';
import * as React from 'react';
import { Pagination } from '@/components/ui/pagination';
export default function PaginationIcons() {
const [page, setPage] = React.useState(3);
return <Pagination page={page} totalPages={8} onPageChange={setPage} showLabels={false} />;
}Com uma lista
Corte os dados com slice a partir da página atual e mostre o contexto ("Página 2 de 3") ao lado.
- Como escolher um domínio para sua empresa
- 5 erros comuns em sites de clínicas
- Google Meu Negócio: guia completo
- Quanto custa um site profissional em 2026?
Página 1 de 3
'use client';
import * as React from 'react';
import { Pagination } from '@/components/ui/pagination';
const posts = [
'Como escolher um domínio para sua empresa',
'5 erros comuns em sites de clínicas',
'Google Meu Negócio: guia completo',
'Quanto custa um site profissional em 2026?',
'WhatsApp no site: vale a pena?',
'Landing page ou site institucional?',
'SEO local para pequenos negócios',
'Como medir os resultados do seu site',
'Fotos profissionais fazem diferença?',
'Checklist antes de publicar o site',
'O que é LGPD e como afeta seu site',
];
const PAGE_SIZE = 4;
export default function PaginationList() {
const [page, setPage] = React.useState(1);
const totalPages = Math.ceil(posts.length / PAGE_SIZE);
const visible = posts.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
return (
<div className="flex w-full max-w-md flex-col gap-4">
<ul className="flex flex-col divide-y rounded-md border">
{visible.map((title) => (
<li key={title} className="px-4 py-3 text-sm">
{title}
</li>
))}
</ul>
<div className="flex items-center justify-between gap-3">
<p className="text-sm text-muted-foreground tabular-nums">
Página {page} de {totalPages}
</p>
<Pagination
page={page}
totalPages={totalPages}
onPageChange={setPage}
showLabels={false}
className="mx-0 w-auto justify-end"
/>
</div>
</div>
);
}Quando usar
- Use em tabelas e listagens longas: contatos, pedidos, posts do blog.
- Não use para poucos itens (cabem numa tela) — mostre tudo.
- Não use em feeds contínuos — prefira "Carregar mais" ou rolagem infinita.
- Para tabela com busca e paginação prontas, use o bloco Data Table.
API
Pagination
Aceita as props de um <nav> HTML, mais:
Prop
Type
getPaginationRange
Função auxiliar exportada que calcula os itens exibidos — útil para montar uma paginação com visual próprio.
getPaginationRange(6, 12) // [1, "ellipsis-start", 5, 6, 7, "ellipsis-end", 12]