Skip to content

Commit

Permalink
feat: migrate Pagination
Browse files Browse the repository at this point in the history
Signed-off-by: Théo Mesnil <[email protected]>
  • Loading branch information
theo-mesnil committed Jun 28, 2023
1 parent 2ec933b commit 07b490c
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 53 deletions.
3 changes: 1 addition & 2 deletions packages/Pagination/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@
"dependencies": {
"@welcome-ui/icons": "^5.0.0-alpha.40",
"@welcome-ui/system": "^5.0.0-alpha.40",
"@welcome-ui/utils": "^5.0.0-alpha.37",
"reakit": "^1.3.11"
"@welcome-ui/utils": "^5.0.0-alpha.37"
},
"peerDependencies": {
"@xstyled/styled-components": "^3.7.3",
Expand Down
84 changes: 36 additions & 48 deletions packages/Pagination/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useCallback, useRef } from 'react'
import { Rover, RoverInitialState, useRoverState } from 'reakit'
import { LeftIcon, RightIcon } from '@welcome-ui/icons'
import { CreateWuiProps, forwardRef } from '@welcome-ui/system'

Expand All @@ -15,7 +14,6 @@ export interface PaginationOptions {
pageCount: number
rangeDisplay?: number
rightArrow?: React.ReactElement
baseId?: RoverInitialState['baseId']
}

