From 329c48378a3c3ab55a0c9b90b745e834fd179f9b Mon Sep 17 00:00:00 2001 From: Grant Steffen Date: Mon, 11 Dec 2023 11:33:04 -0800 Subject: [PATCH 1/5] Add new pager display mode This adds a new pager display mode to customize what table data the pager shows --- docs/components/data/Pager.mdx | 5 +- src/data/Pager/Pager.module.css | 4 + src/data/Pager/Pager.story.tsx | 40 ++++++- src/data/Pager/Pager.tsx | 136 ++++++++++++++--------- src/data/Pager/assets/arrow-end.svg | 6 +- src/data/Pager/assets/arrow-next.svg | 6 +- src/data/Pager/assets/arrow-previous.svg | 6 +- src/data/Pager/assets/arrow-start.svg | 6 +- src/data/Pager/utils.ts | 12 ++ 9 files changed, 164 insertions(+), 57 deletions(-) diff --git a/docs/components/data/Pager.mdx b/docs/components/data/Pager.mdx index 4f60e24f..918ce9f8 100644 --- a/docs/components/data/Pager.mdx +++ b/docs/components/data/Pager.mdx @@ -6,9 +6,12 @@ import * as PagerStories from '../../../src/data/Pager/Pager.story' # Pager A simple pager for navigating between pages of data. You can customise the page navigation indicators (The pager arrows) if you want. +You can also change the `displayMode` to customize what table information the pager shows. ## Example - + + + ## API diff --git a/src/data/Pager/Pager.module.css b/src/data/Pager/Pager.module.css index ba328641..c4fa21e7 100644 --- a/src/data/Pager/Pager.module.css +++ b/src/data/Pager/Pager.module.css @@ -15,4 +15,8 @@ color: var(--input-color); } } + + .items { + margin-right: var(--spacing-sm); + } } diff --git a/src/data/Pager/Pager.story.tsx b/src/data/Pager/Pager.story.tsx index f58d54ea..9aa5d5f4 100644 --- a/src/data/Pager/Pager.story.tsx +++ b/src/data/Pager/Pager.story.tsx @@ -6,8 +6,44 @@ export default { component: Pager }; -export const Basic = () => { +export const ShowPages = () => { const [page, setPage] = useState(0); - return ; + return ( + + ); +}; + +export const ShowItems = () => { + const [page, setPage] = useState(0); + + return ( + + ); +}; + +export const ShowAll = () => { + const [page, setPage] = useState(0); + + return ( + + ); }; diff --git a/src/data/Pager/Pager.tsx b/src/data/Pager/Pager.tsx index c5988677..1f9858bf 100644 --- a/src/data/Pager/Pager.tsx +++ b/src/data/Pager/Pager.tsx @@ -1,13 +1,15 @@ import React, { FC, Fragment, ReactNode, useCallback } from 'react'; import classNames from 'classnames'; -import { Button } from '../../elements/Button'; -import { FUZZY_RANGE, getPageRange } from './utils'; -import { ReactComponent as PreviousArrow } from './assets/arrow-previous.svg'; +import { Button } from '../../elements/Button'; +import { Stack } from '../../layout'; +import { Text } from '../../typography'; +import { Pluralize } from '../Pluralize'; +import { ReactComponent as EndArrow } from './assets/arrow-end.svg'; import { ReactComponent as NextArrow } from './assets/arrow-next.svg'; +import { ReactComponent as PreviousArrow } from './assets/arrow-previous.svg'; import { ReactComponent as StartArrow } from './assets/arrow-start.svg'; -import { ReactComponent as EndArrow } from './assets/arrow-end.svg'; - +import { FUZZY_RANGE, getItemsRange, getPageRange } from './utils'; import css from './Pager.module.css'; export interface PagerProps { @@ -60,6 +62,11 @@ export interface PagerProps { * A callback function that is called when the page changes. */ onPageChange?: (page: number) => void; + + /** + * The type of table data for the pager to display. + */ + displayMode?: 'pages' | 'items' | 'all'; } export const Pager: FC = ({ @@ -72,12 +79,14 @@ export const Pager: FC = ({ endArrow, previousArrow, nextArrow, - onPageChange + onPageChange, + displayMode }) => { const pageCount = Math.ceil(total / size); const canPrevious = page !== 0; const canNext = page < pageCount - 1; const [startPage, endPage] = getPageRange(page, pageCount - 1); + const [startItem, endItem] = getItemsRange(page, size, total); const previousPage = useCallback(() => { if (canPrevious) { @@ -101,16 +110,36 @@ export const Pager: FC = ({ return (
- + {(displayMode === 'items' || displayMode === 'all') && ( +
+ {pageCount === 1 && total > 0 && ( + + Showing {total === 1 ? total : `all ${total.toLocaleString()}`}{' '} + + + )} + {pageCount > 1 && ( + + + {startItem.toLocaleString()}-{endItem.toLocaleString()} of{' '} + + + + )} +
+ )} + {startArrow && ( + + )} - {startPage >= 2 &&
 ...
} - {[...Array(pageCount)].map((_, i) => ( - - {i >= startPage && i <= endPage && ( - )} - onClick={() => onPageChange?.(i)} - > - {(i + 1).toLocaleString()} - + + ))} + {endPage <= pageCount - FUZZY_RANGE && ( +
... 
)} - - ))} - {endPage <= pageCount - FUZZY_RANGE && ( -
... 
+ )} - + {endArrow && ( + + )}
); }; @@ -175,5 +210,6 @@ Pager.defaultProps = { previousArrow: , nextArrow: , startArrow: , - endArrow: + endArrow: , + displayMode: 'pages' }; diff --git a/src/data/Pager/assets/arrow-end.svg b/src/data/Pager/assets/arrow-end.svg index c160b5b0..d90c00f0 100644 --- a/src/data/Pager/assets/arrow-end.svg +++ b/src/data/Pager/assets/arrow-end.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/src/data/Pager/assets/arrow-next.svg b/src/data/Pager/assets/arrow-next.svg index 134c8379..1409161d 100644 --- a/src/data/Pager/assets/arrow-next.svg +++ b/src/data/Pager/assets/arrow-next.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/src/data/Pager/assets/arrow-previous.svg b/src/data/Pager/assets/arrow-previous.svg index 3f4d0298..a5f879c4 100644 --- a/src/data/Pager/assets/arrow-previous.svg +++ b/src/data/Pager/assets/arrow-previous.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/src/data/Pager/assets/arrow-start.svg b/src/data/Pager/assets/arrow-start.svg index 82c4ec35..f9a1d38e 100644 --- a/src/data/Pager/assets/arrow-start.svg +++ b/src/data/Pager/assets/arrow-start.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/src/data/Pager/utils.ts b/src/data/Pager/utils.ts index 50d37a08..34c9690e 100644 --- a/src/data/Pager/utils.ts +++ b/src/data/Pager/utils.ts @@ -16,3 +16,15 @@ export function getPageRange(page: number, totalPages: number) { return [startPage, endPage]; } + +export function getItemsRange( + page: number, + perPage: number, + totalItems: number +) { + const startItem = page * perPage + 1; + const endOfPage = (page + 1) * perPage; + const endItem = Math.min(endOfPage, totalItems); + + return [startItem, endItem]; +} From ce1f428a5a2e73f19b8b4895d4889b4c96b375a0 Mon Sep 17 00:00:00 2001 From: Grant Steffen Date: Mon, 11 Dec 2023 13:01:57 -0800 Subject: [PATCH 2/5] Update pager styling --- src/data/Pager/Pager.module.css | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/data/Pager/Pager.module.css b/src/data/Pager/Pager.module.css index c4fa21e7..dd03a1b2 100644 --- a/src/data/Pager/Pager.module.css +++ b/src/data/Pager/Pager.module.css @@ -2,21 +2,21 @@ display: flex; align-items: center; justify-content: center; +} - svg { - height: 20px; - width: 20px; - } - - .page { - padding: 0 var(--spacing-sm); +svg { + height: 20px; + width: 20px; +} - &.active { - color: var(--input-color); - } - } +.page { + padding: 0 var(--spacing-sm); - .items { - margin-right: var(--spacing-sm); + &.active { + color: var(--input-color); } } +.items { + color: var(--gray-100); + margin-right: var(--spacing-sm); +} From bd4e67af54b89c907cd12f156659f68ae1c15706 Mon Sep 17 00:00:00 2001 From: Grant Steffen Date: Mon, 11 Dec 2023 13:06:01 -0800 Subject: [PATCH 3/5] Update pager styling --- src/data/Pager/Pager.module.css | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/data/Pager/Pager.module.css b/src/data/Pager/Pager.module.css index dd03a1b2..5bb376c0 100644 --- a/src/data/Pager/Pager.module.css +++ b/src/data/Pager/Pager.module.css @@ -2,6 +2,14 @@ display: flex; align-items: center; justify-content: center; + + .page { + padding: 0 var(--spacing-sm); + + &.active { + color: var(--input-color); + } + } } svg { @@ -9,13 +17,6 @@ svg { width: 20px; } -.page { - padding: 0 var(--spacing-sm); - - &.active { - color: var(--input-color); - } -} .items { color: var(--gray-100); margin-right: var(--spacing-sm); From 676cd6d48f942243b8daadbcc1d75b20ff5f10ac Mon Sep 17 00:00:00 2001 From: Grant Steffen Date: Mon, 11 Dec 2023 17:03:32 -0800 Subject: [PATCH 4/5] Add custom classname props --- src/data/Pager/Pager.module.css | 5 +++++ src/data/Pager/Pager.tsx | 20 +++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/data/Pager/Pager.module.css b/src/data/Pager/Pager.module.css index 5bb376c0..32512c7e 100644 --- a/src/data/Pager/Pager.module.css +++ b/src/data/Pager/Pager.module.css @@ -12,6 +12,11 @@ } } +.pagesContainer { + display: flex; + align-items: center; +} + svg { height: 20px; width: 20px; diff --git a/src/data/Pager/Pager.tsx b/src/data/Pager/Pager.tsx index 1f9858bf..e3d60f9c 100644 --- a/src/data/Pager/Pager.tsx +++ b/src/data/Pager/Pager.tsx @@ -23,6 +23,16 @@ export interface PagerProps { */ pageClassName?: string; + /** + * The class name for the active page button. + */ + activePageClassName?: string; + + /** + * The class name to add to the pages container. + */ + pagesContainerClassName?: string; + /** * The current page number. */ @@ -72,6 +82,8 @@ export interface PagerProps { export const Pager: FC = ({ className, pageClassName, + activePageClassName, + pagesContainerClassName, page, size, total, @@ -151,7 +163,9 @@ export const Pager: FC = ({ {previousArrow} {(displayMode === 'pages' || displayMode === 'all') && ( - <> +
{startPage >= 2 &&
 ...
} {[...Array(pageCount)].map((_, i) => ( @@ -164,7 +178,7 @@ export const Pager: FC = ({ className={classNames( css.page, { - [css.active]: page === i + [activePageClassName || css.active]: page === i }, pageClassName )} @@ -178,7 +192,7 @@ export const Pager: FC = ({ {endPage <= pageCount - FUZZY_RANGE && (
... 
)} - +
)}