Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
24 changes: 23 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name: 👮 CI
on:
pull_request:
branches: [main]
branches: [main, modernize]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down Expand Up @@ -30,6 +30,28 @@ jobs:
cache: npm
- run: npm ci
- run: npm test
e2e:
name: 🎭 E2E
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
- run: npm ci
- run: npm run build
# `file:..` deps can be served from npm's cache; `install --no-package-lock`
# forces npm to re-pack the freshly built dist/ on every CI run instead.
- run: npm --prefix example install --no-package-lock
- run: npx playwright install --with-deps chromium
- run: npm run test:e2e
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report
retention-days: 7
lint:
name: 🧹 Lint
runs-on: ubuntu-latest
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@ yarn-debug.log*
yarn-error.log*

.next

# playwright
test-results
playwright-report
blob-report
.playwright
57 changes: 43 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ TL;DR Just show me the [DEMO](https://etchteam.github.io/next-pagination)
- **Responsive.** Works on all devices.
- **Themeable.** Make it look however you want.
- **Self contained.** There's only one required prop to get going. The rest of the logic is handled for you.
- **Works with Next.** Integrated with the Next.js router.
- **Works with Next.** Supports both the pages router and the app router.

## Install

Expand All @@ -26,19 +26,15 @@ npm install --save @etchteam/next-pagination
## Usage
This component is fairly self contained. You will need to pass the **total number of potential results** in order to calculate the number of pages to show.

```jsx
import React, { Component } from 'react'

import Pagination from '@etchteam/next-pagination'
The package ships three entrypoints:

class Example extends Component {
render() {
return <Pagination total={1000} />
}
}
```
| Import path | Export(s) | Use when |
| ---------------------------------------- | ----------------------------------------------- | ------------------------------ |
| `@etchteam/next-pagination` | default `PagesPagination`, named `PagesPagination` + `AppPagination` | Either router (back-compat). |
| `@etchteam/next-pagination/pages` | default `PagesPagination` | Pages router only — avoids pulling in `next/navigation` and the `'use client'` directive. |
| `@etchteam/next-pagination/app` | default `AppPagination` | App router only — avoids pulling in `next/router` / `next/head`. |

You will need to import the CSS, either in your `_app.js`, or in your Sass build.
You will need to import the CSS, either in your `_app.js`, in your app router root layout, or in your Sass build.

```jsx
import '@etchteam/next-pagination/dist/index.css'
Expand All @@ -49,12 +45,45 @@ When used, the pagination component will reload the same route with added pagina
- `page` for the page number the user is on.
- `size` for the number of results per page.

e.g. ?page=4&size=20
e.g. `?page=4&size=20`

The **default page** is 1. The **default size** is 20.
The **default page** is 1. The **default size** is 20. Invalid values in the URL (`?page=abc`, `?page=-1`, `?page=99999`) are clamped to the valid range.

You'll need to load the actual data from your API yourself. We're only here for the front-end!

### Pages router

```jsx
import Pagination from '@etchteam/next-pagination/pages'

export default function Example() {
return <Pagination total={1000} />
}
```

The pages-router adapter also injects `<link rel="prev|next">` SEO hints into `<head>` via `next/head`.

### App router

`AppPagination` reads the route via `next/navigation` and must be rendered inside a `<Suspense>` boundary (a Next.js requirement of `useSearchParams`).

```jsx
'use client'

import { Suspense } from 'react'
import { AppPagination } from '@etchteam/next-pagination/app'

export default function Example() {
return (
<Suspense>
<AppPagination total={1000} />
</Suspense>
)
}
```

`AppPagination` does **not** emit `<link rel="prev|next">` SEO hints — `next/head` is pages-router only and Next's metadata APIs are server-only, so prev/next links can't be written from a client component. If you need them, render them server-side from your route's `generateMetadata`.

## Props

| Name | Type | Description |
Expand Down
30 changes: 30 additions & 0 deletions example/app/app-example/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use client'

import React, { Suspense } from 'react'
import { AppPagination } from '@etchteam/next-pagination/app'

import theme from '../../styles/theme.module.scss'

export default function AppExample() {
return (
<main>
<h1>App Router Pagination</h1>
<p>
This page uses the <code>AppPagination</code> named export, which reads
the route and search params from <code>next/navigation</code> instead of{' '}
<code>next/router</code>.
</p>

<Suspense>
<h2>Default theme</h2>
<AppPagination total={1000} />

<h2>Custom theme</h2>
<AppPagination total={1000} theme={theme} />

<h2>Custom page sizes</h2>
<AppPagination total={1000} sizes={[5, 10, 25, 150]} />
</Suspense>
</main>
)
}
16 changes: 16 additions & 0 deletions example/app/layout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react'

import '@etchteam/next-pagination/dist/index.css'
import '../styles/main.css'

export const metadata = {
title: 'Next pagination (App Router)'
}

export default function RootLayout({ children }) {

Check warning on line 10 in example/app/layout.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'children' is missing in props validation

See more on https://sonarcloud.io/project/issues?id=etchteam_next-pagination&issues=AZ3AjSs0RuvhNyq5ZIv8&open=AZ3AjSs0RuvhNyq5ZIv8&pullRequest=140
return (
<html lang='en'>
<body>{children}</body>
</html>
)
}
7 changes: 4 additions & 3 deletions example/next.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const withSourceMaps = require('@zeit/next-source-maps')()

const isProd = (process.env.NODE_ENV || 'production') === 'production'
const isDeploy = process.env.EXAMPLE_DEPLOY === 'true'

module.exports = withSourceMaps({
assetPrefix: isProd ? '/next-pagination' : undefined,
basePath: isProd ? '/next-pagination' : undefined
output: isDeploy ? 'export' : undefined,
assetPrefix: isDeploy ? '/next-pagination' : undefined,
basePath: isDeploy ? '/next-pagination' : undefined
})
3 changes: 2 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
},
"scripts": {
"dev": "next",
"build": "next build && next export -o build",
"build": "EXAMPLE_DEPLOY=true next build && rm -rf build && mv out build",
"build:server": "next build",
"start": "next start"
},
"browserslist": [
Expand Down
2 changes: 1 addition & 1 deletion example/pages/[dynamic].js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import Pagination from '@etchteam/next-pagination/dist'
import Pagination from '@etchteam/next-pagination/pages'

export default function Dynamic() {
return (
Expand Down
5 changes: 4 additions & 1 deletion example/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import Link from 'next/link'

import Pagination from '@etchteam/next-pagination/dist'
import Pagination from '@etchteam/next-pagination/pages'

import theme from '../styles/theme.module.scss'

Expand Down Expand Up @@ -62,6 +62,9 @@ export default function Home() {
Dynamic pagination
</Link>
</p>
<p>
<Link href='/app-example'>App Router pagination</Link>
</p>
</main>
)
}
Loading
Loading