Skip to main content
Gremorie
Navigation

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 ranges

Instalaçã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.

PropTypeDefaultDescription
...propsReact.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.

PropTypeDefaultDescription
...propsReact.ComponentProps<"ul">-Atributos padrão de ul.

<PaginationItem>

Renderiza um <li> simples. O envelopamento em lista é essencial para a semântica; não pule.

PropTypeDefaultDescription
...propsReact.ComponentProps<"li">-Atributos padrão de li.

O link de página clicável. Renderiza um <a> estilizado com buttonVariants de @gremorie/rx-forms.

PropTypeDefaultDescription
isActivebooleanfalseQuando 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.
...propsReact.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".

PropTypeDefaultDescription
...propsReact.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".

PropTypeDefaultDescription
...propsReact.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.

PropTypeDefaultDescription
...propsReact.ComponentProps<"span">-Atributos padrão de span.

Composição

  1. <Pagination> é o landmark nav com o label de paginação.
  2. <PaginationContent> é a lista de controles.
  3. <PaginationItem> envolve cada controle para que a lista leia como itens.
  4. Números de página usam <PaginationLink>, com a página atual passando isActive.
  5. As pontas usam <PaginationPrevious> e <PaginationNext>.
  6. 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 carrega role="navigation" e aria-label="pagination", expondo o conjunto de controles como um landmark descobrível.
  • Página atual: <PaginationLink isActive> define aria-current="page" para que leitores de tela anunciem a posição do usuário. Combine isActive com a variant outline (default) para uma pista visível.
  • Controles de ponta: <PaginationPrevious> e <PaginationNext> vêm com aria-label="Go to previous page" / "Go to next page". O label visível "Previous" / "Next" fica oculto abaixo do breakpoint sm, mas o aria-label mantém a tecnologia assistiva informada.
  • Ellipsis: <PaginationEllipsis> é aria-hidden e expõe um label "More pages" visualmente oculto.
  • Estados de limite: quem chama é responsável por aria-disabled="true" e tabIndex={-1} em prev / next na primeira e última páginas, além de uma classe pointer-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.

On this page