Components

Pagination

A navigation component for moving between pages of content in lists and tables. Mirrors the DataTable pagination — chevron-only Previous / Next buttons and compact numbered page buttons.

Installation

npm install @marmoui/ui
yarn add @marmoui/ui
pnpm add @marmoui/ui
bun add @marmoui/ui

Usage

import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationPrevious,
  PaginationNext,
  PaginationEllipsis,
} from '@marmoui/ui';

Examples

Basic pager

PaginationPrevious / PaginationNext are button components (not anchors). They take the standard button props — onClick, disabled, type. Page links use PaginationLink with isActive to mark the current page.

Numbered page buttons + chevron prev/next

The default rendering. Identical in style to the pager used inside DataTable.

<Pagination>
<PaginationContent>
  <PaginationItem>
    <PaginationPrevious onClick={() => goTo(page - 1)} disabled={page === 1} />
  </PaginationItem>
  <PaginationItem>
    <PaginationLink isActive>1</PaginationLink>
  </PaginationItem>
  <PaginationItem>
    <PaginationLink onClick={() => goTo(2)}>2</PaginationLink>
  </PaginationItem>
  <PaginationItem>
    <PaginationLink onClick={() => goTo(3)}>3</PaginationLink>
  </PaginationItem>
  <PaginationItem>
    <PaginationEllipsis />
  </PaginationItem>
  <PaginationItem>
    <PaginationLink onClick={() => goTo(10)}>10</PaginationLink>
  </PaginationItem>
  <PaginationItem>
    <PaginationNext onClick={() => goTo(page + 1)} disabled={page === 10} />
  </PaginationItem>
</PaginationContent>
</Pagination>

For paginated table or list tiles, pass Pagination into the Widget footer slot. The widget renders the pager on its own row with a top border, matching the DataTable pagination row.

<Widget
  title="Top Countries"
  footer={
    <Pagination>
      <PaginationContent>
        <PaginationItem>
          <PaginationPrevious
            onClick={() => goTo(page - 1)}
            disabled={page === 1}
          />
        </PaginationItem>
        {pages.map((n) => (
          <PaginationItem key={n}>
            <PaginationLink
              isActive={n === page}
              onClick={() => goTo(n)}
            >
              {n}
            </PaginationLink>
          </PaginationItem>
        ))}
        <PaginationItem>
          <PaginationNext
            onClick={() => goTo(page + 1)}
            disabled={page === pageCount}
          />
        </PaginationItem>
      </PaginationContent>
    </Pagination>
  }
>
  <table>{/* … */}</table>
</Widget>

The parent owns the page state and slices the data — the pager itself is presentational. For larger / sortable / filterable tables, prefer DataTable, which ships a page-size selector together with this same Pagination.

Best Practices

Show current page

Always set isActive on the current page link.

Disable at boundaries

Pass disabled to PaginationPrevious on page 1 and to PaginationNext on the last page — the underlying IconButton handles the muted style.

Don't show too many pages

Use PaginationEllipsis for large page ranges. Show 5–7 page links maximum.

Don't use for single-page content

Only render Pagination when there are at least two pages.

Props

Props

Accessibility

  • Uses nav element with aria-label="pagination".
  • Current page is indicated with aria-current="page".
  • PaginationPrevious and PaginationNext are real <button> elements via IconButton with explicit aria-labels.
  • disabled removes pointer events and dims the trigger.
  • Keyboard navigable with Tab.