Skip to content

Commit

Permalink
Hide paged items in Pagination component on narrow viewports (#714)
Browse files Browse the repository at this point in the history
* Hide paged items in Pagination component on narrow viewports to prevent horizontal scrolling

* cleanup storybook
  • Loading branch information
rezrah authored Aug 23, 2024
1 parent 96e29fb commit fb1980b
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 12 deletions.
11 changes: 11 additions & 0 deletions .changeset/three-sloths-grin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@primer/react-brand': patch
---

Hide paged items in Pagination component on narrow viewports to prevent horizontal scrolling and offer improved accessibility by default.

Use `showPages` to re-enable paged items if required:

```jsx
<Pagination showPages />
```
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/react/src/BreakoutBanner/BreakoutBanner.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe('BreakoutBanner', () => {
it('renders primary link with arrow by default', () => {
const {getAllByRole} = render(
<BreakoutBanner>
<BreakoutBanner.Heading>Required heading</BreakoutBanner.Heading>
<BreakoutBanner.LinkGroup>
<Link href="#">Primary Action</Link>
<Link href="#">Secondary Action</Link>
Expand All @@ -89,6 +90,7 @@ describe('BreakoutBanner', () => {
it('renders secondary link without arrow by default', () => {
const {getAllByRole} = render(
<BreakoutBanner>
<BreakoutBanner.Heading>Required heading</BreakoutBanner.Heading>
<BreakoutBanner.LinkGroup>
<Link href="#">Primary Action</Link>
<Link href="#">Secondary Action</Link>
Expand Down
15 changes: 15 additions & 0 deletions packages/react/src/Pagination/Pagination.features.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import React from 'react'
import {Meta} from '@storybook/react'
import {INITIAL_VIEWPORTS} from '@storybook/addon-viewport'
import {Pagination} from './Pagination'
import {Stack} from '../Stack'
import {Text} from '../Text'

export default {
title: 'Components/Pagination/Features',
component: Pagination,
parameters: {
viewport: {
viewports: INITIAL_VIEWPORTS,
},
},
} as Meta<typeof Pagination>

const handlePageChange = (e: React.MouseEvent, n: number) => {
Expand All @@ -23,6 +29,15 @@ export const HidePageNumbers = () => (
<Pagination pageCount={15} currentPage={5} showPages={false} onPageChange={handlePageChange} />
)

export const NarrowPageNumbersHiddenByDefault = () => (
<Pagination pageCount={15} currentPage={5} marginPageCount={4} onPageChange={handlePageChange} />
)
NarrowPageNumbersHiddenByDefault.parameters = {
viewport: {
defaultViewport: 'iphonexr',
},
}

export const HidePageNumbersByViewport = () => (
<Stack direction="vertical" alignItems="center" gap="spacious">
<div>
Expand Down
20 changes: 17 additions & 3 deletions packages/react/src/Pagination/Pagination.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@ import '@testing-library/jest-dom'
import {axe, toHaveNoViolations} from 'jest-axe'

import {Pagination} from './Pagination'
import '../test-utils/mocks/match-media-mock'
import {useWindowSize} from '../hooks/useWindowSize'

jest.mock('../hooks/useWindowSize')
const mockUseWindowSize = useWindowSize as jest.Mock
mockUseWindowSize.mockImplementation(() => ({isMedium: true}))

expect.extend(toHaveNoViolations)

describe('Pagination', () => {
afterEach(cleanup)
afterEach(() => {
cleanup()
jest.clearAllMocks()
})

it('renders the root element correctly into the document', () => {
const {getByRole} = render(<Pagination pageCount={5} currentPage={1} />)
Expand Down Expand Up @@ -49,7 +56,6 @@ describe('Pagination', () => {
it('can optionally remove paged items', () => {
const {getByRole} = render(<Pagination pageCount={10} currentPage={5} showPages={false} />)
const rootEl = getByRole('navigation')

const linksAsVerbatimText = Array.from(rootEl.querySelectorAll('a')).map(link => link.textContent)
expect(linksAsVerbatimText).toEqual(['Previous', 'Next'])
})
Expand Down Expand Up @@ -124,4 +130,12 @@ describe('Pagination', () => {
}
}
})

it('does not show paged items by default on narrow viewports', () => {
mockUseWindowSize.mockImplementation(() => ({isMedium: false}))
const {getByRole} = render(<Pagination pageCount={5} currentPage={1} />)
const rootEl = getByRole('navigation')
const linksAsVerbatimText = Array.from(rootEl.querySelectorAll('a')).map(link => link.textContent)
expect(linksAsVerbatimText).toEqual(['Previous', 'Next'])
})
})
8 changes: 5 additions & 3 deletions packages/react/src/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {memo, PropsWithChildren, useCallback} from 'react'
import {Link} from '..'
import {Link, useWindowSize} from '..'

import {default as clsx} from 'clsx'

Expand Down Expand Up @@ -56,12 +56,14 @@ export const Pagination = memo(
hrefBuilder = defaultHrefBuilder,
pageAttributesBuilder,
marginPageCount = 1,
showPages = true,
showPages,
surroundingPageCount = 2,
'aria-label': ariaLabel,
'data-testid': testId,
...rest
}: PaginationProps) => {
const {isMedium} = useWindowSize()

const navRef = React.useRef<HTMLElement>(null)
const pageElements = usePaginationPages({
pageCount,
Expand All @@ -70,7 +72,7 @@ export const Pagination = memo(
hrefBuilder,
pageAttributesBuilder,
marginPageCount,
showPages,
showPages: showPages !== undefined ? showPages : isMedium ? true : false,
surroundingPageCount,
})

Expand Down
12 changes: 12 additions & 0 deletions packages/react/src/Pagination/Pagination.visual.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ test.describe('Visual Comparison: Pagination', () => {
expect(await page.screenshot({fullPage: true})).toMatchSnapshot()
})

// eslint-disable-next-line i18n-text/no-en
test.describe('Mobile viewport test for Narrow Page Numbers Hidden By Default', () => {
test.use({viewport: {width: 360, height: 800}})
test('Pagination / Narrow Page Numbers Hidden By Default', async ({page}) => {
await page.goto(
'http://localhost:6006/iframe.html?args=&id=components-pagination-features--narrow-page-numbers-hidden-by-default&viewMode=story',
)

await page.waitForTimeout(500)
expect(await page.screenshot({fullPage: true})).toMatchSnapshot()
})
})
test('Pagination / Hide Page Numbers By Viewport', async ({page}) => {
await page.goto(
'http://localhost:6006/iframe.html?args=&id=components-pagination-features--hide-page-numbers-by-viewport&viewMode=story',
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit fb1980b

Please sign in to comment.