Demo
Usage
Import the Pagination component. To use Pagination as an uncontrolled component, import the usePagination
hook and pass it an object including the following properties:
totalPages
(required)currentPage
(optional, defaults to1
)siblingCount
(optional, defaults to1
)hasMorePages
(optional)
import { Pagination, usePagination } from '@aws-amplify/ui-react';
export const DefaultPaginationExample = () => {
const paginationProps = usePagination({ totalPages: 8 });
return <Pagination {...paginationProps} />;
};
Controlled component
To use Pagination as a controlled component, you'll need to handle state using these callback functions:
onNext
: triggered when the next-page button>
is pressedonPrevious
: triggered when the previous-page button<
is pressedonChange
: triggered every time the page changes (e.g., when a page button is pressed directly)
import * as React from 'react';
import { Pagination } from '@aws-amplify/ui-react';
export const ControlledPaginationExample = () => {
const [currentPageIndex, setCurrentPageIndex] = React.useState(1);
const totalPages = 5;
const handleNextPage = () => {
console.log('handleNextPage');
setCurrentPageIndex(currentPageIndex + 1);
};
const handlePreviousPage = () => {
console.log('handlePreviousPage');
setCurrentPageIndex(currentPageIndex - 1);
};
const handleOnChange = (newPageIndex, prevPageIndex) => {
console.log(
`handleOnChange \n - newPageIndex: ${newPageIndex} \n - prevPageIndex: ${prevPageIndex}`
);
setCurrentPageIndex(newPageIndex);
};
return (
<Pagination
currentPage={currentPageIndex}
totalPages={totalPages}
onNext={handleNextPage}
onPrevious={handlePreviousPage}
onChange={handleOnChange}
/>
);
};
Paginating at an API level
It's common to use a paged API where the total number of pages in the dataset is unknown until you've reached the final page. To use the Pagination component in this scenario, set the totalPages
prop to the total pages of content loaded from the API so far, and set hasMorePages
initially to true
(which enables the next button to be clicked to trigger another API call). Update the totalPages
as you fetch more data. Once you reach the end of the data, set the hasMorePages
to false (and thus the Pagination component's next button will be disabled). See below for a contrived example:
import * as React from 'react';
import { Pagination } from '@aws-amplify/ui-react';
export const PaginationHasMorePagesExample = () => {
const [pageTokens, setPageTokens] = React.useState(['page2']);
const [currentPageIndex, setCurrentPageIndex] = React.useState(1);
const [hasMorePages, setHasMorePages] = React.useState(true);
const handleNextPage = async () => {
if (hasMorePages && currentPageIndex === pageTokens.length) {
const { nextToken } = await myAPI.fetch();
if (!nextToken) {
setHasMorePages(false);
}
setPageTokens([...pageTokens, nextToken]);
}
setCurrentPageIndex(currentPageIndex + 1);
};
return (
<Pagination
currentPage={currentPageIndex}
totalPages={pageTokens.length}
hasMorePages={hasMorePages}
onNext={handleNextPage}
onPrevious={() => setCurrentPageIndex(currentPageIndex - 1)}
onChange={(pageIndex) => setCurrentPageIndex(pageIndex)}
/>
);
};
const mockedAPI = () => {
const response = [
{
res: 'cat',
nextToken: 'page3',
},
{
res: 'parrot',
nextToken: null,
},
];
let timesCalled = 0;
return {
fetch() {
if (timesCalled < 2) {
return response[timesCalled++];
}
},
};
};
const myAPI = mockedAPI();
Sibling Count
siblingCount
is an optional prop which controls the number of pages displayed on each side of the current page (defaults to 1
). For example, in the demo below, notice how page 5 has two siblings to the left (3 and 4) and two siblings to the right (6 and 7).
import { Pagination, usePagination } from '@aws-amplify/ui-react';
export const PaginationSiblingCountExample = () => {
const paginationProps = usePagination({
totalPages: 11,
currentPage: 5,
siblingCount: 2,
});
return <Pagination {...paginationProps} />;
};
Accessibility
Accessible labels are provided for the Pagination buttons either via the aria-label
attribute or by using the VisuallyHidden primitive.
Use the following props to customize these labels:
-
previousLabel
: Set thearia-label
for the previous page button (defaults toGo to previous page
) -
nextLabel
: Set thearia-label
for the next page button (defaults toGo to next page
) -
currentPageLabel
: Set theVisuallyHidden
label for current page (defaults toPage
). This will be used to construct the label text for current page. e.g,Page: 1
if page1
is the current page. -
pageLabel
: Set the label for each page button other than the current page (defaults toGo to page
). This will be used to construct thearia-label
. e.g,Go to page 1
for page1
button.
By default, the root node of the Pagination component is a <nav>
element. Elements with the navigation role, like <nav>
, require unique labels if there are multiple on the same page. Passing an aria-label
to the Pagination component is one way to accomodate this.
import { usePagination, Pagination } from '@aws-amplify/ui-react';
export const PaginationAccessibilityExample = () => {
const paginationProps = usePagination({ totalPages: 5 });
return (
<Pagination
aria-label="Example pagination"
pageLabel="Jump to page"
currentPageLabel="You are on page"
previousLabel="Back to previous page"
nextLabel="Forward to next page"
{...paginationProps}
/>
);
};
Styling
Theme
You can customize the appearance of all Pagination components in your application with a Theme.
Pagination Theme Source
import {
Pagination,
usePagination,
ThemeProvider,
Theme,
} from '@aws-amplify/ui-react';
const theme: Theme = {
name: 'pagination-theme',
tokens: {
components: {
pagination: {
current: {
backgroundColor: { value: '{colors.secondary.80}' },
},
button: {
hover: {
backgroundColor: { value: '{colors.neutral.40}' },
color: { value: '{colors.secondary.80}' },
},
},
},
},
},
};
export const PaginationThemeExample = () => {
const paginationProps = usePagination({ totalPages: 6 });
return (
<ThemeProvider theme={theme} colorMode="light">
<Pagination {...paginationProps} />
</ThemeProvider>
);
};
Icons
import {
Pagination,
usePagination,
IconsProvider,
} from '@aws-amplify/ui-react';
import { FiArrowLeft, FiArrowRight } from 'react-icons/fi';
export const PaginationIconExample = () => {
const paginationProps = usePagination({ totalPages: 6 });
return (
<IconsProvider
icons={{
pagination: {
next: <FiArrowRight />,
previous: <FiArrowLeft />,
},
}}
>
<Pagination {...paginationProps} />
</IconsProvider>
);
};
Target classes
Class | Description |
---|---|
amplify-pagination | Top level element that wraps the Pagination primitive |
amplify-pagination__item | Class applied to the pagination items |
--amplify-components-pagination-button-color
--amplify-components-pagination-button-disabled-color
--amplify-components-pagination-button-hover-background-color
--amplify-components-pagination-button-hover-color
--amplify-components-pagination-button-padding-inline-end
--amplify-components-pagination-button-padding-inline-start
--amplify-components-pagination-button-transition-duration
--amplify-components-pagination-button-transition-property
--amplify-components-pagination-current-align-items
--amplify-components-pagination-current-background-color
--amplify-components-pagination-current-color
--amplify-components-pagination-current-font-size
--amplify-components-pagination-current-justify-content
--amplify-components-pagination-ellipsis-align-items
--amplify-components-pagination-ellipsis-justify-content
--amplify-components-pagination-ellipsis-padding-inline-end
--amplify-components-pagination-ellipsis-padding-inline-start
--amplify-components-pagination-item-container-margin-left
--amplify-components-pagination-item-container-margin-right
--amplify-components-pagination-item-shared-border-radius
--amplify-components-pagination-item-shared-height
--amplify-components-pagination-item-shared-min-width
Global styling
To override styling on all Pagination components, you can set the Amplify CSS variables or use the built-in .amplify-pagination
class.
/* styles.css */
.amplify-pagination {
--amplify-components-pagination-current-background-color: var(
--amplify-colors-red-60
);
}
import { Pagination, usePagination } from '@aws-amplify/ui-react';
import './styles.css';
const PaginationGlobalStylingExample = () => {
const paginationProps = usePagination({ totalPages: 8 });
return <Pagination {...paginationProps} />;
};
Local styling
To override styling on a specific Pagination component, you can use a class selector or style props.
Using a class selector:
/* styles.css */
.my-custom-pagination {
--amplify-components-pagination-current-background-color: var(
--amplify-colors-green-80
);
--amplify-components-pagination-button-hover-background-color: var(
--amplify-colors-blue-20
);
}
import { Pagination, usePagination } from '@aws-amplify/ui-react';
import './styles.css';
const PaginationClassStylingExample= () => {
const paginationProps = usePagination({ totalPages: 7 });
return <Pagination {...paginationProps} className="my-custom-pagination" />;
};
Using style props:
import { Pagination, usePagination } from '@aws-amplify/ui-react';
const PaginationStylePropsExample = () => {
const paginationProps = usePagination({ totalPages: 5 });
return <Pagination {...paginationProps} backgroundColor="lavender" padding="1rem" />;
};