Components

Pagination

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.

Minerals

MineralColorLusterCrystal SystemCrystal Habit
Malachitegreenadamantinemonoclinicbotryoidal, stalactitic
Fluoritecolorlessvitreousisometriccoarse, 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.

NameTypeDefaultDescription
currentPagenumberrequired

The currently displayed page

messages

Various messages and labels used by Pagination (see example for more details)

onPageChangerequired

Called when current page is changed

onPageSizeChange

Called when page size is changed

pageSizenumberrequired

The number of items or data to be rendered on each page

pageSizesArray<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.

showPageJumperboolean

Render a page jumper (TextInput component); enables the user to change the current page on number entry

showPageNumbersbooleantrue

Hide the page number buttons

showPageSizerboolean

Render a page sizer (Select component); enables the user to select the page size

size'small' | 'medium' | 'large' | 'jumbo''medium'

Available sizes

totalCountnumberrequired

The total number of items or data to be paginated

visibleRangenumber5

The number of consecutive pages to be displayed when the paginated results are truncated (see example for details)

Undocumented properties, including as and css, will be applied to the root element.

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.

VariableValue
PaginationPageJumper_width4.65em
Pagination_gutterWidththeme.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.