The Pagination component enables the user to select a specific page from a range of pages with previous and next controls, collapsing long ranges with ellipses.
import { useState } from "react";
import { Pagination } from "@kesko/components";
export default () => {
const [page, setPage] = useState(1);
return <Pagination count={10} page={page} onChange={setPage} />;
};<nav class="k-pagination" aria-label="Pagination">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<button class="k-button" appearance="plain" aria-disabled="true" onclick="event.preventDefault()">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
Previous
</button>
</div>
<div class="k-pagination-pages">
<button class="k-button" square aria-current="page" aria-label="Page 1">1</button>
<button class="k-button" appearance="plain" square aria-label="Page 2">2</button>
<button class="k-button" appearance="plain" square aria-label="Page 3">3</button>
<button class="k-button" appearance="plain" square aria-label="Page 4">4</button>
<button class="k-button" appearance="plain" square aria-label="Page 5">5</button>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<button class="k-button" appearance="plain" square aria-label="Page 10">10</button>
</div>
<div class="k-pagination-next">
<button class="k-button" appearance="plain">
Next
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</button>
</div>
</div>
</nav>import type { CSSProperties } from "react";
import { useState } from "react";
import { Pagination } from "@kesko/components";
const secondary = {
"--k-pagination-color": "var(--k-color-theme-secondary)",
"--k-pagination-color-hover": "var(--k-color-highlight-secondary)",
"--k-pagination-color-text": "var(--k-color-text-on-secondary)",
"--k-pagination-color-item": "var(--k-color-text-secondary)",
"--k-pagination-color-tint": "var(--k-color-bg-secondary)",
"--k-button-radius": "var(--k-radius-sm)",
} as CSSProperties;
export default () => {
const [page, setPage] = useState(5);
return <Pagination count={20} page={page} onChange={setPage} style={secondary} />;
};<nav class="k-pagination" aria-label="Pagination" style="--k-pagination-color: var(--k-color-theme-secondary); --k-pagination-color-hover: var(--k-color-highlight-secondary); --k-pagination-color-text: var(--k-color-text-on-secondary); --k-pagination-color-item: var(--k-color-text-secondary); --k-pagination-color-tint: var(--k-color-bg-secondary); --k-button-radius: var(--k-radius-sm)">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<button class="k-button" appearance="plain">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
Previous
</button>
</div>
<div class="k-pagination-pages">
<button class="k-button" appearance="plain" square aria-label="Page 1">1</button>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<button class="k-button" appearance="plain" square aria-label="Page 4">4</button>
<button class="k-button" square aria-current="page" aria-label="Page 5">5</button>
<button class="k-button" appearance="plain" square aria-label="Page 6">6</button>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<button class="k-button" appearance="plain" square aria-label="Page 20">20</button>
</div>
<div class="k-pagination-next">
<button class="k-button" appearance="plain">
Next
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</button>
</div>
</div>
</nav>import { useState } from "react";
import { Pagination } from "@kesko/components";
export default () => {
const [page, setPage] = useState(1);
return <Pagination count={5} page={page} onChange={setPage} hideLabels />;
};<nav class="k-pagination" aria-label="Pagination">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<button class="k-button" appearance="plain" square aria-label="Previous" aria-disabled="true" onclick="event.preventDefault()">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
</button>
</div>
<div class="k-pagination-pages">
<button class="k-button" square aria-current="page" aria-label="Page 1">1</button>
<button class="k-button" appearance="plain" square aria-label="Page 2">2</button>
<button class="k-button" appearance="plain" square aria-label="Page 3">3</button>
<button class="k-button" appearance="plain" square aria-label="Page 4">4</button>
<button class="k-button" appearance="plain" square aria-label="Page 5">5</button>
</div>
<div class="k-pagination-next">
<button class="k-button" appearance="plain" square aria-label="Next">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</button>
</div>
</div>
</nav>import { useState } from "react";
import { Pagination } from "@kesko/components";
export default () => {
const [page, setPage] = useState(3);
return (
<Pagination
count={10}
page={page}
onChange={setPage}
previousLabel="Newer posts"
nextLabel="Older posts"
pageLabel={page => `Page ${page}`}
/>
);
};<nav class="k-pagination" aria-label="Pagination">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<button class="k-button" appearance="plain">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
Newer posts
</button>
</div>
<div class="k-pagination-pages">
<button class="k-button" appearance="plain" square aria-label="Page 1">1</button>
<button class="k-button" appearance="plain" square aria-label="Page 2">2</button>
<button class="k-button" square aria-current="page" aria-label="Page 3">3</button>
<button class="k-button" appearance="plain" square aria-label="Page 4">4</button>
<button class="k-button" appearance="plain" square aria-label="Page 5">5</button>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<button class="k-button" appearance="plain" square aria-label="Page 10">10</button>
</div>
<div class="k-pagination-next">
<button class="k-button" appearance="plain">
Older posts
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</button>
</div>
</div>
</nav>import { useEffect, useState } from "react";
import { Pagination } from "@kesko/components";
const count = 10;
const pageFromHash = () => Number(window.location.hash.replace("#page-", "")) || 1;
export default () => {
const [page, setPage] = useState(1);
const target = (item: number | "previous" | "next") =>
item === "previous" ? Math.max(page - 1, 1) : item === "next" ? Math.min(page + 1, count) : item;
useEffect(() => {
const sync = () => setPage(pageFromHash());
sync();
window.addEventListener("hashchange", sync);
return () => window.removeEventListener("hashchange", sync);
}, []);
return <Pagination count={count} page={page} href={item => `#page-${target(item)}`} />;
};<nav class="k-pagination" aria-label="Pagination">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<a class="k-button" appearance="plain" aria-disabled="true" href="#page-1" onclick="event.preventDefault()">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
Previous
</a>
</div>
<div class="k-pagination-pages">
<a class="k-button" square aria-current="page" href="#page-1" aria-label="Page 1">1</a>
<a class="k-button" appearance="plain" square href="#page-2" aria-label="Page 2">2</a>
<a class="k-button" appearance="plain" square href="#page-3" aria-label="Page 3">3</a>
<a class="k-button" appearance="plain" square href="#page-4" aria-label="Page 4">4</a>
<a class="k-button" appearance="plain" square href="#page-5" aria-label="Page 5">5</a>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<a class="k-button" appearance="plain" square href="#page-10" aria-label="Page 10">10</a>
</div>
<div class="k-pagination-next">
<a class="k-button" appearance="plain" href="#page-2">
Next
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</a>
</div>
</div>
</nav>import { useState } from "react";
import { Pagination, Stack } from "@kesko/components";
const PER_PAGE = 3;
const PRODUCTS = Array.from({ length: 12 }, (_, i) => `Product ${i + 1}`);
export default () => {
const [page, setPage] = useState(1);
const count = Math.ceil(PRODUCTS.length / PER_PAGE);
const visible = PRODUCTS.slice((page - 1) * PER_PAGE, page * PER_PAGE);
return (
<Stack gap="md" align="stretch">
<ul>
{visible.map(name => (
<li key={name}>{name}</li>
))}
</ul>
<Pagination count={count} page={page} onChange={setPage} aria-label="Search results pages" />
</Stack>
);
};<k-stack gap="md" align="stretch">
<ul>
<li>Product 1</li>
<li>Product 2</li>
<li>Product 3</li>
</ul>
<nav class="k-pagination" aria-label="Search results pages">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<button class="k-button" appearance="plain" aria-disabled="true" onclick="event.preventDefault()">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
Previous
</button>
</div>
<div class="k-pagination-pages">
<button class="k-button" square aria-current="page" aria-label="Page 1">1</button>
<button class="k-button" appearance="plain" square aria-label="Page 2">2</button>
<button class="k-button" appearance="plain" square aria-label="Page 3">3</button>
<button class="k-button" appearance="plain" square aria-label="Page 4">4</button>
</div>
<div class="k-pagination-next">
<button class="k-button" appearance="plain">
Next
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</button>
</div>
</div>
</nav>
</k-stack>import { useState } from "react";
import { Pagination, Stack } from "@kesko/components";
export default () => {
const [page, setPage] = useState(3);
return (
<Stack gap="lg" align="stretch">
<Pagination count={10} page={page} onChange={setPage} size="sm" aria-label="Small" />
<Pagination count={10} page={page} onChange={setPage} aria-label="Medium" />
<Pagination count={10} page={page} onChange={setPage} size="lg" aria-label="Large" />
</Stack>
);
};<k-stack gap="lg" align="stretch">
<nav class="k-pagination k-pagination-sm" aria-label="Small">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<button class="k-button k-button-sm" appearance="plain">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
Previous
</button>
</div>
<div class="k-pagination-pages">
<button class="k-button k-button-sm" appearance="plain" square aria-label="Page 1">1</button>
<button class="k-button k-button-sm" appearance="plain" square aria-label="Page 2">2</button>
<button class="k-button k-button-sm" square aria-current="page" aria-label="Page 3">3</button>
<button class="k-button k-button-sm" appearance="plain" square aria-label="Page 4">4</button>
<button class="k-button k-button-sm" appearance="plain" square aria-label="Page 5">5</button>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<button class="k-button k-button-sm" appearance="plain" square aria-label="Page 10">10</button>
</div>
<div class="k-pagination-next">
<button class="k-button k-button-sm" appearance="plain">
Next
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</button>
</div>
</div>
</nav>
<nav class="k-pagination" aria-label="Medium">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<button class="k-button" appearance="plain">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
Previous
</button>
</div>
<div class="k-pagination-pages">
<button class="k-button" appearance="plain" square aria-label="Page 1">1</button>
<button class="k-button" appearance="plain" square aria-label="Page 2">2</button>
<button class="k-button" square aria-current="page" aria-label="Page 3">3</button>
<button class="k-button" appearance="plain" square aria-label="Page 4">4</button>
<button class="k-button" appearance="plain" square aria-label="Page 5">5</button>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<button class="k-button" appearance="plain" square aria-label="Page 10">10</button>
</div>
<div class="k-pagination-next">
<button class="k-button" appearance="plain">
Next
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</button>
</div>
</div>
</nav>
<nav class="k-pagination k-pagination-lg" aria-label="Large">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<button class="k-button k-button-lg" appearance="plain">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
Previous
</button>
</div>
<div class="k-pagination-pages">
<button class="k-button k-button-lg" appearance="plain" square aria-label="Page 1">1</button>
<button class="k-button k-button-lg" appearance="plain" square aria-label="Page 2">2</button>
<button class="k-button k-button-lg" square aria-current="page" aria-label="Page 3">3</button>
<button class="k-button k-button-lg" appearance="plain" square aria-label="Page 4">4</button>
<button class="k-button k-button-lg" appearance="plain" square aria-label="Page 5">5</button>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<button class="k-button k-button-lg" appearance="plain" square aria-label="Page 10">10</button>
</div>
<div class="k-pagination-next">
<button class="k-button k-button-lg" appearance="plain">
Next
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</button>
</div>
</div>
</nav>
</k-stack>import { useState } from "react";
import { Pagination } from "@kesko/components";
export default () => {
const [page, setPage] = useState(10);
return <Pagination count={20} page={page} siblingCount={2} boundaryCount={2} onChange={setPage} />;
};<nav class="k-pagination" aria-label="Pagination">
<div class="k-pagination-content">
<div class="k-pagination-prev">
<button class="k-button" appearance="plain">
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M14.748 17.688a.401.401 0 0 1 0 .565l-.495.495a.401.401 0 0 1-.565 0l-6.465-6.465a.401.401 0 0 1 0-.565l6.465-6.465a.401.401 0 0 1 .565 0l.495.495a.401.401 0 0 1 0 .565L9.06 12z" fill="currentColor" /></svg>
Previous
</button>
</div>
<div class="k-pagination-pages">
<button class="k-button" appearance="plain" square aria-label="Page 1">1</button>
<button class="k-button" appearance="plain" square aria-label="Page 2">2</button>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<button class="k-button" appearance="plain" square aria-label="Page 8">8</button>
<button class="k-button" appearance="plain" square aria-label="Page 9">9</button>
<button class="k-button" square aria-current="page" aria-label="Page 10">10</button>
<button class="k-button" appearance="plain" square aria-label="Page 11">11</button>
<button class="k-button" appearance="plain" square aria-label="Page 12">12</button>
<span class="k-pagination-ellipsis" aria-hidden="true">…</span>
<button class="k-button" appearance="plain" square aria-label="Page 19">19</button>
<button class="k-button" appearance="plain" square aria-label="Page 20">20</button>
</div>
<div class="k-pagination-next">
<button class="k-button" appearance="plain">
Next
<svg viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M16.777 12.283l-6.465 6.465a.401.401 0 0 1-.564 0l-.495-.495a.401.401 0 0 1 0-.565L14.94 12 9.253 6.312a.401.401 0 0 1 0-.565l.495-.494a.401.401 0 0 1 .565 0l6.464 6.465a.401.401 0 0 1 0 .565z" fill="currentColor" /></svg>
</button>
</div>
</div>
</nav>Properties
| Name | Description | Type | Default |
|---|---|---|---|
count | Total number of pages. | number | — |
size | Size of the page and control buttons. | "sm" | "md" | "lg" | "md" |
siblingCount | Number of always-visible page buttons on each side of the active page. | number | 1 |
boundaryCount | Number of always-visible page buttons at the start and end of the range. | number | 1 |
pageLabel | Overrides the translated accessible name of a numbered page button, “Sivu 3” by default. Previous and next are named by their visible labels. | (page: number) => string | — |
previousLabel | Label for the previous-page button: visible text, or the accessible name when | string | — |
nextLabel | Label for the next-page button: visible text, or the accessible name when | string | — |
hideLabels | Shows the previous and next controls as icon-only square buttons, named by | boolean | false |
hidePrevious | Hides the previous-page button. | boolean | false |
hideNext | Hides the next-page button. | boolean | false |
page | The currently active page (1-based). | number | — |
aria-label | Accessible label for the navigation landmark. | string | — |
href | Returns the href for a page item as well as next and prev buttons, rendering the items as links. | (paginationItem: PaginationItem) => string | — |
Events
| Name | Description | Type |
|---|---|---|
onChange | Called with the newly selected page and the originating click event. | (page: number, event: MouseEvent<ButtonTarget>) => void |
Styles
CSS custom properties provide finer-grained control than props. Prefer the props API when it suits your need.
| Name | Description | Default |
|---|---|---|
--k-pagination-column-gap | Overrides the horizontal gap between items. | var(--k-space-3xs) |
--k-pagination-row-gap | Overrides the vertical gap between the page list and the controls. | var(--k-space-2xs) |
--k-pagination-color | Overrides the current page background. Also colors the text of the other items unless | var(--k-color-theme-primary) |
--k-pagination-color-hover | Overrides the hover and pressed background of the current page. Also colors the hover text of the other items unless | var(--k-color-highlight-primary) |
--k-pagination-color-text | Overrides the text color on the current page. | var(--k-color-text-on-primary) |
--k-pagination-color-item | Overrides the text of the other pages, the controls and the ellipsis. Set it when the accent is a fill that is not readable as text, as the secondary color is in dark mode. | var(--k-color-text-primary) |
--k-pagination-color-item-hover | Overrides the hover and pressed text of the other pages and controls. | var(--k-pagination-color-item) |
--k-pagination-color-tint | Overrides the hover and pressed background of the other pages and controls. | var(--k-color-bg-primary) |
Accessibility #
Under the hood this is a <nav> landmark holding native buttons, or links when you pass href, so people can jump to it, step through it and hear which page is current.
- Name it when there are several. Every pagination is a
navigationlandmark called “Sivutus” by default. When a page has more than one, for example search results and comments, pass a distinctaria-labelto each, such as “Hakutulosten sivutus”, so a landmark list tells them apart. - Prefer
hrefwhen pages are URLs. Links give people a real address: the back button works, the page can be opened in a new tab and screen readers announce a link to a page rather than a button that does something. - Decide what the page buttons say. A page button is named “Page {page}” by default and follows the language like the other built-in text. The name keeps the visible number, so saying “click 3” still works with voice control. Pass
pageLabelto override it per instance. - Previous and next are named by their visible text. Screen readers read the “Edellinen” and “Seuraava” text as it is shown, and the component has no prop for a different hidden name. This is on purpose: someone using voice control activates a button by saying its visible text, for example “click Edellinen”, and that only works when the accessible name contains the visible text.
- Keep the controls where they are. Previous and next stay focusable when there is nowhere to go; they are marked
aria-disabledinstead of removed or disabled, so focus is never lost when someone reaches the first or last page. - Keep it on one row on small screens. The page list never wraps, so a wide range overflows a narrow viewport. Lower
siblingCountorboundaryCount, or passsize="sm", where the component has less than about 360px to work with. - Check contrast when you override the item color.
--k-pagination-color-itempaints the other pages, the controls and the ellipsis, and needs 4.5:1 against the page background and against--k-pagination-color-tint.
See the accessibility guidelines and the A11Y checklist for more details.
Usage #
There are two necessary parts to using the Pagination component. The @kesko/components package and the CSS Framework are required. Everything else is optional:
npm install @kesko/components @kesko/csspnpm add @kesko/components @kesko/cssyarn add @kesko/components @kesko/cssbun add @kesko/components @kesko/cssOnce installed, load the CSS Framework in your app’s entry point or root layout:
import "@kesko/css";Then, you can import the Pagination:
import { Pagination } from "@kesko/components";Projects without React can get the same styles from @kesko/css by importing the components stylesheet as well:
@import "@kesko/css";
@import "@kesko/css/components";Resources #
Usage guidelines
Learn how to use the component library with React, Next.js, or basic HTML.
Localization
How to translate the components for multiple languages.
CSS Framework
Utilities and tokens for everything the components don’t cover.
Themes
How to customize the component library theme.
Accessibility checklist
Interactive, browser-based Kesko accessibility checklist.