{{!-- This is a react component --}}
/* No context defined. */
import React from 'react';
import { getPages } from './utils';
const Pager = props => {
const { page, total, onChange } = props;
const pages = getPages(page, total);
if (pages.length <= 1) return null;
const isPrevDisabled = page === 1;
const isNextDisabled = page === total;
const previous = (
<li key="prev" className={`pager__page pager__page--prev ${isPrevDisabled ? 'pager__page--disabled' : ''}`}>
<button
onClick={() => onChange(page - 1)}
className="pager__button"
disabled={isPrevDisabled}
title={'prev'}
>
{props.prevLabel}
<svg viewBox="0 0 320 202" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M70.356 82.67l56.762-56.641L101.217 0 0 101l101.217 101 25.901-26.029-56.762-56.64 249.644.183V82.853z" fillRule="nonzero"/></svg>
</button>
</li>
);
const next = (
<li key="next" className={`pager__page pager__page--next ${isNextDisabled ? 'pager__page--disabled' : ''}`}>
<button
onClick={() => onChange(page + 1)}
className="pager__button"
disabled={isNextDisabled}
title={'next'}
>
{props.nextLabel}
<svg viewBox="0 0 320 202" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M249.644 119.33l-56.762 56.641L218.783 202 320 101 218.783 0l-25.901 26.029 56.762 56.64L0 82.487v36.661z" fillRule="nonzero"/></svg>
</button>
</li>
);
return (
<ol className="pager">
{previous}
{pages.map(p => (
<li key={`${p.page}-${p.isEllipses ? 'ellipses' : ''}`} className={`pager__page ${p.isCurrent ? 'pager__page--current' : ''} ${p.isEllipses ? 'pager__page--ellipses' : ''}`}>
<button disabled={p.isCurrent} onClick={() => onChange(p.page)} className="pager__button">{p.isEllipses ? '...' : p.page}</button>
</li>
))}
{next}
</ol>
);
};
export default Pager;
.pager {
display: flex;
justify-content: center;
margin-left: auto;
margin-right: auto;
li {
display: inline;
font-size: 16px;
font-weight: 500;
vertical-align: middle;
&:not(:first-child) {
margin-left: 20px;
}
&:last-child {
margin-left: 30px;
}
@include mq(tablet) {
&:not(:first-child) {
margin-left: 28px;
}
&:last-child {
margin-left: 38px;
}
}
}
}
.pager__arrow {
color: map-get($theme-colors, 'primary');
}
.pager__page {
line-height: 12px;
}
.pager__button {
height: 30px;
width: 25px;
&:hover,
&:focus {
border-bottom: 1px solid map-get($theme-colors, 'primary');
color: map-get($theme-colors, 'primary');
cursor: pointer;
}
&:focus-visible {
outline: 1px solid map-get($theme-colors, 'primary');
outline-offset: 2px;
}
}
.pager__page--current {
.pager__button {
border-bottom: 2px solid map-get($theme-colors, 'primary');
color: map-get($theme-colors, 'primary');
cursor: default;
font-weight: 700;
}
}
.pager__page--prev {
margin-right: 15px;
}
.pager__page--prev,
.pager__page--next {
&:not(.pager__page--disabled) {
.pager__button {
&:hover,
&:focus {
border-bottom: 0;
}
.pager__arrow:hover {
color: map-get($theme-colors, 'primary');
}
.pager__arrow:focus {
outline: 1px solid;
outline-offset: 3px;
}
}
}
}
.pager__page--disabled {
.pager__arrow,
.pager__page {
color: rgba(map-get($theme-colors, 'primary-gray'), 0.5);
&:hover {
color: rgba(map-get($theme-colors, 'primary-gray'), 0.5);
}
}
.pager__button:hover {
border-bottom: 0;
color: rgba(map-get($theme-colors, 'primary-gray'), 0.5) !important;
cursor: default;
}
}
const getPageSpread = (pages, current) => {
const spreadPages = pages.map(page => ({
page,
isCurrent: current === page
}));
return spreadPages;
};
export const getPages = (current, total) => {
if (total <= 5) {
const items = Array.from(new Array(total).keys()).map(n => n + 1);
return getPageSpread(items, current);
}
if (current < 5) {
const items = Array.from(new Array(4).keys()).map(n => n + 1);
return [
...getPageSpread(items, current),
{ isEllipses: true, page: 5 },
...getPageSpread([total], current)
];
}
if (total > 5 && current >= total - 3) {
return [
...getPageSpread([1], current),
{ isEllipses: true, page: total - 4 },
...getPageSpread([total - 3, total - 2, total - 1, total], current)
];
}
if (total > 6 && current > 4) {
return [
...getPageSpread([1], current),
{ isEllipses: true, page: current - 2 },
...getPageSpread([current - 1, current, current + 1], current),
{ isEllipses: true, page: current + 2 },
...getPageSpread([total], current)
];
}
return [];
};
This is a react component. Mostly used in listings,
Add the front-end-copmonent library to your project
yarn add @verndale/front-end-components
Import the style to your main style file in your project
@import "../../node_modules/@verndale/front-end-components/lib/pager/styles";
Import the component like this with the following props
import Pager from "../../node_modules/@verndale/front-end-components/lib/pager/Pager";
<Pager
total={10}
page={1}
onChange={() => {}}
prevLabel="Previous"
nextLabel="Next"
/>