Skip to content
This repository was archived by the owner on Jun 19, 2021. It is now read-only.

Commit 08ec1f5

Browse files
committedJan 24, 2021
Enable pagination to only show first pages
1 parent a350147 commit 08ec1f5

File tree

4 files changed

+102
-32
lines changed

4 files changed

+102
-32
lines changed
 

‎components/__tests__/pagination.test.tsx ‎components/pagination/__tests__/pagination.test.tsx

+54-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { render, screen } from '@testing-library/react'
22
import userEvent from '@testing-library/user-event'
33

4-
import { Pagination } from '../pagination'
4+
import { Pagination } from '..'
55

66
const handlePageChange = jest.fn()
77

@@ -119,3 +119,56 @@ test.each(invalidPageCombos)(
119119
expect(container).toBeEmptyDOMElement()
120120
}
121121
)
122+
123+
/* eslint-disable no-magic-numbers -- defining the magic numbers*/
124+
// current, pageCount, surroundCurrent = 1, expectedButtons, number of separators
125+
const startOnlyCombos: PageCombo[] = [
126+
[1, 10, undefined, [1, 2, 'Next'], 0],
127+
[4, 10, undefined, ['Previous', 1, 3, 4, 5, 'Next'], 1],
128+
[4, 4, undefined, ['Previous', 1, 3, 4], 1],
129+
[2, 3, undefined, ['Previous', 1, 2, 3, 'Next'], 0],
130+
[1, 11, 2, [1, 2, 3, 'Next'], 0],
131+
[4, 11, 2, ['Previous', 1, 2, 3, 4, 5, 6, 'Next'], 0],
132+
[5, 5, 2, ['Previous', 1, 3, 4, 5], 1],
133+
]
134+
/* eslint-enable no-magic-numbers -- defining the magic numbers*/
135+
136+
test.each(startOnlyCombos)(
137+
'correct buttons are shown. current: "%s", pageCount: "%s", surroundCurrent: "%s", startOnly: "true"',
138+
(current, pageCount, surroundCurrent, shownButtons) => {
139+
render(
140+
<Pagination
141+
current={current}
142+
pageCount={pageCount}
143+
surroundCurrent={surroundCurrent}
144+
onPageChange={handlePageChange}
145+
startOnly
146+
/>
147+
)
148+
const buttons = screen.getAllByRole('button')
149+
expect(buttons).toHaveLength(shownButtons.length)
150+
for (const button of buttons) {
151+
const content = button.textContent
152+
if (content === 'Previous' || content === 'Next')
153+
expect(shownButtons.includes(content)).toBeTruthy()
154+
else if (content) expect(shownButtons.includes(parseInt(content))).toBeTruthy()
155+
else expect(false).toBeTruthy()
156+
}
157+
}
158+
)
159+
160+
test.each(startOnlyCombos)(
161+
'correct separators are shown. current: "%s", pageCount: "%s", surroundCurrent: "%s", startOnly: "true"',
162+
(current, pageCount, surroundCurrent, _, separatorCount) => {
163+
render(
164+
<Pagination
165+
current={current}
166+
pageCount={pageCount}
167+
surroundCurrent={surroundCurrent}
168+
onPageChange={handlePageChange}
169+
startOnly
170+
/>
171+
)
172+
expect(screen.queryAllByText('…')).toHaveLength(separatorCount)
173+
}
174+
)

‎components/pagination.tsx ‎components/pagination/index.tsx

+18-31
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Fragment, useCallback } from 'react'
22

3-
import { Button } from '../elements/button'
4-
import { ChevronLeft, ChevronRight } from '../elements/icon'
5-
import { Text } from '../elements/text'
3+
import { Button } from '../../elements/button'
4+
import { ChevronLeft, ChevronRight } from '../../elements/icon'
5+
import { PaginationButton } from './pagination-button'
6+
import { PaginationSeparator } from './pagination-separator'
67

78
type Align = 'left' | 'right' | 'center'
89

@@ -13,44 +14,22 @@ type Props = {
1314
surroundCurrent?: number
1415
onPageChange: (newPage: number) => void
1516
align?: Align
17+
startOnly?: boolean
1618
}
1719

