Skip to content
Esc
navigateopen⌘Jpreview
On this page

Pagination

Pagination with page navigation, next and previous links.

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

export default function PaginationDemo() {
  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>
  );
}

Install

npx shadcn@latest add @madeui/pagination

Usage

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

Composition

<Pagination>
  <PaginationContent>
    <PaginationItem>
      <PaginationPrevious />
    </PaginationItem>
    <PaginationItem>
      <PaginationLink />
    </PaginationItem>
    <PaginationItem>
      <PaginationEllipsis />
    </PaginationItem>
    <PaginationItem>
      <PaginationNext />
    </PaginationItem>
  </PaginationContent>
</Pagination>

Simple

Numbers only, no previous/next controls.

import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
} from '@/components/ui/pagination';

export default function PaginationSimple() {
  return (
    <Pagination>
      <PaginationContent>
        <PaginationItem>
          <PaginationLink href="#" isActive>
            1
          </PaginationLink>
        </PaginationItem>
        <PaginationItem>
          <PaginationLink href="#">2</PaginationLink>
        </PaginationItem>
        <PaginationItem>
          <PaginationLink href="#">3</PaginationLink>
        </PaginationItem>
      </PaginationContent>
    </Pagination>
  );
}

Icons only

Pass text="" to PaginationPrevious / PaginationNext to hide the label at every breakpoint — aria-label still carries the accessible name. size is fixed to md on both, so a style override squares up the padding for an icon-only look.

import * as stylex from '@stylexjs/stylex';

import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationNext,
  PaginationPrevious,
} from '@/components/ui/pagination';
import { space } from '@/lib/constants.stylex';

export default function PaginationIconsOnly() {
  return (
    <Pagination>
      <PaginationContent>
        <PaginationItem>
          <PaginationPrevious href="#" text="" style={styles.iconOnly} />
        </PaginationItem>
        <PaginationItem>
          <PaginationNext href="#" text="" style={styles.iconOnly} />
        </PaginationItem>
      </PaginationContent>
    </Pagination>
  );
}

const styles = stylex.create({
  iconOnly: {
    paddingInline: space.s2,
    width: space.s9,
  },
});

API reference

Plain semantic markup rendered through Button — links use Base UI’s render prop under the hood, so they are real <a> elements.

Prop Type Default Description
isActive boolean Renders as the outline button variant with aria-current="page".
size ButtonSize 'icon'
style StyleXStyles StyleX styles merged last — always win over the component’s own styles.

PaginationPrevious / PaginationNext

Prop Type Default Description
text string 'Previous' / 'Next' Label text; hidden below the sm breakpoint.

Both also accept all PaginationLink props except size.

Was this page helpful?