Pagination
Ro'yxat va jadvallarni sahifalarga bo'lish: SEO uchun haqiqiy havolalar, Next.js Link va telefonda ixcham ko'rinish.
21–30 / 230 ta
'use client';
import { Pagination, PaginationInfo } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function PaginationBasic() {
const [page, setPage] = useState(3);
return (
<div className="flex flex-col items-center gap-3">
<Pagination page={page} onPageChange={setPage} total={230} pageSize={10} />
<PaginationInfo page={page} pageSize={10} total={230} />
</div>
);
}
Import
import { Pagination, PaginationInfo } from '@akhatmirzo/ui';Qachon ishlatish
- Uzun ro'yxatlar va jadvallar — buyurtmalar, blog maqolalari, qidiruv natijalari. Foydalanuvchi kerakli sahifaga to'g'ridan-to'g'ri o'ta oladi.
- Sahifa URL'da bo'lishi kerak bo'lsa (
/blog?page=3) —getHrefbering: tugmalar haqiqiy<a href>bo'ladi, qidiruv tizimlari barcha sahifalarni topadi. - Cheksiz lenta uchun emas. Ijtimoiy tarmoq lentasi kabi oqimda "Yana yuklash" tugmasi yoki avtomatik yuklash qulayroq.
- Kichik ro'yxatda kerak emas. Hammasi bitta sahifaga sig'sa, sahifalashni ko'rsatmang.
Sahifalar hisobi
Sahifalar ro'yxati @akhatmirzo/hooks dagi getPagination bilan hisoblanadi — DataTable bilan
bir xil algoritm. Elementlar soni barqaror (siblings * 2 + 5), shuning uchun sahifa almashganda
tugmalar "sakramaydi". … bosilmaydi.
total + pageSize (standart 10) yoki to'g'ridan-to'g'ri pageCount bering. Sahifalar 1 dan
boshlanadi.
O'lchamlar
size — sm (32px) yoki md (40px, standart) kvadrat tugmalar.
'use client';
import { Pagination } from '@akhatmirzo/ui';
export default function PaginationSizes() {
return (
<div className="flex flex-col items-center gap-4">
<Pagination defaultPage={4} pageCount={12} size="sm" compact={false} />
<Pagination defaultPage={4} pageCount={12} compact={false} />
</div>
);
}
Birinchi / oxirgi sahifa
showFirstLast — ⏮ ⏭ tugmalari. siblings — joriy sahifa yonida nechta raqam ko'rinadi
(standart 1).
'use client';
import { Pagination } from '@akhatmirzo/ui';
export default function PaginationFirstLast() {
return <Pagination defaultPage={10} pageCount={40} siblings={2} showFirstLast compact={false} />;
}
Ixcham ko'rinish
compact="auto" (standart) — 640px dan tor ekranda ‹ 3 / 24 › ko'rinishiga o'tadi.
compact — har doim ixcham, compact={false} — har doim to'liq.
'use client';
import { Pagination } from '@akhatmirzo/ui';
export default function PaginationCompact() {
return (
<div className="flex flex-col items-center gap-4">
<Pagination defaultPage={3} pageCount={24} compact />
<Pagination defaultPage={3} pageCount={24} compact size="sm" showFirstLast />
</div>
);
}
Nega CSS bilan?
auto rejimda ikkala ko'rinish ham render qilinadi va CSS breakpoint bilan bittasi yashiriladi
(display: none — ekran o'quvchi ham ko'rmaydi). JavaScript matchMedia ishlatilmagani uchun
SSR'da hydration farqi va sahifa yuklanganda "sakrash" bo'lmaydi.
Havolalar (SEO)
getHref berilsa, har bir sahifa — haqiqiy <a href>. Bosilganda brauzer odatdagidek o'tadi;
onPageChange ham chaqiriladi. Chekkadagi "Oldingi" / "Keyingi" havola emas, o'chirilgan tugma
bo'ladi.
'use client';
import { Pagination } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function PaginationLinks() {
// Haqiqiy loyihada sahifa URL'dan o'qiladi: ?page=3
const [page, setPage] = useState(1);
return (
<Pagination page={page} onPageChange={setPage} pageCount={8} getHref={(p) => `#sahifa-${p}`} />
);
}
Next.js Link
renderLink — o'z havola komponentingiz. Barcha prop'larni havolaga yoying; page — qaysi
sahifaga olib borishi.
import Link from 'next/link';
import { Pagination } from '@akhatmirzo/ui';
export default async function BlogPage({
searchParams,
}: {
searchParams: Promise<{ page?: string }>;
}) {
const page = Number((await searchParams).page ?? 1);
const { posts, total } = await getPosts(page);
return (
<>
<PostList posts={posts} />
<Pagination
page={page}
total={total}
pageSize={10}
getHref={(p) => `/blog?page=${p}`}
renderLink={({ page, ...props }) => <Link {...props} />}
/>
</>
);
}DataTable bilan
DataTable'ning o'z sahifalashi bor (pagination prop). Sahifalashni jadvaldan tashqarida —
masalan URL bilan boshqarish kerak bo'lsa, pagination ni bermang va Pagination +
PaginationInfo ni pastga qo'ying.
| № | Mijoz | Summa |
|---|---|---|
| 3001 | Jasur Karimov | 120 000 so'm |
| 3002 | Malika Rahimova | 434 159 so'm |
| 3003 | Nodira Saidova | 748 318 so'm |
| 3004 | Otabek Qodirov | 1 062 477 so'm |
| 3005 | Jasur Karimov | 1 376 636 so'm |
1–5 / 47 ta
'use client';
import { formatMoney } from '@akhatmirzo/core';
import { DataTable, Pagination, PaginationInfo, type DataTableColumn } from '@akhatmirzo/ui';
import { useState } from 'react';
interface Order {
id: number;
customer: string;
total: number;
}
const NAMES = ['Jasur Karimov', 'Malika Rahimova', 'Nodira Saidova', 'Otabek Qodirov'];
const ORDERS: Order[] = Array.from({ length: 47 }, (_, i) => ({
id: 3001 + i,
customer: NAMES[i % NAMES.length]!,
total: 120_000 + ((i * 314_159) % 2_500_000),
}));
const columns: DataTableColumn<Order>[] = [
{ key: 'id', header: '№', width: 88 },
{ key: 'customer', header: 'Mijoz' },
{ key: 'total', header: 'Summa', numeric: true, cell: (o) => formatMoney(o.total) },
];
const PAGE_SIZE = 5;
export default function PaginationDataTable() {
const [page, setPage] = useState(1);
const rows = ORDERS.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
return (
<div className="flex w-full flex-col gap-3">
<DataTable label="Buyurtmalar" data={rows} columns={columns} className="w-full" />
<div className="flex flex-wrap items-center justify-between gap-3">
<PaginationInfo page={page} pageSize={PAGE_SIZE} total={ORDERS.length} />
<Pagination
page={page}
onPageChange={setPage}
total={ORDERS.length}
pageSize={PAGE_SIZE}
size="sm"
/>
</div>
</div>
);
}
Props
Pagination
Qolgan <nav> atributlari ham qabul qilinadi.
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
page | number | — | Joriy sahifa, 1 dan (boshqariladigan rejim) |
defaultPage | number | 1 | Boshlang'ich sahifa |
onPageChange | (page: number) => void | — | Sahifa almashganda |
total | number | — | Jami yozuvlar soni |
pageSize | number | 10 | Bir sahifadagi yozuvlar |
pageCount | number | — | Sahifalar soni to'g'ridan-to'g'ri (`total` / `pageSize` o'rniga) |
siblings | number | 1 | Joriy sahifaning har ikki tomonidagi raqamlar |
getHref | (page: number) => string | — | Berilsa — tugmalar haqiqiy `<a href>` bo'ladi |
renderLink | (props: PaginationLinkProps) => ReactNode | — | Next `Link` kabi havola komponenti (`getHref` bilan) |
size | 'sm' | 'md' | 'md' | Tugma: 32 / 40px |
showFirstLast | boolean | false | Birinchi / oxirgi sahifa tugmalari |
compact | boolean | 'auto' | 'auto' | `‹ 3 / 24 ›` ko'rinishi; `auto` — 640px dan tor ekranda |
labels | { nav, previous, next, first, last, page, ellipsis, compact } | — | Ekran o'quvchi matnlari. Standart: "Sahifalash", "Oldingi sahifa", "Keyingi sahifa", `(n) => "${n}-sahifa"` ... |
PaginationInfo
Qolgan <p> atributlari ham qabul qilinadi.
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
pagemajburiy | number | — | Joriy sahifa (1 dan) |
pageSizemajburiy | number | — | Bir sahifadagi yozuvlar |
totalmajburiy | number | — | Jami yozuvlar |
labels | { template?: (from, to, total) => ReactNode; empty?: ReactNode } | — | Standart: "21–30 / 230 ta" va "Ma'lumot yo'q" |
Data atributlari
| Atribut | Qayerda | Qiymat |
|---|---|---|
data-size | nav, tugmalar | sm · md |
data-compact | nav | auto yoki mavjud (compact) |
data-active | sahifa tugmasi | joriy sahifada mavjud |
data-disabled | oldingi / keyingi | chekkada mavjud |
Accessibility
- Tuzilish.
<nav aria-label="Sahifalash">ichida<ul>ro'yxat — ekran o'quvchi navigatsiya hududi va elementlar sonini e'lon qiladi. - Joriy sahifa —
aria-current="page". Rang yagona signal emas: joriy tugma to'ldirilgan fonda. - Nomlar. Har bir tugmada
aria-label("5-sahifa","Keyingi sahifa"); ikonkalararia-hidden.…ekran o'quvchiga "Boshqa sahifalar" deb o'qiladi. - Klaviatura. Oddiy tugma yoki havolalar:
Tabbilan yuriladi,Enterbilan bosiladi. Chekkadagi o'chirilgan tugmalarTabda o'tkazib yuboriladi. - PaginationInfo —
aria-live="polite": sahifa almashganda yangi oraliq e'lon qilinadi.