Pagination offers a means to control the space consumed by a large data set or other collection of items by limiting the page size and providing navigation for access to all pages.
Examples #
Import Syntax #
import Pagination from 'mineral-ui/Pagination';
Basic Usage #
Pass Pagination a currentPage
to render, an onPageChange
handler, a pageSize
(number of items to be rendered), and the totalCount
of the items to be paginated. The total number of pages is calculated from the
total count and the page size.
() => { class Paginated extends Component { constructor(props) { super(props); this.state = { currentPage: 1 }; this.handlePageChange = this.handlePageChange.bind(this); } handlePageChange(currentPage) { this.setState({ currentPage }); } render() { const { currentPage } = this.state; return ( <Pagination currentPage={currentPage} onPageChange={this.handlePageChange} pageSize={10} totalCount={100} /> ); } } return <Paginated />; }
Previous & Next #
Render only the Previous and Next buttons by passing false
to the showPageNumbers
prop.
() => { class Paginated extends Component { constructor(props) { super(props); this.state = { currentPage: 1 }; this.handlePageChange = this.handlePageChange.bind(this); } handlePageChange(currentPage) { this.setState({ currentPage }); } render() { const { currentPage } = this.state; return ( <Pagination showPageNumbers={false} currentPage={currentPage} onPageChange={this.handlePageChange} pageSize={10} totalCount={100} /> ); } } return <Paginated />; }
Visible Range #
The width of the page navigation can be controlled with the
visibleRange
prop. The value represents the length of the range to be
displayed between ellipses when the full range of pages is truncated. The value
should be an odd number, by nature of the design.
() => { const visibleRange = 3 class Paginated extends Component { constructor(props) { super(props); this.state = { currentPage: 5 }; this.handlePageChange = this.handlePageChange.bind(this); } handlePageChange(currentPage) { this.setState({ currentPage }) } render() { const { currentPage } = this.state; return ( <Pagination visibleRange={visibleRange} currentPage={currentPage} onPageChange={this.handlePageChange} pageSize={10} totalCount={100} {...this.props} />); } } return <Paginated />; }
Sizes #
The controls within Pagination can be rendered in various sizes.
() => { const sizes = ['small', 'medium', 'large', 'jumbo'] class Paginated extends Component { constructor(props) { super(props); this.state = { currentPage: 1 }; this.handlePageChange = this.handlePageChange.bind(this); } handlePageChange(currentPage) { this.setState({ currentPage }); } render() { const { currentPage } = this.state; const { size } = this.props return ( <Pagination size={size} currentPage={currentPage} onPageChange={this.handlePageChange} pageSize={10} totalCount={100} /> ); } } return ( <DemoLayout> {sizes.map((size) => { return <Paginated size={size} key={size} /> })} </DemoLayout> ) }
Page Jumper #
Allow users to jump to any page with the showPageJumper
prop.
The caption and placeholder can be defined via the messages
prop (see the
bidirectionality example for details). The width of the input can be
adjusted with the component theme.
() => { class Paginated extends Component { constructor(props) { super(props); this.state = { currentPage: 1 }; this.handlePageChange = this.handlePageChange.bind(this); } handlePageChange(currentPage) { this.setState({ currentPage }) } render() { const { currentPage } = this.state; return ( <Pagination showPageJumper currentPage={currentPage} onPageChange={this.handlePageChange} pageSize={10} totalCount={100} /> ); } } return <Paginated />; }
Page Sizer #
Allow users to select the page size with the showPageSizer
prop. A custom collection of optional page sizes can be provided with the
pageSizes
prop. The category descriptor (e.g. "minerals", below) within the
caption can be modified with the messages.category
prop. The full caption
and item description can be defined via the messages
prop (see the
bidirectionality example for details).
The example below paginates a Table, but this approach applies to any collection of items.
Mineral | Color | Luster | Crystal System | Crystal Habit |
---|---|---|---|---|
Malachite | green | adamantine | monoclinic | botryoidal, stalactitic |
Fluorite | colorless | vitreous | isometric | coarse, granular |
() => { const pageSizes = [2, 3, 4]; const category = 'minerals'; class PaginatedTable extends Component { constructor(props) { super(props); this.state = { currentPage: 1, pageSize: pageSizes[0] }; this.handlePageChange = this.handlePageChange.bind(this); this.handlePageSizeChange = this.handlePageSizeChange.bind(this); } handlePageChange(currentPage) { this.setState({ currentPage }); } handlePageSizeChange(pageSize) { this.setState({ pageSize }); } render() { const { currentPage, pageSize } = this.state; const firstRow = (currentPage - 1) * pageSize; const lastRow = (currentPage - 1) * pageSize + pageSize; const slicedData = this.props.data.slice(firstRow, lastRow); return ( <DemoLayout> <Table data={slicedData} rowKey="name" columns={columns} title="Minerals" hideTitle /> <Pagination showPageSizer pageSize={pageSize} pageSizes={pageSizes} onPageSizeChange={this.handlePageSizeChange} messages={{ category }} currentPage={currentPage} onPageChange={this.handlePageChange} totalCount={data.length} /> </DemoLayout> ); } } return <PaginatedTable data={data} />; }
Bidirectionality #
When the direction
theme variable is set to rtl
(right-to-left), alignment and page order are reversed for Pagination. The
messages
prop allows customization of various messages — both those that are
displayed, and those that are announced by assistive technologies.
معدني | اللون | بريق | نظام الكريستال | الكريستال العادة |
---|---|---|---|---|
الملكيت | الخضر المختلفة | الأسمنت المسلح | أحادي الميلان | إبري |
الفلوريت معدن متبلور | عديم اللون | زجاجي | متساوي القياس | عقدي |
المغنتيت | أسود | معدني | متساوي القياس | ثماني السطوح |
() => { const pageSizes = [2, 3, 4]; const itemText = (pageSize) => pageSize + ' لكل صفحة'; const status = (category, first, last, total) => first + '–' + last + ' من ' + total + ' ' + category; const pageLabel = (isCurrentPage, isLastPage, page) => page + (isCurrentPage ? ', الصفحه الحاليه' : '') + (isLastPage ? ', آخر صفحة' : ''); const messages = { category: 'المعادن', label: 'ترقيم الصفحات', pages: { pageLabel, next: 'التالى', previous: 'سابق' }, pageJumper: { label: 'اذهب الى الصفحة', placeholder: 'صفحة #' }, pageSizer: { status, itemText } }; class PaginatedTable extends Component { constructor(props) { super(props); this.state = { currentPage: 1, pageSize: pageSizes[1] }; this.handlePageChange = this.handlePageChange.bind(this); this.handlePageSizeChange = this.handlePageSizeChange.bind(this); } handlePageChange(currentPage) { this.setState({ currentPage }); } handlePageSizeChange(pageSize) { this.setState({ pageSize }); } render() { const { currentPage, pageSize } = this.state; const firstRow = (currentPage - 1) * pageSize; const lastRow = (currentPage - 1) * pageSize + pageSize; const slicedData = this.props.data.slice(firstRow, lastRow); return ( <div dir="rtl"> <ThemeProvider theme={{ direction: 'rtl' }}> <DemoLayout> <Table data={slicedData} rowKey="اسم" columns={columns} title="المعادن" hideTitle /> <Pagination rtl messages={messages} currentPage={currentPage} onPageSizeChange={this.handlePageSizeChange} onPageChange={this.handlePageChange} showPageJumper showPageSizer pageSize={pageSize} pageSizes={pageSizes} totalCount={data.length} /> </DemoLayout> </ThemeProvider> </div> ); } } return <PaginatedTable data={data} />; }
API & Theme #
Pagination Props #
The Pagination component takes the following React props.
Name | Type | Default | Description |
---|---|---|---|
currentPage | number | required | The currently displayed page |
messages | Various messages and labels used by Pagination (see example for more details) | ||
onPageChange | required | Called when current page is changed | |
onPageSizeChange | Called when page size is changed | ||
pageSize | number | required | The number of items or data to be rendered on each page |
pageSizes | Array<number> | [10, 20, 50] | A collection of possible page sizes for a user to select from; implemented in page sizer. Be sure to provide unique values. |
showPageJumper | boolean | Render a page jumper (TextInput component); enables the user to change the current page on number entry | |
showPageNumbers | boolean | true | Hide the page number buttons |
showPageSizer | boolean | Render a page sizer (Select component); enables the user to select the page size | |
size | 'small' | 'medium' | 'large' | 'jumbo' | 'medium' | Available sizes |
totalCount | number | required | The total number of items or data to be paginated |
visibleRange | number | 5 | The number of consecutive pages to be displayed when the paginated results are truncated (see example for details) |
Pagination Theme Variables #
These variables can be used as hooks to override this component's
style at either a
local
or global
level. The theme
referenced below is whatever theme is available
from props to the instance of this component.
Variable | Value |
---|---|
PaginationPageJumper_width | 4.65em |
Pagination_gutterWidth | theme.space_inline_sm |
Usage #
When/How to Use #
Pagination improves user experience with a large data set or other collection of items by distributing it across multiple pages, decreasing the vertical space consumed and load/render times. It is most useful when implemented in conjunction with tables and lists, such as search results and directories.
Pagination is best placed below the data or items it paginates. However, if pages have variable heights (i.e. items on the page have different heights), then you may consider placing it above, instead.
If the remainder of data or items on the final page does not match the page size, it is recommended to add empty rows or items in order to maintain the same vertical space as the other pages.
Best Practices #
Use showPageJumper
if pagination results are truncated so
that users can easily navigate to hidden pages.
For narrow layouts, prevent page numbers from wrapping by
decreasing the visibleRange
or using
showPageNumbers
to display only Previous & Next buttons.
Hide Pagination if there is only one resulting page to avoid confusion.