Prisma
Live Preview

Pagination Component

Skill này hướng dẫn tạo component Pagination — điều hướng giữa các trang dữ liệu cho table, list, và grid.

1. Mục tiêu (Objective)

Tạo component Pagination cho table/list navigation: page numbers, prev/next, per-page selector. Luôn đi cùng Table hoặc data list.

2. AI Context & Intent (Ngữ cảnh cho AI)

Khi nào dùng Pagination?

  • Table data: Navigate qua nhiều trang rows
  • Search results: Page qua kết quả tìm kiếm
  • Product listing: Browse danh sách sản phẩm
  • Admin dashboard: List users, orders, logs

⚠️ Phân biệt Pagination vs Infinite Scroll vs Load More (QUAN TRỌNG)

Tiêu chí Pagination Infinite Scroll Load More
UX Jump to any page Auto-load on scroll Manual "Load More" button
Best for Structured data, known total Social feed, timeline Mixed content
SEO ✅ URL per page ❌ Hard to index ❌ Hard to index
Mobile ⚠️ Small buttons ✅ Natural swipe ✅ Simple
Ví dụ Table, admin list News feed, Instagram Comments section

Decision Tree cho AI

text
Data có nhiều pages?
├─ Structured data + cần random access → Pagination
│   ├─ Table → Pagination (default) + per-page selector
│   ├─ Search results → Pagination (default)
│   ├─ Mobile table → Pagination (simple: prev/next only)
│   └─ Compact header → Pagination (compact: "1 of 10")
│
├─ Feed / timeline / social → Infinite scroll
├─ Comments / replies → Load More button
└─ ≤ 20 items → Show all, no pagination needed

3. Anatomy

text
┌────────────────────────────────────────────────────────────┐
│  ◀  1  2  [3]  4  5  ...  10  ▶     10 per page ▼        │
│  ↑  ↑     ↑↑           ↑    ↑       ↑                    │
│  │  │     ││           │    │       └─ Per-page selector  │
│  │  │     │└─ active   │    └─ Next button                │
│  │  │     └─ --primary │                                  │
│  │  └─ page buttons    └─ Ellipsis                        │
│  └─ Prev button                                           │
│                                                            │
│  Showing 21-30 of 100 items                                │ ← Info text
└────────────────────────────────────────────────────────────┘

4. Platform Mapping

Platform Component Key Difference
Web Pagination Page numbers + prev/next buttons
iOS ❌ (infinite scroll) iOS không dùng pagination, dùng pull-to-load
Android (M3) ❌ (infinite scroll) M3 prefer infinite scroll
Carbon Pagination Full: page numbers + per-page + total count

Cross-platform note: Pagination là Web/Desktop concept. Mobile platforms prefer infinite scroll.

5. Variants

Variant Mô tả
default Full page numbers with prev/next
simple Prev/Next only (no numbers)
compact "1 of 10" text with arrows
with-select Includes per-page selector (10/25/50/100)

5.4. Slot Map (Figma ↔ Code)

📎 Source: slot-manifest.jsonpagination · Layer: item

Figma Slot data-slot CSS Class Required Accepts
Root pagination .pagination
Prev pagination-prev icon-button
Next pagination-next icon-button
Item pagination-item ✅ (n×) page-button
Ellipsis pagination-ellipsis

6. Token Mapping

📦 Atomic Mapping: Xem ATOMIC-MAPPING.md → mục pagination — Density Tier: comp.

Active page dùng --primary / --primary-foreground, default fg dùng --muted-foreground, hover dùng --state-layer-hover. Component token JSON files đã deprecated.

7. Props & API

typescript
interface PaginationProps {
  currentPage: number;
  totalPages: number;
  variant?: 'default' | 'simple' | 'compact' | 'with-select';
  siblingCount?: number;
  showFirstLast?: boolean;
  perPage?: number;
  perPageOptions?: number[];
  totalItems?: number;
  onChange: (page: number) => void;
  onPerPageChange?: (perPage: number) => void;
}

8. Accessibility (a11y)

  • Container: nav element with aria-label="Pagination".
  • Current page: aria-current="page".
  • Disabled prev/next: aria-disabled="true".
  • Keyboard: Tab moves between buttons, Enter/Space activates.

9. Best Practices & Rules

  • Ellipsis: Show ... when too many pages (e.g., 1 2 ... 5 6 7 ... 99 100).
  • Mobile: Switch to simple variant (prev/next only) on small screens.
  • Pair with Table: Always co-locate with table, show total items count.
  • Không Hardcode: Mọi giá trị từ Token.

10. Example Usage

jsx
{/* Standard table pagination */}
<Pagination
  currentPage={3}
  totalPages={10}
  totalItems={100}
  onChange={handlePageChange}
/>

{/* With per-page selector */}
<Pagination
  currentPage={1}
  totalPages={20}
  variant="with-select"
  perPage={10}
  perPageOptions={[10, 25, 50, 100]}
  totalItems={200}
  onChange={handlePageChange}
  onPerPageChange={handlePerPageChange}
/>

{/* Mobile simple */}
<Pagination
  currentPage={page}
  totalPages={total}
  variant="simple"
  onChange={setPage}
/>