Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/pagination-labels-prop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@primer/react-brand': minor
Comment thread
Copilot marked this conversation as resolved.
Outdated
---

Added a `labels` prop to the `Pagination` component for customizing the visible text of the previous and next controls.

```jsx
<Pagination pageCount={10} currentPage={2} labels={{prev: 'Pr茅c茅dent', next: 'Suivant'}} />
```
9 changes: 9 additions & 0 deletions apps/next-docs/content/components/Pagination/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ render(<App />)
/>
```

### Custom button labels

Use the `labels` prop to customize the visible text of the previous and next controls.

```jsx live
<Pagination pageCount={3} currentPage={2} labels={{prev: 'Pr茅c茅dent', next: 'Suivant'}} />
```

## Component props

### Pagination <Label>Required</Label>
Expand All @@ -83,3 +91,4 @@ render(<App />)
| `marginPageCount` | `number` | | `false` | Defines how many pages are to be displayed on the left and right of the component. Will be reduced on narrow viewports. |
| `showPages` | `boolean` | | `false` | Whether to show the page numbers |
| `surroundingPageCount` | `number` | | `false` | The number of pages to show on each side of the current page. Will be hidden on narrow viewports. |
| `labels` | `{prev: string; next: string}` | | `false` | Custom text labels for certain pagination controls |
Comment thread
rezrah marked this conversation as resolved.
Outdated
11 changes: 11 additions & 0 deletions packages/react/src/Pagination/Pagination.features.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,14 @@ export const CustomAttributeForwarding: Story = {
},
},
}

export const CustomLabels: Story = {
args: {
pageCount: 15,
currentPage: 5,
labels: {
prev: 'Pr茅c茅dent',
next: 'Suivant',
},
},
}
18 changes: 18 additions & 0 deletions packages/react/src/Pagination/Pagination.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ describe('Pagination', () => {
expect(getByRole('button', {name: 'Next Page'}).classList).toContain('Button')
})

it('renders custom visible labels for the previous and next controls', () => {
const {getByText, queryByText} = render(
<Pagination pageCount={5} currentPage={2} labels={{prev: 'Newer', next: 'Older'}} />,
)

expect(getByText('Newer')).toBeInTheDocument()
expect(getByText('Older')).toBeInTheDocument()
expect(queryByText('Previous')).not.toBeInTheDocument()
expect(queryByText('Next')).not.toBeInTheDocument()
})

it('falls back to the default previous and next labels when none are provided', () => {
const {getByText} = render(<Pagination pageCount={5} currentPage={2} />)

expect(getByText('Previous')).toBeInTheDocument()
expect(getByText('Next')).toBeInTheDocument()
})

it('shows ellipsis just before the final item to reduce pagination links on longer lists, where the first item is selected', () => {
const {getByRole} = render(<Pagination pageCount={10} currentPage={1} />)
const rootEl = getByRole('navigation')
Expand Down
32 changes: 29 additions & 3 deletions packages/react/src/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,19 @@ export type PaginationProps = {
showPages?: boolean
/* The number of pages to show on each side of the current page */
surroundingPageCount?: number
/* Custom text labels for the pagination controls. Use for localization. */
labels?: {
prev?: string
next?: string
}
'data-testid'?: string
} & Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>

const defaultPaginationLabels = {
prev: 'Previous',
next: 'Next',
}

/**
* Use Pagination to display a sequence of links that allow navigation to discrete, related pages.
* @see https://primer.style/brand/components/Pagination
Expand All @@ -45,6 +55,7 @@ export const Pagination = memo(
marginPageCount = 1,
showPages = true,
surroundingPageCount = 2,
labels,
'aria-label': ariaLabel,
'data-testid': testId,
...rest
Expand All @@ -56,6 +67,8 @@ export const Pagination = memo(
surroundingPageCount = 0
}

const {prev: prevLabel, next: nextLabel} = {...defaultPaginationLabels, ...labels}
Comment thread
rezrah marked this conversation as resolved.
Outdated

const navRef = React.useRef<HTMLElement>(null)

const pageChange = useCallback(
Expand All @@ -77,6 +90,8 @@ export const Pagination = memo(
page={page}
hrefBuilder={hrefBuilder}
pageAttributesBuilder={pageAttributesBuilder}
prevLabel={prevLabel}
nextLabel={nextLabel}
onClick={pageChange(page.num)}
/>
)
Expand All @@ -89,6 +104,8 @@ export const Pagination = memo(
surroundingPageCount,
hrefBuilder,
pageAttributesBuilder,
prevLabel,
nextLabel,
pageChange,
])

Expand All @@ -111,10 +128,19 @@ type PaginationItemProps = {
page: PaginationPageType
hrefBuilder: (n: number) => string
pageAttributesBuilder?: (n: number, page: PaginationPageType) => {[key: string]: string}
prevLabel: string
nextLabel: string
onClick?: React.MouseEventHandler<HTMLAnchorElement>
}

const PaginationItem = ({page, hrefBuilder, pageAttributesBuilder, onClick}: PaginationItemProps) => {
const PaginationItem = ({
page,
hrefBuilder,
pageAttributesBuilder,
prevLabel,
nextLabel,
onClick,
}: PaginationItemProps) => {
const [isArrowExpanded, setIsArrowExpanded] = React.useState(false)

const baseProps = {
Expand Down Expand Up @@ -158,7 +184,7 @@ const PaginationItem = ({page, hrefBuilder, pageAttributesBuilder, onClick}: Pag
className={styles.Pagination__controlArrow}
/>
</span>
<span className={styles.Pagination__controlText}>Previous</span>
<span className={styles.Pagination__controlText}>{prevLabel}</span>
Comment thread
rezrah marked this conversation as resolved.
</span>
</Button>
)
Expand All @@ -180,7 +206,7 @@ const PaginationItem = ({page, hrefBuilder, pageAttributesBuilder, onClick}: Pag
onBlur={() => setIsArrowExpanded(false)}
>
<span className={styles.Pagination__controlContent}>
<span className={styles.Pagination__controlText}>Next</span>
<span className={styles.Pagination__controlText}>{nextLabel}</span>
<span
className={clsx(styles.Pagination__controlArrowWrapper, styles['Pagination__controlArrowWrapper--next'])}
>
Expand Down
11 changes: 11 additions & 0 deletions packages/react/src/Pagination/Pagination.visual.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,15 @@ test.describe('Visual Comparison: Pagination', () => {
await page.waitForTimeout(500)
await expect(page).toHaveScreenshot({fullPage: true})
})

test('Pagination / Custom Labels', async ({page}) => {
await page.goto(
'http://localhost:6006/iframe.html?args=&id=components-pagination-features--custom-labels&viewMode=story',
{waitUntil: 'networkidle'},
)
await page.locator('body.sb-show-main').waitFor({state: 'visible'})

await page.waitForTimeout(500)
await expect(page).toHaveScreenshot({fullPage: true})
})
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading