Pagination
Navegação página a página com bookmark. Nav semântica com previous, next, links de página e ellipsis.
Visão geral
Pagination é o primitivo de navegação página a página com bookmark: um <nav> envolvendo uma lista não ordenada de links <a> estilizados como botões. Cada página tem uma URL estável, a página ativa é marcada com aria-current="page", e os controles ao redor (Previous, Next, Ellipsis) compõem no clássico padrão 1...4 5 6 ...20.
Use o Pagination quando as URLs devem ser compartilháveis, a ordem estável importa, e os usuários precisam voltar a uma posição específica - resultados de busca, arquivos, logs de auditoria. Para feeds sem noção de "página 7" use scroll infinito ou load-more. O primitivo é intencionalmente headless quanto à matemática de páginas: ele não auto-detecta primeira ou última; quem chama conecta aria-disabled e click handlers nos links de prev / next.
Preview
'use client';import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious,} from '@gremorie/rx-navigation';export function PaginationPreview() { return ( <Pagination> <PaginationContent> <PaginationItem> <PaginationPrevious href="#" /> </PaginationItem> <PaginationItem> <PaginationLink href="#">1</PaginationLink> </PaginationItem> <PaginationItem> <PaginationLink href="#" isActive> 2 </PaginationLink> </PaginationItem> <PaginationItem> <PaginationLink href="#">3</PaginationLink> </PaginationItem> <PaginationItem> <PaginationEllipsis /> </PaginationItem> <PaginationItem> <PaginationNext href="#" /> </PaginationItem> </PaginationContent> </Pagination> );}Anatomia
Pagination <nav aria-label="pagination"> wrapper
└─ PaginationContent the <ul> row of controls
└─ PaginationItem one <li> cell wrapping a control
├─ PaginationLink page-number link; isActive marks the current page
├─ PaginationPrevious labelled previous-page control
├─ PaginationNext labelled next-page control
└─ PaginationEllipsis gap indicator for skipped page rangesInstalação
bash npx gremorie@latest add rx-pagination bash pnpm dlx gremorie@latest add rx-pagination bash yarn dlx gremorie@latest add rx-pagination bash bunx --bun gremorie@latest add rx-pagination
Uso
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationPrevious,
PaginationNext,
PaginationEllipsis,
} from "@gremorie/rx-navigation";
export function SearchPagination() {
return (
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="?page=1" />
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=1">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=2" isActive>
2
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=3">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationNext href="?page=3" />
</PaginationItem>
</PaginationContent>
</Pagination>
);
}A edição Angular deste componente hoje é distribuída a partir do source (veja o side-by-side no workbench); sua entrada no registry vem a seguir.
API
<Pagination>
Renderiza um <nav role="navigation" aria-label="pagination"> centrado no eixo da página.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<"nav"> | - | Atributos padrão de nav. Label e role são definidos automaticamente. |
<PaginationContent>
Renderiza um <ul> com flex flex-row items-center gap-1.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<"ul"> | - | Atributos padrão de ul. |
<PaginationItem>
Renderiza um <li> simples. O envelopamento em lista é essencial para a semântica; não pule.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<"li"> | - | Atributos padrão de li. |
<PaginationLink>
O link de página clicável. Renderiza um <a> estilizado com buttonVariants de @gremorie/rx-forms.
| Prop | Type | Default | Description |
|---|---|---|---|
isActive | boolean | false | Quando true, define aria-current="page" e troca a variant do botão para outline. Caso contrário renderiza como ghost. |
size | "default" | "sm" | "lg" | "icon" | "icon" | Encaminhado para o buttonVariants subjacente. Números de página usam "icon" por default para ficarem num grid quadrado. |
...props | React.ComponentProps<"a"> | - | Atributos padrão de âncora, incluindo href. |
<PaginationPrevious>
Wrapper de conveniência em torno de <PaginationLink> que renderiza um ChevronLeft mais um label "Previous" (o label fica oculto abaixo do breakpoint sm para manter o controle compacto no mobile). Define aria-label="Go to previous page" e size="default".
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof PaginationLink> | - | Mesma forma que PaginationLink. Passe href e quaisquer outros atributos de âncora. |
<PaginationNext>
Espelho de PaginationPrevious: label "Next" mais ChevronRight. Define aria-label="Go to next page" e size="default".
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof PaginationLink> | - | Mesma forma que PaginationLink. |
<PaginationEllipsis>
Renderiza um <span aria-hidden> quadrado contendo um ícone MoreHorizontal e um label "More pages" visualmente oculto.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<"span"> | - | Atributos padrão de span. |
Composição
<Pagination>é o landmark nav com o label de paginação.<PaginationContent>é a lista de controles.<PaginationItem>envolve cada controle para que a lista leia como itens.- Números de página usam
<PaginationLink>, com a página atual passandoisActive. - As pontas usam
<PaginationPrevious>e<PaginationNext>. - Gaps são visualizados com
<PaginationEllipsis>entre páginas não adjacentes.
O primitivo não é dono da matemática de páginas. Quem chama calcula quais números de página, ellipses e estados desabilitados renderizar com base em currentPage, totalPages e o tamanho de janela desejado.
Variações
Range simples
'use client';import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious,} from '@gremorie/rx-navigation';export function PaginationSimpleRangePreview() { return ( <Pagination> <PaginationContent> <PaginationItem> <PaginationPrevious href="#" /> </PaginationItem> <PaginationItem> <PaginationLink href="#">1</PaginationLink> </PaginationItem> <PaginationItem> <PaginationLink href="#" isActive> 2 </PaginationLink> </PaginationItem> <PaginationItem> <PaginationLink href="#">3</PaginationLink> </PaginationItem> <PaginationItem> <PaginationNext href="#" /> </PaginationItem> </PaginationContent> </Pagination> );}<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="?page=1" />
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=1">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=2" isActive>
2
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=3">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext href="?page=3" />
</PaginationItem>
</PaginationContent>
</Pagination>Use quando a contagem total de páginas cabe confortavelmente sem truncar (abaixo de dez).
Com ellipsis
'use client';import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious,} from '@gremorie/rx-navigation';export function PaginationWithEllipsisPreview() { return ( <Pagination> <PaginationContent> <PaginationItem> <PaginationPrevious href="#" /> </PaginationItem> <PaginationItem> <PaginationLink href="#">1</PaginationLink> </PaginationItem> <PaginationItem> <PaginationEllipsis /> </PaginationItem> <PaginationItem> <PaginationLink href="#">4</PaginationLink> </PaginationItem> <PaginationItem> <PaginationLink href="#" isActive> 5 </PaginationLink> </PaginationItem> <PaginationItem> <PaginationLink href="#">6</PaginationLink> </PaginationItem> <PaginationItem> <PaginationEllipsis /> </PaginationItem> <PaginationItem> <PaginationLink href="#">20</PaginationLink> </PaginationItem> <PaginationItem> <PaginationNext href="#" /> </PaginationItem> </PaginationContent> </Pagination> );}<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="?page=4" />
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=1">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=4">4</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=5" isActive>
5
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=6">6</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=20">20</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext href="?page=6" />
</PaginationItem>
</PaginationContent>
</Pagination>Use para ranges longos. Mantenha a primeira e a última ancoradas, mostre uma janela em torno da página atual e elida os gaps.
Pontas desabilitadas nos limites
'use client';import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious,} from '@gremorie/rx-navigation';export function PaginationDisabledEdgesPreview() { return ( <Pagination> <PaginationContent> <PaginationItem> <PaginationPrevious href="#" aria-disabled tabIndex={-1} className="pointer-events-none opacity-50" /> </PaginationItem> <PaginationItem> <PaginationLink href="#" isActive> 1 </PaginationLink> </PaginationItem> <PaginationItem> <PaginationLink href="#">2</PaginationLink> </PaginationItem> <PaginationItem> <PaginationLink href="#">3</PaginationLink> </PaginationItem> <PaginationItem> <PaginationNext href="#" /> </PaginationItem> </PaginationContent> </Pagination> );}<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious
href="#"
aria-disabled
tabIndex={-1}
className="pointer-events-none opacity-50"
/>
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=1" isActive>
1
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=2">2</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext href="?page=2" />
</PaginationItem>
</PaginationContent>
</Pagination>Use na página 1 (previous) ou na última página (next). O primitivo não auto-detecta limites - aplique aria-disabled, tabIndex={-1} e uma classe passiva na ponta afetada.
Acessibilidade
- Landmark: o
<nav>externo carregarole="navigation"earia-label="pagination", expondo o conjunto de controles como um landmark descobrível. - Página atual:
<PaginationLink isActive>definearia-current="page"para que leitores de tela anunciem a posição do usuário. CombineisActivecom a variantoutline(default) para uma pista visível. - Controles de ponta:
<PaginationPrevious>e<PaginationNext>vêm comaria-label="Go to previous page"/"Go to next page". O label visível "Previous" / "Next" fica oculto abaixo do breakpointsm, mas o aria-label mantém a tecnologia assistiva informada. - Ellipsis:
<PaginationEllipsis>éaria-hiddene expõe um label "More pages" visualmente oculto. - Estados de limite: quem chama é responsável por
aria-disabled="true"etabIndex={-1}em prev / next na primeira e última páginas, além de uma classepointer-events-none opacity-50(ou equivalente) para que o controle fique visivelmente inerte.
Relacionados
- Breadcrumb - trilha hierárquica, não navegação página a página.
- Tabs - content irmão dentro de um container.
- Button - a fonte de estilo subjacente via
buttonVariants.