export type PaginationProps = CreateWuiProps<'ul', PaginationOptions>
Expand All @@ -24,7 +22,6 @@ export const Pagination = forwardRef<'ul', PaginationProps>(
(
{
'aria-label': ariaLabel,
baseId,
dataTestId,
getHref,
leftArrow,
Expand All @@ -37,10 +34,12 @@ export const Pagination = forwardRef<'ul', PaginationProps>(
},
ref
) => {
const rover = useRoverState({ baseId })
const pages = usePages({ page, pageCount, rangeDisplay })
const firstPageRef = useRef<HTMLButtonElement>(null)
const lastPageRef = useRef<HTMLButtonElement>(null)
const firstPageRef = useRef<HTMLAnchorElement>(null)
const lastPageRef = useRef<HTMLAnchorElement>(null)
const isPrevButtonDisabled = page === 1
const isNextButtonDisabled = page === pageCount

const handlePrevious = useCallback(
(event: React.MouseEvent) => {
event.preventDefault()
Expand All @@ -52,6 +51,7 @@ export const Pagination = forwardRef<'ul', PaginationProps>(
},
[page, onChange]
)

const handleNext = useCallback(
(event: React.MouseEvent) => {
event.preventDefault()
Expand All @@ -74,18 +74,16 @@ export const Pagination = forwardRef<'ul', PaginationProps>(
>
<S.List>
<S.Item>
<Rover as={undefined} disabled={page === 1} {...rover}>
{roverProps => (
<S.ArrowLink
{...roverProps}
href={getHref && getHref(page - 1)}
isDisabled={page === 1}
onClick={handlePrevious}
>
{leftArrow || <LeftIcon size="sm" />}
</S.ArrowLink>
)}
</Rover>
<S.ArrowLink
aria-disabled={isPrevButtonDisabled}
data-testid={dataTestId ? `${dataTestId}-arrow-prev` : undefined}
href={!isPrevButtonDisabled && getHref ? getHref(page - 1) : ''}
isDisabled={isPrevButtonDisabled}
onClick={!isPrevButtonDisabled ? handlePrevious : undefined}
ref={firstPageRef}
>
{leftArrow || <LeftIcon size="sm" />}
</S.ArrowLink>
</S.Item>
{pages.map((iPage: string | number, i: number) =>
iPage === '-' ? (
Expand All @@ -95,41 +93,31 @@ export const Pagination = forwardRef<'ul', PaginationProps>(
</S.Item>
) : (
<S.Item key={iPage}>
<Rover
as={undefined}
ref={iPage === 1 ? firstPageRef : iPage === pageCount ? lastPageRef : null}
{...rover}
<S.PageLink
aria-current={iPage === page}
data-testid={dataTestId ? `${dataTestId}-${iPage}` : undefined}
href={getHref ? getHref(iPage) : ''}
onClick={event => {
event.preventDefault()
onChange(iPage)
}}
>
{roverProps => (
<S.PageLink
{...roverProps}
aria-current={iPage === page}
href={getHref && getHref(iPage)}
onClick={event => {
event.preventDefault()
onChange(iPage)
}}
>
{iPage}
</S.PageLink>
)}
</Rover>
{iPage}
</S.PageLink>
</S.Item>
)
)}
<S.Item>
<Rover as={undefined} disabled={page === pageCount} {...rover}>
{roverProps => (
<S.ArrowLink
{...roverProps}
href={getHref && getHref(page + 1)}
isDisabled={page === pageCount}
onClick={handleNext}
>
{rightArrow || <RightIcon size="sm" />}
</S.ArrowLink>
)}
</Rover>
<S.ArrowLink
aria-disabled={isNextButtonDisabled}
data-testid={dataTestId ? `${dataTestId}-arrow-next` : undefined}
href={!isNextButtonDisabled && getHref ? getHref(page + 1) : ''}
isDisabled={isNextButtonDisabled}
onClick={!isNextButtonDisabled ? handleNext : undefined}
ref={lastPageRef}
>
{rightArrow || <RightIcon size="sm" />}
</S.ArrowLink>
</S.Item>
</S.List>
</S.Pagination>
Expand Down
8 changes: 5 additions & 3 deletions packages/Pagination/src/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const Dots = styled.span`
align-items: center;
`

export const AbstractLink = styled.a`
export const abstractLinkStyle = css`
${th('paginations.default')};
${th('paginations.item')};
border-radius: 50%;
Expand All @@ -47,8 +47,9 @@ export const AbstractLink = styled.a`
}
`

export const ArrowLink = styled(AbstractLink)<{ isDisabled: boolean }>(
export const ArrowLink = styled.a<{ isDisabled: boolean }>(
({ isDisabled }) => css`
${abstractLinkStyle};
${isDisabled &&
css`
color: nude-700;
Expand All @@ -57,8 +58,9 @@ export const ArrowLink = styled(AbstractLink)<{ isDisabled: boolean }>(
`
)

export const PageLink = styled(AbstractLink)(
export const PageLink = styled.a(
props => css`
${abstractLinkStyle};
${props['aria-current'] && th('paginations.active')}
`
)
97 changes: 97 additions & 0 deletions packages/Pagination/tests/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from 'react'
import { fireEvent, screen } from '@testing-library/react'
import { renderHook } from '@testing-library/react-hooks'

import { render } from '../../../utils/tests'
import { Pagination } from '../src'
import { usePages } from '../src/utils'

describe('<Pagination>', () => {
it('should render correctly', () => {
const onChange = jest.fn()

render(
<Pagination
aria-label="pagination"
dataTestId="pagination"
onChange={onChange}
page={1}
pageCount={10}
/>
)

const prevButton = screen.getByTestId('pagination-arrow-prev')
const nextButton = screen.getByTestId('pagination-arrow-next')
const currentPage = screen.getByText('1')
const nextPage = screen.getByText('2')

expect(prevButton).toHaveAttribute('aria-disabled', 'true')
expect(nextButton).toHaveAttribute('aria-disabled', 'false')
expect(currentPage).toHaveAttribute('aria-current', 'true')
expect(nextPage).toHaveAttribute('aria-current', 'false')

/** Click on next button */
fireEvent.click(nextButton)

expect(onChange).toHaveBeenCalledWith(2)

/** Click on a page 3 button */
fireEvent.click(screen.getByText('3'))

expect(onChange).toHaveBeenCalledWith(3)
})

it('should render correctly with prev Button', () => {
const onChange = jest.fn()

render(
<Pagination
aria-label="pagination"
dataTestId="pagination"
onChange={onChange}
page={10}
pageCount={10}
/>
)

const prevButton = screen.getByTestId('pagination-arrow-prev')
const nextButton = screen.getByTestId('pagination-arrow-next')
const currentPage = screen.getByText('10')
const prevPage = screen.getByText('9')

expect(prevButton).toHaveAttribute('aria-disabled', 'false')
expect(nextButton).toHaveAttribute('aria-disabled', 'true')
expect(currentPage).toHaveAttribute('aria-current', 'true')
expect(prevPage).toHaveAttribute('aria-current', 'false')

/** Click on prev button */
fireEvent.click(prevButton)

expect(onChange).toHaveBeenCalledWith(9)

/** Click on a page 3 button */
fireEvent.click(screen.getByText('10'))

expect(onChange).toHaveBeenCalledWith(10)
})

describe('usePages', () => {
it('should return correct values', () => {
const { result } = renderHook(() => usePages({ page: 1, pageCount: 10, rangeDisplay: 5 }))

expect(result.current).toStrictEqual([1, 2, 3, 4, 5, '-', 10])
})

it('should return correct values in middle', () => {
const { result } = renderHook(() => usePages({ page: 5, pageCount: 10, rangeDisplay: 5 }))

expect(result.current).toStrictEqual([1, '-', 4, 5, 6, '-', 10])
})

it('should return correct values with small pagination', () => {
const { result } = renderHook(() => usePages({ page: 1, pageCount: 5, rangeDisplay: 5 }))

expect(result.current).toStrictEqual([1, 2, 3, 4, 5])
})
})
})

0 comments on commit 07b490c

Please sign in to comment.