18-
type PaginationButtonProps = {
19-
value: number
20-
active: boolean
21-
onClick: (newPage: number) => void
22-
}
23-
24-
const PaginationButton = ({ value, active, onClick }: PaginationButtonProps) => {
25-
const handleClick = useCallback(() => {
26-
onClick(value)
27-
}, [onClick, value])
28-
return (
29-
<Button
30-
value={String(value)}
31-
size='small'
32-
style={active ? 'filled' : 'outlined'}
33-
color={active ? 'primary' : 'default'}
34-
square
35-
onClick={handleClick}
36-
/>
37-
)
38-
}
39-
40-
const Separator = () => <Text color='text-gray'></Text>
41-
4220
type MiddleButtonProps = {
4321
current: number
4422
pageCount: number
4523
surroundCurrent: number
4624
onPageChange: (newPage: number) => void
25+
startOnly: boolean
4726
}
4827

4928
const getMiddleButtons = (props: MiddleButtonProps): JSX.Element[] => {
5029
const middleButtons: JSX.Element[] = []
5130
const lowerPadding = props.current - 2
5231
const upperPadding = props.pageCount - props.current - 1
53-
if (lowerPadding > props.surroundCurrent) middleButtons.push(<Separator />)
32+
if (lowerPadding > props.surroundCurrent) middleButtons.push(<PaginationSeparator />)
5433
const middleStartIndex = Math.max(props.current - props.surroundCurrent, 2)
5534
for (let index = middleStartIndex; index < props.current; index++) {
5635
middleButtons.push(
@@ -86,7 +65,8 @@ const getMiddleButtons = (props: MiddleButtonProps): JSX.Element[] => {
8665
)
8766
}
8867

89-
if (upperPadding > props.surroundCurrent) middleButtons.push(<Separator />)
68+
if (upperPadding > props.surroundCurrent && !props.startOnly)
69+
middleButtons.push(<PaginationSeparator />)
9070

9171
return middleButtons
9272
}
@@ -108,8 +88,15 @@ export const Pagination = ({
10888
onPageChange,
10989
surroundCurrent = 1,
11090
align = 'center',
91+
startOnly = false,
11192
}: Props): JSX.Element => {
112-
const middleButtons = getMiddleButtons({ current, pageCount, onPageChange, surroundCurrent })
93+
const middleButtons = getMiddleButtons({
94+
current,
95+
pageCount,
96+
onPageChange,
97+
surroundCurrent,
98+
startOnly,
99+
})
113100
const handleGoToStart = useCallback(() => onPageChange(current - 1), [current, onPageChange])
114101
const handleGoToEnd = useCallback(() => onPageChange(current + 1), [current, onPageChange])
115102

@@ -138,7 +125,7 @@ export const Pagination = ({
138125
{middleButtons.map((button, index) => {
139126
return <Fragment key={index}>{button}</Fragment>
140127
})}
141-
{pageCount !== 1 && (
128+
{pageCount !== 1 && (!startOnly || pageCount - current - 1 < surroundCurrent) && (
142129
<PaginationButton
143130
value={pageCount}
144131
active={current === pageCount}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { useCallback } from 'react'
2+
3+
import { Button } from '../../elements/button'
4+
5+
type Props = {
6+
value: number
7+
active: boolean
8+
onClick: (newPage: number) => void
9+
}
10+
11+
export const PaginationButton = ({ value, active, onClick }: Props): JSX.Element => {
12+
const handleClick = useCallback(() => {
13+
onClick(value)
14+
}, [onClick, value])
15+
return (
16+
<Button
17+
value={String(value)}
18+
size='small'
19+
style={active ? 'filled' : 'outlined'}
20+
color={active ? 'primary' : 'default'}
21+
square
22+
onClick={handleClick}
23+
/>
24+
)
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Text } from '../../elements/text'
2+
3+
export const PaginationSeparator = (): JSX.Element => {
4+
return <Text color='text-gray'></Text>
5+
}

0 commit comments

Comments
 (0)