Cursor Pager
- Stable
- WCAG 2.2 evidence
- RTL
A previous and next pair for data without stable page numbers, such as an activity log or a cursor API. A named nav landmark with two buttons (or links with previousHref and nextHref) and the context text
between them. At the first or last page the matching button is inactive through aria-disabled and stays in the tab
order, so keyboard focus is not lost when a press makes it inactive; presses are ignored (WCAG 2.1.1, 2.4.1, 2.4.3, 2.4.7,
4.1.2). The chevrons mirror in right-to-left layouts. Use Pagination where pages are numbered. Consumer duties: a unique landmark name, a context that names what the page shows, and moving focus to the new content
where that helps.
import { CursorPager } from "@nexera-ui/react";- 8
- examples
- 10
- props
- 1
- live controls
- 1
- platform
- 10
- WCAG criteria
- 1
- block uses it
Try every prop. Copy the code.
Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.
import { CursorPager } from "@nexera-ui/react";
<CursorPager />Examples 7
The same examples as Storybook, rendered live. Open Code to copy one.
First page
Figma State=First page: Previous is inactive (aria-disabled) but keeps focus.
import { CursorPager } from "@nexera-ui/react";
<CursorPager
aria-label="Activity"
context="Showing activity from 1 to 7 Oct"
status="first-page"
/>;
Last page
Figma State=Last page: Next is inactive.
import { CursorPager } from "@nexera-ui/react";
<CursorPager aria-label="Activity" context="Showing activity from 1 to 7 Oct" status="last-page" />;
Interactive
Wired to three pages of a log: pressing Next on the second page keeps focus on the button when it becomes inactive.
import { useState } from "react";
import { CursorPager } from "@nexera-ui/react";
const weeks = ["1 to 7 Oct", "8 to 14 Oct", "15 to 21 Oct"];
export function Interactive() {
function Log() {
const [index, setIndex] = useState(0);
return (
<CursorPager
aria-label="Activity (interactive)"
{...(index === 0
? { status: "first-page" as const }
: index === weeks.length - 1
? { status: "last-page" as const }
: {})}
context={`Showing activity from ${weeks[index] ?? ""}`}
onPrevious={() => {
setIndex(index - 1);
}}
onNext={() => {
setIndex(index + 1);
}}
/>
);
}
return <Log />;
}
As links
With previousHref and nextHref the buttons are links, for cursors that live in the address.
import { CursorPager } from "@nexera-ui/react";
<CursorPager
aria-label="Activity"
context="Showing activity from 1 to 7 Oct"
previousHref="#before"
nextHref="#after"
/>;
Narrow width
A 320 px column: the context sits above the two buttons, which share the row.
import { CursorPager } from "@nexera-ui/react";
export function NarrowWidth() {
return (
<div className="max-w-xs">
<CursorPager context="Showing activity from 1 to 7 Oct" aria-label="Activity (narrow)" />
</div>
);
}
Long labels
Long translated texts wrap and are never truncated.
import { CursorPager } from "@nexera-ui/react";
export function LongLabels() {
return (
<div className="max-w-sm">
<CursorPager
aria-label="Aktivitätsprotokoll"
context="Aktivitäten vom 1. bis 7. Oktober aus allen Teams und Standorten"
previousLabel="Frühere Einträge"
nextLabel="Spätere Einträge"
/>
</div>
);
}
Right to left
Right to left: Previous is at the right and the chevrons mirror.
import { CursorPager } from "@nexera-ui/react";
export function RightToLeft() {
return (
<CursorPager
aria-label="النشاط"
context="عرض النشاط من ١ إلى ٧ أكتوبر"
previousLabel="السابق"
nextLabel="التالي"
/>
);
}
Props 10
Press "Try it" on a card to load that prop into the playground.
10 props shown
statusNexera"first-page" | "last-page"Where the user is. first-page makes Previous inactive and last-page
makes Next inactive; leave it out for a page in the middle. A list with a single page needs no pager.
contextNexeraReactNodeText that says what the current page shows.
With buttons, a string context is announced politely when it changes, because the new page replaces the content in
place (WCAG 4.1.3).
onPreviousNexera() => voidCalled when Previous is pressed (button mode).
onNextNexera() => voidCalled when Next is pressed (button mode).
previousHrefNexerastringMakes Previous a link, for cursors that live in the address (?before=…). Nothing is announced: navigation announces itself.
nextHrefNexerastringMakes Next a link.
previousLabelNexerastringVisible text and name of the previous button. Translate it.
nextLabelNexerastringVisible text and name of the next button. Translate it.
aria-labelNexerastringAccessible name of the pagination landmark, for example "Employees". Say what is paged: a page with several nav
landmarks needs a unique name for each. Translate it.
Accessible name when it must differ from the visible text.
aria-labelledbyNexerastringId(s) of visible element(s) that name the landmark; wins over aria-label.
Id(s) of visible element(s) that name the landmark, for example the heading of the table.
* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.
Accessible by default.
Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.
WCAG 2.2 evidence
7 direct · 3 supporting- 1.3.1Info and RelationshipsLevel A · tested directly
- 1.3.2Meaningful SequenceLevel A · supporting test
- 1.4.10ReflowLevel AA · supporting test
- 1.4.12Text SpacingLevel AA · supporting test
- 2.1.1KeyboardLevel A · tested directly
- 2.4.1Bypass BlocksLevel A · tested directly
- 2.4.3Focus OrderLevel A · tested directly
- 2.4.4Link Purpose (In Context)Level A · tested directly
- 4.1.2Name, Role, ValueLevel A · tested directly
- 4.1.3Status MessagesLevel AA · tested directly
Fits any width.
Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.
Styling hooks
Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.
<CursorPager className="shadow-sm" />Used in blocks
Related components
- BreadcrumbShows where the current page sits in the hierarchy and links back to each level.
- BreadcrumbItemOne level of a `Breadcrumb` trail; use it only inside `Breadcrumb`.
- FABThe main action of a mobile screen: a floating button with a `nav/active-bg` fill and a large shadow.
- FeedStatusThe status line at the bottom of an infinite feed or a lazy list: "Loading more", "You have reached the end" or "Could not load more" with a retry action.
- JumpToPageA small "Go to page [48] of 120" control for long paged lists.
- NavigationBarThe bottom bar of a mobile layout: a named `nav` landmark with a list of three to five `NavItem`s.
- NavItemOne destination or action of a `NavigationBar`.
- PageButtonOne page number of a `Pagination` or `TableFooter`.