@ceed/ads 1.20.0 → 1.20.1-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ProfileMenu/ProfileMenu.d.ts +1 -1
- package/dist/components/data-display/Markdown.md +832 -0
- package/dist/components/feedback/Dialog.md +605 -3
- package/dist/components/feedback/Modal.md +656 -24
- package/dist/components/feedback/llms.txt +1 -1
- package/dist/components/inputs/Autocomplete.md +734 -2
- package/dist/components/inputs/Calendar.md +655 -1
- package/dist/components/inputs/DatePicker.md +699 -3
- package/dist/components/inputs/DateRangePicker.md +815 -1
- package/dist/components/inputs/MonthPicker.md +626 -4
- package/dist/components/inputs/MonthRangePicker.md +682 -4
- package/dist/components/inputs/Select.md +600 -0
- package/dist/components/layout/Container.md +507 -0
- package/dist/components/navigation/Breadcrumbs.md +582 -0
- package/dist/components/navigation/IconMenuButton.md +693 -0
- package/dist/components/navigation/InsetDrawer.md +1150 -3
- package/dist/components/navigation/Link.md +526 -0
- package/dist/components/navigation/MenuButton.md +632 -0
- package/dist/components/navigation/NavigationGroup.md +401 -1
- package/dist/components/navigation/NavigationItem.md +311 -0
- package/dist/components/navigation/Navigator.md +373 -0
- package/dist/components/navigation/Pagination.md +521 -0
- package/dist/components/navigation/ProfileMenu.md +605 -0
- package/dist/components/navigation/Tabs.md +609 -7
- package/dist/components/surfaces/Accordions.md +947 -3
- package/dist/index.cjs +3 -1
- package/dist/index.js +3 -1
- package/dist/llms.txt +1 -1
- package/framer/index.js +1 -1
- package/package.json +3 -2
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
## Introduction
|
|
4
4
|
|
|
5
|
+
Pagination allows users to navigate through large datasets or content collections by dividing them into discrete pages. It provides intuitive controls for moving between pages, jumping to specific pages, and understanding the current position within the total dataset. Pagination comes in two variants: standard (page numbers) and compact (dropdown selector), making it suitable for different space constraints and use cases.
|
|
6
|
+
|
|
5
7
|
```tsx
|
|
6
8
|
<Stack spacing={4}>
|
|
7
9
|
<Stack spacing={1}>
|
|
@@ -23,4 +25,523 @@
|
|
|
23
25
|
|
|
24
26
|
```tsx
|
|
25
27
|
import { Pagination } from '@ceed/ads';
|
|
28
|
+
|
|
29
|
+
function DataList() {
|
|
30
|
+
const [page, setPage] = useState(1);
|
|
31
|
+
const pageSize = 10;
|
|
32
|
+
const totalItems = 250;
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<ItemList items={items} page={page} pageSize={pageSize} />
|
|
37
|
+
<Pagination
|
|
38
|
+
rowCount={totalItems}
|
|
39
|
+
paginationModel={{ page, pageSize }}
|
|
40
|
+
onPageChange={setPage}
|
|
41
|
+
/>
|
|
42
|
+
</>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Examples
|
|
48
|
+
|
|
49
|
+
### Playground
|
|
50
|
+
|
|
51
|
+
Both standard and compact variants displayed together.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
<Stack spacing={4}>
|
|
55
|
+
<Stack spacing={1}>
|
|
56
|
+
<div>Standard</div>
|
|
57
|
+
<Pagination {...args} variant="standard" />
|
|
58
|
+
</Stack>
|
|
59
|
+
<Stack spacing={1}>
|
|
60
|
+
<div>Compact</div>
|
|
61
|
+
<Pagination {...args} variant="compact" />
|
|
62
|
+
</Stack>
|
|
63
|
+
</Stack>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Sizes
|
|
67
|
+
|
|
68
|
+
Pagination supports three sizes for different layouts.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<Stack spacing={4}>
|
|
72
|
+
<Stack spacing={2}>
|
|
73
|
+
<div>Standard</div>
|
|
74
|
+
<Pagination {...args} variant="standard" size="sm" />
|
|
75
|
+
<Pagination {...args} variant="standard" size="md" />
|
|
76
|
+
<Pagination {...args} variant="standard" size="lg" />
|
|
77
|
+
</Stack>
|
|
78
|
+
<Stack spacing={2}>
|
|
79
|
+
<div>Compact</div>
|
|
80
|
+
<Pagination {...args} variant="compact" size="sm" />
|
|
81
|
+
<Pagination {...args} variant="compact" size="md" />
|
|
82
|
+
<Pagination {...args} variant="compact" size="lg" />
|
|
83
|
+
</Stack>
|
|
84
|
+
</Stack>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Pages
|
|
88
|
+
|
|
89
|
+
Navigation through different page positions.
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
<Stack spacing={4}>
|
|
93
|
+
<Stack spacing={2}>
|
|
94
|
+
<div>Standard</div>
|
|
95
|
+
<Pagination {...args} variant="standard" defaultPaginationModel={{
|
|
96
|
+
page: 1,
|
|
97
|
+
pageSize: 1
|
|
98
|
+
}} />
|
|
99
|
+
<Pagination {...args} variant="standard" defaultPaginationModel={{
|
|
100
|
+
page: 10,
|
|
101
|
+
pageSize: 1
|
|
102
|
+
}} />
|
|
103
|
+
<Pagination {...args} variant="standard" defaultPaginationModel={{
|
|
104
|
+
page: 20,
|
|
105
|
+
pageSize: 1
|
|
106
|
+
}} />
|
|
107
|
+
</Stack>
|
|
108
|
+
<Stack spacing={2}>
|
|
109
|
+
<div>Compact</div>
|
|
110
|
+
<Pagination {...args} variant="compact" defaultPaginationModel={{
|
|
111
|
+
page: 1,
|
|
112
|
+
pageSize: 1
|
|
113
|
+
}} />
|
|
114
|
+
<Pagination {...args} variant="compact" defaultPaginationModel={{
|
|
115
|
+
page: 10,
|
|
116
|
+
pageSize: 1
|
|
117
|
+
}} />
|
|
118
|
+
<Pagination {...args} variant="compact" defaultPaginationModel={{
|
|
119
|
+
page: 20,
|
|
120
|
+
pageSize: 1
|
|
121
|
+
}} />
|
|
122
|
+
</Stack>
|
|
123
|
+
</Stack>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Uncontrolled
|
|
127
|
+
|
|
128
|
+
Component manages its own page state.
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
<Pagination {...args} />
|
|
26
132
|
```
|
|
133
|
+
|
|
134
|
+
### Controlled
|
|
135
|
+
|
|
136
|
+
Parent component controls the page state.
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
<Pagination {...args} paginationModel={paginationModel} onPageChange={handlePageChange} />
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Change Row Count
|
|
143
|
+
|
|
144
|
+
Pagination automatically adjusts when total items change.
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
<Stack gap={2}>
|
|
148
|
+
<Pagination {...args} rowCount={rowCount} />
|
|
149
|
+
<Stack direction="row" gap={2}>
|
|
150
|
+
<Button onClick={() => setRowCount(rowCount - 1)}>Decrease Row count</Button>
|
|
151
|
+
<Button onClick={() => setRowCount(rowCount + 1)}>Increase Row count</Button>
|
|
152
|
+
</Stack>
|
|
153
|
+
</Stack>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## When to Use
|
|
157
|
+
|
|
158
|
+
### ✅ Good Use Cases
|
|
159
|
+
|
|
160
|
+
- **Data tables**: Navigate through paginated table data
|
|
161
|
+
- **Search results**: Browse through multiple pages of results
|
|
162
|
+
- **Content listings**: Articles, products, or any list content
|
|
163
|
+
- **Admin panels**: Managing records across multiple pages
|
|
164
|
+
- **API data**: When server returns paginated responses
|
|
165
|
+
|
|
166
|
+
### ❌ When Not to Use
|
|
167
|
+
|
|
168
|
+
- **Infinite scroll**: When content loads continuously on scroll
|
|
169
|
+
- **Small datasets**: Less than 20 items don't need pagination
|
|
170
|
+
- **Single content**: Individual articles or detail views
|
|
171
|
+
- **Sequential flows**: Use Stepper for multi-step processes
|
|
172
|
+
- **Real-time data**: Frequently updating data may shift pages unpredictably
|
|
173
|
+
|
|
174
|
+
## Common Use Cases
|
|
175
|
+
|
|
176
|
+
### Data Table Pagination
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
function DataTable({ columns, fetchData }) {
|
|
180
|
+
const [page, setPage] = useState(1);
|
|
181
|
+
const [pageSize, setPageSize] = useState(25);
|
|
182
|
+
const { data, totalCount, isLoading } = useFetchData(page, pageSize);
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<Box>
|
|
186
|
+
<Table columns={columns} data={data} loading={isLoading} />
|
|
187
|
+
<Stack direction="row" justifyContent="space-between" mt={2}>
|
|
188
|
+
<Typography level="body-sm">
|
|
189
|
+
Showing {(page - 1) * pageSize + 1} - {Math.min(page * pageSize, totalCount)} of {totalCount}
|
|
190
|
+
</Typography>
|
|
191
|
+
<Pagination
|
|
192
|
+
rowCount={totalCount}
|
|
193
|
+
paginationModel={{ page, pageSize }}
|
|
194
|
+
onPageChange={setPage}
|
|
195
|
+
/>
|
|
196
|
+
</Stack>
|
|
197
|
+
</Box>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Search Results
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
function SearchResults({ query }) {
|
|
206
|
+
const [page, setPage] = useState(1);
|
|
207
|
+
const { results, totalCount } = useSearch(query, page);
|
|
208
|
+
|
|
209
|
+
// Reset to page 1 when query changes
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
setPage(1);
|
|
212
|
+
}, [query]);
|
|
213
|
+
|
|
214
|
+
return (
|
|
215
|
+
<Stack spacing={2}>
|
|
216
|
+
<Typography level="body-sm">{totalCount} results for "{query}"</Typography>
|
|
217
|
+
<ResultList results={results} />
|
|
218
|
+
<Pagination
|
|
219
|
+
rowCount={totalCount}
|
|
220
|
+
defaultPaginationModel={{ page: 1, pageSize: 10 }}
|
|
221
|
+
onPageChange={setPage}
|
|
222
|
+
variant="compact"
|
|
223
|
+
/>
|
|
224
|
+
</Stack>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Gallery with Pagination
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
function Gallery({ images }) {
|
|
233
|
+
const pageSize = 12;
|
|
234
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
235
|
+
|
|
236
|
+
const paginatedImages = useMemo(() => {
|
|
237
|
+
const start = (currentPage - 1) * pageSize;
|
|
238
|
+
return images.slice(start, start + pageSize);
|
|
239
|
+
}, [images, currentPage, pageSize]);
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<Box>
|
|
243
|
+
<Grid container spacing={2}>
|
|
244
|
+
{paginatedImages.map((image) => (
|
|
245
|
+
<Grid key={image.id} xs={4}>
|
|
246
|
+
<ImageCard image={image} />
|
|
247
|
+
</Grid>
|
|
248
|
+
))}
|
|
249
|
+
</Grid>
|
|
250
|
+
<Box display="flex" justifyContent="center" mt={3}>
|
|
251
|
+
<Pagination
|
|
252
|
+
rowCount={images.length}
|
|
253
|
+
paginationModel={{ page: currentPage, pageSize }}
|
|
254
|
+
onPageChange={setCurrentPage}
|
|
255
|
+
/>
|
|
256
|
+
</Box>
|
|
257
|
+
</Box>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### API Pagination
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
function APIList() {
|
|
266
|
+
const [paginationModel, setPaginationModel] = useState({
|
|
267
|
+
page: 1,
|
|
268
|
+
pageSize: 20,
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const { data } = useQuery({
|
|
272
|
+
queryKey: ['items', paginationModel],
|
|
273
|
+
queryFn: () => fetchItems({
|
|
274
|
+
page: paginationModel.page,
|
|
275
|
+
limit: paginationModel.pageSize,
|
|
276
|
+
}),
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<Box>
|
|
281
|
+
<ItemList items={data?.items || []} />
|
|
282
|
+
<Pagination
|
|
283
|
+
rowCount={data?.totalCount || 0}
|
|
284
|
+
paginationModel={paginationModel}
|
|
285
|
+
onPageChange={(newPage) =>
|
|
286
|
+
setPaginationModel((prev) => ({ ...prev, page: newPage }))
|
|
287
|
+
}
|
|
288
|
+
/>
|
|
289
|
+
</Box>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Compact Pagination for Mobile
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
function ResponsivePagination({ rowCount, page, onPageChange }) {
|
|
298
|
+
const isMobile = useMediaQuery('(max-width: 600px)');
|
|
299
|
+
|
|
300
|
+
return (
|
|
301
|
+
<Pagination
|
|
302
|
+
rowCount={rowCount}
|
|
303
|
+
paginationModel={{ page, pageSize: 10 }}
|
|
304
|
+
onPageChange={onPageChange}
|
|
305
|
+
variant={isMobile ? 'compact' : 'standard'}
|
|
306
|
+
size={isMobile ? 'sm' : 'md'}
|
|
307
|
+
/>
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Props and Customization
|
|
313
|
+
|
|
314
|
+
### Key Props
|
|
315
|
+
|
|
316
|
+
| Prop | Type | Default | Description |
|
|
317
|
+
| ------------------------ | ------------------------------------ | --------------------------- | ---------------------------- |
|
|
318
|
+
| `rowCount` | `number` | - | Total number of items |
|
|
319
|
+
| `paginationModel` | `{ page: number; pageSize: number }` | - | Controlled pagination state |
|
|
320
|
+
| `defaultPaginationModel` | `{ page: number; pageSize: number }` | `{ page: 1, pageSize: 25 }` | Default state (uncontrolled) |
|
|
321
|
+
| `onPageChange` | `(newPage: number) => void` | - | Callback when page changes |
|
|
322
|
+
| `variant` | `'standard' \| 'compact'` | `'standard'` | Pagination style |
|
|
323
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Component size |
|
|
324
|
+
|
|
325
|
+
### Variant Comparison
|
|
326
|
+
|
|
327
|
+
| Feature | Standard | Compact |
|
|
328
|
+
| -------------------- | ------------ | ------------------- |
|
|
329
|
+
| Page numbers visible | Yes | No |
|
|
330
|
+
| Quick page jump | Click number | Dropdown select |
|
|
331
|
+
| Space required | More | Less |
|
|
332
|
+
| Best for | Desktop | Mobile/tight spaces |
|
|
333
|
+
|
|
334
|
+
### Controlled vs Uncontrolled
|
|
335
|
+
|
|
336
|
+
```tsx
|
|
337
|
+
// Uncontrolled - component manages state
|
|
338
|
+
<Pagination
|
|
339
|
+
rowCount={100}
|
|
340
|
+
defaultPaginationModel={{ page: 1, pageSize: 10 }}
|
|
341
|
+
onPageChange={(page) => console.log('Page:', page)}
|
|
342
|
+
/>
|
|
343
|
+
|
|
344
|
+
// Controlled - you manage state
|
|
345
|
+
const [page, setPage] = useState(1);
|
|
346
|
+
<Pagination
|
|
347
|
+
rowCount={100}
|
|
348
|
+
paginationModel={{ page, pageSize: 10 }}
|
|
349
|
+
onPageChange={setPage}
|
|
350
|
+
/>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Page Calculation
|
|
354
|
+
|
|
355
|
+
The component automatically calculates total pages:
|
|
356
|
+
|
|
357
|
+
```tsx
|
|
358
|
+
// With 95 items and pageSize of 10:
|
|
359
|
+
// totalPages = Math.ceil(95 / 10) = 10 pages
|
|
360
|
+
|
|
361
|
+
<Pagination
|
|
362
|
+
rowCount={95}
|
|
363
|
+
paginationModel={{ page: 1, pageSize: 10 }}
|
|
364
|
+
onPageChange={handleChange}
|
|
365
|
+
/>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Accessibility
|
|
369
|
+
|
|
370
|
+
Pagination includes built-in accessibility features:
|
|
371
|
+
|
|
372
|
+
### ARIA Attributes
|
|
373
|
+
|
|
374
|
+
- Current page marked with `aria-current="page"`
|
|
375
|
+
- Navigation buttons have descriptive `aria-label` attributes
|
|
376
|
+
- Disabled buttons properly marked with `disabled`
|
|
377
|
+
|
|
378
|
+
### Keyboard Navigation
|
|
379
|
+
|
|
380
|
+
- **Tab**: Move through pagination controls
|
|
381
|
+
- **Enter/Space**: Activate focused button
|
|
382
|
+
- **Arrow Keys**: Navigate within the compact dropdown
|
|
383
|
+
|
|
384
|
+
### Screen Reader Support
|
|
385
|
+
|
|
386
|
+
```tsx
|
|
387
|
+
// Buttons announce their purpose
|
|
388
|
+
<button aria-label="Previous page">←</button>
|
|
389
|
+
<button aria-label="Next page">→</button>
|
|
390
|
+
<button aria-label="More previous pages">...</button>
|
|
391
|
+
<button aria-current="page">5</button> // "Page 5, current"
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Status Announcements
|
|
395
|
+
|
|
396
|
+
Consider adding live region for page changes:
|
|
397
|
+
|
|
398
|
+
```tsx
|
|
399
|
+
function PaginatedList() {
|
|
400
|
+
const [page, setPage] = useState(1);
|
|
401
|
+
|
|
402
|
+
return (
|
|
403
|
+
<>
|
|
404
|
+
<div aria-live="polite" className="sr-only">
|
|
405
|
+
Page {page} of {totalPages}
|
|
406
|
+
</div>
|
|
407
|
+
<Pagination onPageChange={setPage} />
|
|
408
|
+
</>
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Best Practices
|
|
414
|
+
|
|
415
|
+
### ✅ Do
|
|
416
|
+
|
|
417
|
+
1. **Show context**: Display total items and current range
|
|
418
|
+
|
|
419
|
+
```tsx
|
|
420
|
+
// ✅ Good: Show pagination context
|
|
421
|
+
<Stack direction="row" justifyContent="space-between">
|
|
422
|
+
<Typography>Showing 1-25 of 250 items</Typography>
|
|
423
|
+
<Pagination rowCount={250} />
|
|
424
|
+
</Stack>
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
2. **Start from page 1**: Users expect 1-based pagination
|
|
428
|
+
|
|
429
|
+
```tsx
|
|
430
|
+
// ✅ Good: 1-based pagination
|
|
431
|
+
defaultPaginationModel={{ page: 1, pageSize: 25 }}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
3. **Handle empty states**: Show appropriate UI when there's no data
|
|
435
|
+
|
|
436
|
+
```tsx
|
|
437
|
+
{totalCount > 0 ? (
|
|
438
|
+
<Pagination rowCount={totalCount} />
|
|
439
|
+
) : (
|
|
440
|
+
<Typography>No results found</Typography>
|
|
441
|
+
)}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
4. **Reset on filter changes**: Return to page 1 when filters change
|
|
445
|
+
|
|
446
|
+
```tsx
|
|
447
|
+
useEffect(() => {
|
|
448
|
+
setPage(1);
|
|
449
|
+
}, [filters]);
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### ❌ Don't
|
|
453
|
+
|
|
454
|
+
1. **Don't use for very small datasets**: Pagination adds complexity
|
|
455
|
+
|
|
456
|
+
```tsx
|
|
457
|
+
// ❌ Bad: Pagination for 5 items
|
|
458
|
+
<Pagination rowCount={5} />
|
|
459
|
+
|
|
460
|
+
// ✅ Good: Just show all items
|
|
461
|
+
<ItemList items={items} />
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
2. **Don't hide the page count**: Users need to know how many pages exist
|
|
465
|
+
|
|
466
|
+
3. **Don't use inconsistent page sizes**: Keep pageSize consistent in session
|
|
467
|
+
|
|
468
|
+
4. **Don't forget loading states**: Show loading while fetching page data
|
|
469
|
+
|
|
470
|
+
```tsx
|
|
471
|
+
// ✅ Good: Handle loading
|
|
472
|
+
<Pagination disabled={isLoading} />
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## Performance Considerations
|
|
476
|
+
|
|
477
|
+
### Server-Side Pagination
|
|
478
|
+
|
|
479
|
+
For large datasets, paginate on the server:
|
|
480
|
+
|
|
481
|
+
```tsx
|
|
482
|
+
function ServerPaginatedList() {
|
|
483
|
+
const [page, setPage] = useState(1);
|
|
484
|
+
const pageSize = 25;
|
|
485
|
+
|
|
486
|
+
const { data, isLoading } = useQuery({
|
|
487
|
+
queryKey: ['items', page, pageSize],
|
|
488
|
+
queryFn: () => api.getItems({ page, pageSize }),
|
|
489
|
+
keepPreviousData: true, // Keep old data while loading
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
return (
|
|
493
|
+
<>
|
|
494
|
+
<ItemList items={data?.items} loading={isLoading} />
|
|
495
|
+
<Pagination
|
|
496
|
+
rowCount={data?.totalCount || 0}
|
|
497
|
+
paginationModel={{ page, pageSize }}
|
|
498
|
+
onPageChange={setPage}
|
|
499
|
+
/>
|
|
500
|
+
</>
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Memoize Handlers
|
|
506
|
+
|
|
507
|
+
When used in complex components, memoize the change handler:
|
|
508
|
+
|
|
509
|
+
```tsx
|
|
510
|
+
const handlePageChange = useCallback((newPage) => {
|
|
511
|
+
setPage(newPage);
|
|
512
|
+
}, []);
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
### Virtualization Alternative
|
|
516
|
+
|
|
517
|
+
For very large datasets, consider virtualization instead of pagination:
|
|
518
|
+
|
|
519
|
+
```tsx
|
|
520
|
+
// Instead of pagination for 10,000+ items:
|
|
521
|
+
<VirtualizedList items={items} itemHeight={50} />
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### URL Sync
|
|
525
|
+
|
|
526
|
+
For shareable pagination state, sync with URL:
|
|
527
|
+
|
|
528
|
+
```tsx
|
|
529
|
+
function URLPaginatedList() {
|
|
530
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
531
|
+
const page = parseInt(searchParams.get('page') || '1', 10);
|
|
532
|
+
|
|
533
|
+
const handlePageChange = (newPage) => {
|
|
534
|
+
setSearchParams({ page: String(newPage) });
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
return (
|
|
538
|
+
<Pagination
|
|
539
|
+
rowCount={totalCount}
|
|
540
|
+
paginationModel={{ page, pageSize: 25 }}
|
|
541
|
+
onPageChange={handlePageChange}
|
|
542
|
+
/>
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Pagination is essential for managing large datasets in admin interfaces. Choose between standard and compact variants based on available space and user needs, ensuring a smooth navigation experience through your data.
|