EXEPERTAI LAB

Research alpha

Time Machine
EXEPERTAI LAB
GALLERY / COLLECTION
← Browse Astryx gallery
Table·hook·@astryxdesign/core

useTablePagination

Headless pagination plugin for Table. Call with a config object: `useTablePagination({ page, onPageChange, totalItems })`. Returns a TablePlugin to pass to `<Table plugins={{ pagination: paginationPlugin }} />`.

Open in Playground @astryxdesign/core/Table

Signature

Call shape
useTablePagination()

Showcases and examples

1 documented example

Table — Paginated Data

Paginated data table navigating through a larger dataset page by page.

Preview loads on approachPreview loads on approach
Exact source · table-paginated-table
// Copyright (c) Meta Platforms, Inc. and affiliates.

'use client';

import {useState} from 'react';
import {
  Table,
  useTablePagination,
  paginateData,
  proportional,
} from '@astryxdesign/core/Table';
import type {TableColumn} from '@astryxdesign/core/Table';
import {Section} from '@astryxdesign/core/Section';

interface User extends Record<string, unknown> {
  id: string;
  name: string;
  email: string;
  role: string;
}

const names = [
  'Alice Johnson',
  'Bob Smith',
  'Charlie Brown',
  'Diana Prince',
  'Eve Davis',
  'Frank Miller',
  'Grace Lee',
  'Hank Wilson',
  'Ivy Chen',
  'Jack Turner',
  'Karen White',
  'Leo Garcia',
  'Mia Thompson',
  'Noah Martinez',
  'Olivia Clark',
  'Paul Harris',
  'Quinn Walker',
  'Rachel Adams',
  'Sam Robinson',
  'Tina Scott',
];

const roles = ['Engineer', 'Designer', 'Manager', 'Admin', 'Analyst'];

const users: User[] = names.map((name, i) => ({
  id: String(i + 1),
  name,
  email: `${name.split(' ')[0].toLowerCase()}@example.com`,
  role: roles[i % roles.length],
}));

const columns: TableColumn<User>[] = [
  {key: 'name', header: 'Name', width: proportional(1)},
  {key: 'email', header: 'Email', width: proportional(2)},
  {key: 'role', header: 'Role', width: proportional(1)},
];

export default function TablePaginatedTable() {
  const [page, setPage] = useState(1);
  const pageSize = 5;

  const plugin = useTablePagination<User>({
    page,
    onPageChange: setPage,
    totalItems: users.length,
    pageSize,
  });

  return (
    <Section>
      <Table
        data={paginateData(users, page, pageSize)}
        columns={columns}
        idKey="id"
        plugins={{pagination: plugin}}
      />
    </Section>
  );
}

Usage

Call useTablePagination with a config object containing page state and callback. Pass the returned plugin to Table via the plugins prop.

Typed props

PropType and behavior
pagenumber · required
Current page number (1-based).
onPageChange(page: number) => void · required
Called when the page changes.
totalItemsnumber
Total number of items across all pages. Used to calculate total page count.
totalPagesnumber
Total number of pages. Use when you know the page count but not item count.
hasMoreboolean
Whether more pages exist. Use for cursor-based pagination where the total is unknown.
pageSizenumber · default 10
Number of items per page.
onPageSizeChange(pageSize: number) => void
Called when the user changes the page size. Shows a page size dropdown when provided with pageSizeOptions.
pageSizeOptionsnumber[]
Available page size options. Shows a page size selector when provided.
variant'pages' | 'count' | 'compact' | 'dots' | 'none' · default 'pages'
Visual variant for the pagination controls.
position'below' | 'above' | 'both' | 'none' · default 'below'
Where to render pagination controls relative to the table.
align'start' | 'center' | 'end' · default 'center'
Horizontal alignment of the pagination controls.
labelstring · default 'Table pagination'
Accessible name for the pagination nav landmark. With position='both' the two navs get distinct names (the label suffixed as '(top)' and '(bottom)') so same-type landmarks stay unique (axe landmark-unique).