Nasaq
Components

Pagination

Numbered Pagination with ellipsis, CursorPager (previous/next with a "Showing X-Y" label) and LoadMore button with a loading state.

PreviewOpen ↗

Code

import { useState } from "react";import { Pagination } from "@fadymondy/nasaq/web";export function Results() {  const [page, setPage] = useState(1);  return <Pagination page={page} pageCount={24} onPageChange={setPage} />;}

Navigation · beta

Live examples and controls: Pagination in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/pagination.json

Three ways to move through a long list. Pagination shows numbered pages with ellipsis. CursorPager has previous and next only and a "Showing X-Y" label, for APIs that use cursors. LoadMore is a button that appends the next batch.

When to use

  • Pagination: the total is known and users jump to a page (tables, search results).
  • CursorPager: the API gives cursors and cannot jump.
  • LoadMore: feeds where continuing the list matters more than position.

When not to use

  • Fewer than about 20 items: show them all.
  • Steps in a flow: use a stepper.

Import

import { CursorPager, LoadMore, Pagination } from "@fadymondy/nasaq/web";

Quick start

import { useState } from "react";
import { Pagination } from "@fadymondy/nasaq/web";

export function Results() {
  const [page, setPage] = useState(1);
  return <Pagination page={page} pageCount={24} onPageChange={setPage} />;
}

Anatomy

<Pagination>   <nav data-slot="pagination" aria-label>
└─ ul > li     previous · page buttons (aria-current="page") · ellipsis (data-slot="pagination-ellipsis") · next
<CursorPager>  <nav data-slot="cursor-pager">  summary text + previous / next buttons
<LoadMore>     data-slot="load-more"  (a Button)

API

Pagination (PaginationProps)

PropTypeDefaultDescription
pagenumberrequiredCurrent page, 1-based.
pageCountnumberrequiredTotal pages.
onPageChange(page: number) => voidrequiredCalled with the new page.
siblingsnumber1Pages each side of the current one.
boundariesnumber1Pages always shown at each end.
labelstring"Pagination" / "ترقيم الصفحات"Landmark name.
previousLabel / nextLabelstring"Previous" / "Next" (Arabic by locale)Chevron button names.
pageLabel(formatted: string) => string"Page N" / "الصفحة N"Name of a page button.

getPaginationItems(page, pageCount, siblings?, boundaries?) returns (number | "start-ellipsis" | "end-ellipsis")[].

CursorPager (CursorPagerProps)

PropTypeDefaultDescription
from / tonumberrequiredFirst and last item index on this page.
totalnumbernoneTotal items when known.
hasPrevious / hasNextbooleanrequiredEnable the buttons.
onPrevious / onNext() => voidrequiredHandlers.
loadingbooleanfalseDisable both while fetching.
labelstring"Pagination" / "ترقيم الصفحات"Landmark name.
previousLabel / nextLabelReactNode"Previous" / "Next" (Arabic by locale)Button text.
summaryReactNode"Showing X-Y of Z"Replaces the summary.

LoadMore

All Button props (loading, variant, onClick). Default variant secondary, default text "Load more" / "تحميل المزيد".

Examples

Cursor pager:

import { CursorPager } from "@fadymondy/nasaq/web";

export function Pager() {
  return (
    <CursorPager from={21} to={40} total={95} hasPrevious hasNext onPrevious={() => {}} onNext={() => {}} />
  );
}

Load more with loading state:

import { useState } from "react";
import { LoadMore } from "@fadymondy/nasaq/web";

export function More() {
  const [loading, setLoading] = useState(false);
  return <LoadMore loading={loading} onClick={() => setLoading(true)} />;
}

Accessibility

KeyAction
TabMoves between buttons.
Enter / SpaceActivates.
  • Each control is a nav landmark with a label; the current page has aria-current="page". Page buttons are named "Page N".
  • Labels default to English or Arabic from the Nasaq locale; pass your own for other languages.

RTL & i18n

Chevrons are directional icons and mirror in RTL, so "previous" points right in Arabic. Page numbers and the "showing" range are formatted with Nasaq number formatting (Western digits) and the range is bidi-isolated.

Styling & tokens

Buttons use Button variants; the current page uses border-primary and bg-nq-selected. className merges onto the nav.

Do / Don't

  • Do keep the current page announced with aria-current.
  • Don't use it for fewer than a screenful of items.

button, data-table.

Lab

https://docs.nasaqui.com/?path=/docs/components-navigation-pagination--docs

On this page