@lglab/compose-ui-mcp 0.0.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/README.md +11 -0
- package/dist/assets/llms/accordion.md +184 -0
- package/dist/assets/llms/alert-dialog.md +306 -0
- package/dist/assets/llms/autocomplete.md +756 -0
- package/dist/assets/llms/avatar.md +166 -0
- package/dist/assets/llms/badge.md +478 -0
- package/dist/assets/llms/button.md +238 -0
- package/dist/assets/llms/card.md +264 -0
- package/dist/assets/llms/checkbox-group.md +158 -0
- package/dist/assets/llms/checkbox.md +83 -0
- package/dist/assets/llms/collapsible.md +165 -0
- package/dist/assets/llms/combobox.md +1255 -0
- package/dist/assets/llms/context-menu.md +371 -0
- package/dist/assets/llms/dialog.md +592 -0
- package/dist/assets/llms/drawer.md +437 -0
- package/dist/assets/llms/field.md +74 -0
- package/dist/assets/llms/form.md +1931 -0
- package/dist/assets/llms/input.md +47 -0
- package/dist/assets/llms/menu.md +484 -0
- package/dist/assets/llms/menubar.md +804 -0
- package/dist/assets/llms/meter.md +181 -0
- package/dist/assets/llms/navigation-menu.md +187 -0
- package/dist/assets/llms/number-field.md +243 -0
- package/dist/assets/llms/pagination.md +514 -0
- package/dist/assets/llms/popover.md +206 -0
- package/dist/assets/llms/preview-card.md +146 -0
- package/dist/assets/llms/progress.md +60 -0
- package/dist/assets/llms/radio-group.md +105 -0
- package/dist/assets/llms/scroll-area.md +132 -0
- package/dist/assets/llms/select.md +276 -0
- package/dist/assets/llms/separator.md +49 -0
- package/dist/assets/llms/skeleton.md +96 -0
- package/dist/assets/llms/slider.md +161 -0
- package/dist/assets/llms/switch.md +101 -0
- package/dist/assets/llms/table.md +1325 -0
- package/dist/assets/llms/tabs.md +327 -0
- package/dist/assets/llms/textarea.md +38 -0
- package/dist/assets/llms/toast.md +349 -0
- package/dist/assets/llms/toggle-group.md +261 -0
- package/dist/assets/llms/toggle.md +161 -0
- package/dist/assets/llms/toolbar.md +148 -0
- package/dist/assets/llms/tooltip.md +486 -0
- package/dist/assets/llms-full.txt +14515 -0
- package/dist/assets/llms.txt +65 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +161 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
# Pagination
|
|
2
|
+
|
|
3
|
+
A composable pagination component for navigating through paginated content. Use with tables, search results, or any paginated data.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lglab/compose-ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Import
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { // eslint-disable-next-line react-refresh/only-export-components
|
|
15
|
+
usePagination, PaginationRoot, PaginationContent, PaginationItem, PaginationButton, PaginationPrevious, PaginationNext, PaginationFirst, PaginationLast, PaginationEllipsis } from '@lglab/compose-ui'
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### Default
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import {
|
|
24
|
+
PaginationButton,
|
|
25
|
+
PaginationContent,
|
|
26
|
+
PaginationEllipsis,
|
|
27
|
+
PaginationItem,
|
|
28
|
+
PaginationNext,
|
|
29
|
+
PaginationPrevious,
|
|
30
|
+
PaginationRoot,
|
|
31
|
+
usePagination,
|
|
32
|
+
} from '@lglab/compose-ui/pagination'
|
|
33
|
+
import { ChevronLeft, ChevronRight, Ellipsis } from 'lucide-react'
|
|
34
|
+
import { useState } from 'react'
|
|
35
|
+
|
|
36
|
+
export default function DefaultExample() {
|
|
37
|
+
const [currentPage, setCurrentPage] = useState(1)
|
|
38
|
+
const totalPages = 5
|
|
39
|
+
|
|
40
|
+
const { pages, canGoPrevious, canGoNext, goToPrevious, goToNext, goToPage } =
|
|
41
|
+
usePagination({
|
|
42
|
+
currentPage,
|
|
43
|
+
totalPages,
|
|
44
|
+
onPageChange: setCurrentPage,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<PaginationRoot className='mx-auto'>
|
|
49
|
+
<PaginationContent>
|
|
50
|
+
<PaginationItem>
|
|
51
|
+
<PaginationPrevious onClick={goToPrevious} disabled={!canGoPrevious}>
|
|
52
|
+
<ChevronLeft className='size-4' />
|
|
53
|
+
</PaginationPrevious>
|
|
54
|
+
</PaginationItem>
|
|
55
|
+
|
|
56
|
+
{pages.map((page, i) => (
|
|
57
|
+
<PaginationItem key={i}>
|
|
58
|
+
{page === 'ellipsis' ? (
|
|
59
|
+
<PaginationEllipsis>
|
|
60
|
+
<Ellipsis className='size-4' />
|
|
61
|
+
</PaginationEllipsis>
|
|
62
|
+
) : (
|
|
63
|
+
<PaginationButton
|
|
64
|
+
isActive={page === currentPage}
|
|
65
|
+
onClick={() => goToPage(page)}
|
|
66
|
+
>
|
|
67
|
+
{page}
|
|
68
|
+
</PaginationButton>
|
|
69
|
+
)}
|
|
70
|
+
</PaginationItem>
|
|
71
|
+
))}
|
|
72
|
+
|
|
73
|
+
<PaginationItem>
|
|
74
|
+
<PaginationNext onClick={goToNext} disabled={!canGoNext}>
|
|
75
|
+
<ChevronRight className='size-4' />
|
|
76
|
+
</PaginationNext>
|
|
77
|
+
</PaginationItem>
|
|
78
|
+
</PaginationContent>
|
|
79
|
+
</PaginationRoot>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### With Ellipsis
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import {
|
|
88
|
+
PaginationButton,
|
|
89
|
+
PaginationContent,
|
|
90
|
+
PaginationEllipsis,
|
|
91
|
+
PaginationItem,
|
|
92
|
+
PaginationNext,
|
|
93
|
+
PaginationPrevious,
|
|
94
|
+
PaginationRoot,
|
|
95
|
+
usePagination,
|
|
96
|
+
} from '@lglab/compose-ui/pagination'
|
|
97
|
+
import { ChevronLeft, ChevronRight, Ellipsis } from 'lucide-react'
|
|
98
|
+
import { useState } from 'react'
|
|
99
|
+
|
|
100
|
+
export default function WithEllipsisExample() {
|
|
101
|
+
const [currentPage, setCurrentPage] = useState(5)
|
|
102
|
+
const totalPages = 20
|
|
103
|
+
|
|
104
|
+
const { pages, canGoPrevious, canGoNext, goToPrevious, goToNext, goToPage } =
|
|
105
|
+
usePagination({
|
|
106
|
+
currentPage,
|
|
107
|
+
totalPages,
|
|
108
|
+
onPageChange: setCurrentPage,
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<PaginationRoot>
|
|
113
|
+
<PaginationContent>
|
|
114
|
+
<PaginationItem>
|
|
115
|
+
<PaginationPrevious onClick={goToPrevious} disabled={!canGoPrevious}>
|
|
116
|
+
<ChevronLeft className='size-4' />
|
|
117
|
+
</PaginationPrevious>
|
|
118
|
+
</PaginationItem>
|
|
119
|
+
|
|
120
|
+
{pages.map((page, i) => (
|
|
121
|
+
<PaginationItem key={i}>
|
|
122
|
+
{page === 'ellipsis' ? (
|
|
123
|
+
<PaginationEllipsis>
|
|
124
|
+
<Ellipsis className='size-4' />
|
|
125
|
+
</PaginationEllipsis>
|
|
126
|
+
) : (
|
|
127
|
+
<PaginationButton
|
|
128
|
+
isActive={page === currentPage}
|
|
129
|
+
onClick={() => goToPage(page)}
|
|
130
|
+
>
|
|
131
|
+
{page}
|
|
132
|
+
</PaginationButton>
|
|
133
|
+
)}
|
|
134
|
+
</PaginationItem>
|
|
135
|
+
))}
|
|
136
|
+
|
|
137
|
+
<PaginationItem>
|
|
138
|
+
<PaginationNext onClick={goToNext} disabled={!canGoNext}>
|
|
139
|
+
<ChevronRight className='size-4' />
|
|
140
|
+
</PaginationNext>
|
|
141
|
+
</PaginationItem>
|
|
142
|
+
</PaginationContent>
|
|
143
|
+
</PaginationRoot>
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### With First/Last
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
import {
|
|
152
|
+
PaginationButton,
|
|
153
|
+
PaginationContent,
|
|
154
|
+
PaginationEllipsis,
|
|
155
|
+
PaginationFirst,
|
|
156
|
+
PaginationItem,
|
|
157
|
+
PaginationLast,
|
|
158
|
+
PaginationNext,
|
|
159
|
+
PaginationPrevious,
|
|
160
|
+
PaginationRoot,
|
|
161
|
+
usePagination,
|
|
162
|
+
} from '@lglab/compose-ui/pagination'
|
|
163
|
+
import {
|
|
164
|
+
ChevronLeft,
|
|
165
|
+
ChevronRight,
|
|
166
|
+
ChevronsLeft,
|
|
167
|
+
ChevronsRight,
|
|
168
|
+
Ellipsis,
|
|
169
|
+
} from 'lucide-react'
|
|
170
|
+
import { useState } from 'react'
|
|
171
|
+
|
|
172
|
+
export default function WithFirstLastExample() {
|
|
173
|
+
const [currentPage, setCurrentPage] = useState(10)
|
|
174
|
+
const totalPages = 20
|
|
175
|
+
|
|
176
|
+
const {
|
|
177
|
+
pages,
|
|
178
|
+
canGoPrevious,
|
|
179
|
+
canGoNext,
|
|
180
|
+
goToPrevious,
|
|
181
|
+
goToNext,
|
|
182
|
+
goToFirst,
|
|
183
|
+
goToLast,
|
|
184
|
+
goToPage,
|
|
185
|
+
} = usePagination({
|
|
186
|
+
currentPage,
|
|
187
|
+
totalPages,
|
|
188
|
+
onPageChange: setCurrentPage,
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<PaginationRoot>
|
|
193
|
+
<PaginationContent>
|
|
194
|
+
<PaginationItem>
|
|
195
|
+
<PaginationFirst onClick={goToFirst} disabled={!canGoPrevious}>
|
|
196
|
+
<ChevronsLeft className='size-4' />
|
|
197
|
+
</PaginationFirst>
|
|
198
|
+
</PaginationItem>
|
|
199
|
+
|
|
200
|
+
<PaginationItem>
|
|
201
|
+
<PaginationPrevious onClick={goToPrevious} disabled={!canGoPrevious}>
|
|
202
|
+
<ChevronLeft className='size-4' />
|
|
203
|
+
</PaginationPrevious>
|
|
204
|
+
</PaginationItem>
|
|
205
|
+
|
|
206
|
+
{pages.map((page, i) => (
|
|
207
|
+
<PaginationItem key={i}>
|
|
208
|
+
{page === 'ellipsis' ? (
|
|
209
|
+
<PaginationEllipsis>
|
|
210
|
+
<Ellipsis className='size-4' />
|
|
211
|
+
</PaginationEllipsis>
|
|
212
|
+
) : (
|
|
213
|
+
<PaginationButton
|
|
214
|
+
isActive={page === currentPage}
|
|
215
|
+
onClick={() => goToPage(page)}
|
|
216
|
+
>
|
|
217
|
+
{page}
|
|
218
|
+
</PaginationButton>
|
|
219
|
+
)}
|
|
220
|
+
</PaginationItem>
|
|
221
|
+
))}
|
|
222
|
+
|
|
223
|
+
<PaginationItem>
|
|
224
|
+
<PaginationNext onClick={goToNext} disabled={!canGoNext}>
|
|
225
|
+
<ChevronRight className='size-4' />
|
|
226
|
+
</PaginationNext>
|
|
227
|
+
</PaginationItem>
|
|
228
|
+
|
|
229
|
+
<PaginationItem>
|
|
230
|
+
<PaginationLast onClick={goToLast} disabled={!canGoNext}>
|
|
231
|
+
<ChevronsRight className='size-4' />
|
|
232
|
+
</PaginationLast>
|
|
233
|
+
</PaginationItem>
|
|
234
|
+
</PaginationContent>
|
|
235
|
+
</PaginationRoot>
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Page Size
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
import {
|
|
244
|
+
PaginationButton,
|
|
245
|
+
PaginationContent,
|
|
246
|
+
PaginationEllipsis,
|
|
247
|
+
PaginationItem,
|
|
248
|
+
PaginationNext,
|
|
249
|
+
PaginationPrevious,
|
|
250
|
+
PaginationRoot,
|
|
251
|
+
usePagination,
|
|
252
|
+
} from '@lglab/compose-ui/pagination'
|
|
253
|
+
import {
|
|
254
|
+
SelectIcon,
|
|
255
|
+
SelectItem,
|
|
256
|
+
SelectItemIndicator,
|
|
257
|
+
SelectItemText,
|
|
258
|
+
SelectList,
|
|
259
|
+
SelectPopup,
|
|
260
|
+
SelectPortal,
|
|
261
|
+
SelectPositioner,
|
|
262
|
+
SelectRoot,
|
|
263
|
+
SelectTrigger,
|
|
264
|
+
SelectValue,
|
|
265
|
+
} from '@lglab/compose-ui/select'
|
|
266
|
+
import { Check, ChevronLeft, ChevronRight, ChevronsUpDown, Ellipsis } from 'lucide-react'
|
|
267
|
+
import { useState } from 'react'
|
|
268
|
+
|
|
269
|
+
export default function WithPageSizeExample() {
|
|
270
|
+
const [currentPage, setCurrentPage] = useState(1)
|
|
271
|
+
const [pageSize, setPageSize] = useState(10)
|
|
272
|
+
|
|
273
|
+
const totalItems = 235
|
|
274
|
+
const totalPages = Math.ceil(totalItems / pageSize)
|
|
275
|
+
|
|
276
|
+
const {
|
|
277
|
+
pages,
|
|
278
|
+
canGoPrevious,
|
|
279
|
+
canGoNext,
|
|
280
|
+
goToPrevious,
|
|
281
|
+
goToNext,
|
|
282
|
+
goToPage,
|
|
283
|
+
pageSizeOptions,
|
|
284
|
+
setPageSize: handleSetPageSize,
|
|
285
|
+
} = usePagination({
|
|
286
|
+
currentPage,
|
|
287
|
+
totalPages,
|
|
288
|
+
onPageChange: setCurrentPage,
|
|
289
|
+
pageSize,
|
|
290
|
+
onPageSizeChange: (size) => {
|
|
291
|
+
setPageSize(size)
|
|
292
|
+
setCurrentPage(1)
|
|
293
|
+
},
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
const pageSizeItems = pageSizeOptions.map((size) => ({
|
|
297
|
+
label: `${size} per page`,
|
|
298
|
+
value: size,
|
|
299
|
+
}))
|
|
300
|
+
|
|
301
|
+
return (
|
|
302
|
+
<div className='flex flex-wrap gap-2 items-center'>
|
|
303
|
+
<PaginationRoot>
|
|
304
|
+
<PaginationContent>
|
|
305
|
+
<PaginationItem>
|
|
306
|
+
<PaginationPrevious onClick={goToPrevious} disabled={!canGoPrevious}>
|
|
307
|
+
<ChevronLeft className='size-4' />
|
|
308
|
+
</PaginationPrevious>
|
|
309
|
+
</PaginationItem>
|
|
310
|
+
|
|
311
|
+
{pages.map((page, i) => (
|
|
312
|
+
<PaginationItem key={i}>
|
|
313
|
+
{page === 'ellipsis' ? (
|
|
314
|
+
<PaginationEllipsis>
|
|
315
|
+
<Ellipsis className='size-4' />
|
|
316
|
+
</PaginationEllipsis>
|
|
317
|
+
) : (
|
|
318
|
+
<PaginationButton
|
|
319
|
+
isActive={page === currentPage}
|
|
320
|
+
onClick={() => goToPage(page)}
|
|
321
|
+
>
|
|
322
|
+
{page}
|
|
323
|
+
</PaginationButton>
|
|
324
|
+
)}
|
|
325
|
+
</PaginationItem>
|
|
326
|
+
))}
|
|
327
|
+
|
|
328
|
+
<PaginationItem>
|
|
329
|
+
<PaginationNext onClick={goToNext} disabled={!canGoNext}>
|
|
330
|
+
<ChevronRight className='size-4' />
|
|
331
|
+
</PaginationNext>
|
|
332
|
+
</PaginationItem>
|
|
333
|
+
</PaginationContent>
|
|
334
|
+
</PaginationRoot>
|
|
335
|
+
|
|
336
|
+
<SelectRoot
|
|
337
|
+
value={pageSize}
|
|
338
|
+
onValueChange={(value) => value && handleSetPageSize(value)}
|
|
339
|
+
items={pageSizeItems}
|
|
340
|
+
>
|
|
341
|
+
<SelectTrigger aria-label='Select page size' className='min-w-32 min-h-8'>
|
|
342
|
+
<SelectValue placeholder='Page size' />
|
|
343
|
+
<SelectIcon>
|
|
344
|
+
<ChevronsUpDown className='size-4' />
|
|
345
|
+
</SelectIcon>
|
|
346
|
+
</SelectTrigger>
|
|
347
|
+
<SelectPortal>
|
|
348
|
+
<SelectPositioner>
|
|
349
|
+
<SelectPopup>
|
|
350
|
+
<SelectList>
|
|
351
|
+
{pageSizeItems.map(({ label, value }) => (
|
|
352
|
+
<SelectItem key={value} value={value}>
|
|
353
|
+
<SelectItemText>{label}</SelectItemText>
|
|
354
|
+
<SelectItemIndicator>
|
|
355
|
+
<Check className='size-3.5' />
|
|
356
|
+
</SelectItemIndicator>
|
|
357
|
+
</SelectItem>
|
|
358
|
+
))}
|
|
359
|
+
</SelectList>
|
|
360
|
+
</SelectPopup>
|
|
361
|
+
</SelectPositioner>
|
|
362
|
+
</SelectPortal>
|
|
363
|
+
</SelectRoot>
|
|
364
|
+
</div>
|
|
365
|
+
)
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Sizes
|
|
370
|
+
|
|
371
|
+
```tsx
|
|
372
|
+
import {
|
|
373
|
+
PaginationButton,
|
|
374
|
+
PaginationContent,
|
|
375
|
+
PaginationEllipsis,
|
|
376
|
+
PaginationItem,
|
|
377
|
+
PaginationNext,
|
|
378
|
+
PaginationPrevious,
|
|
379
|
+
PaginationRoot,
|
|
380
|
+
usePagination,
|
|
381
|
+
} from '@lglab/compose-ui/pagination'
|
|
382
|
+
import { ChevronLeft, ChevronRight, Ellipsis } from 'lucide-react'
|
|
383
|
+
import { useState } from 'react'
|
|
384
|
+
|
|
385
|
+
export default function SizesExample() {
|
|
386
|
+
const [currentPage, setCurrentPage] = useState(1)
|
|
387
|
+
const totalPages = 5
|
|
388
|
+
|
|
389
|
+
const { pages, canGoPrevious, canGoNext, goToPrevious, goToNext, goToPage } =
|
|
390
|
+
usePagination({
|
|
391
|
+
currentPage,
|
|
392
|
+
totalPages,
|
|
393
|
+
onPageChange: setCurrentPage,
|
|
394
|
+
})
|
|
395
|
+
|
|
396
|
+
return (
|
|
397
|
+
<div className='flex flex-col gap-6 items-center'>
|
|
398
|
+
<PaginationRoot>
|
|
399
|
+
<PaginationContent>
|
|
400
|
+
<PaginationItem>
|
|
401
|
+
<PaginationPrevious onClick={goToPrevious} disabled={!canGoPrevious}>
|
|
402
|
+
<ChevronLeft className='size-4' />
|
|
403
|
+
</PaginationPrevious>
|
|
404
|
+
</PaginationItem>
|
|
405
|
+
|
|
406
|
+
{pages.map((page, i) => (
|
|
407
|
+
<PaginationItem key={i}>
|
|
408
|
+
{page === 'ellipsis' ? (
|
|
409
|
+
<PaginationEllipsis>
|
|
410
|
+
<Ellipsis className='size-4' />
|
|
411
|
+
</PaginationEllipsis>
|
|
412
|
+
) : (
|
|
413
|
+
<PaginationButton
|
|
414
|
+
isActive={page === currentPage}
|
|
415
|
+
onClick={() => goToPage(page)}
|
|
416
|
+
>
|
|
417
|
+
{page}
|
|
418
|
+
</PaginationButton>
|
|
419
|
+
)}
|
|
420
|
+
</PaginationItem>
|
|
421
|
+
))}
|
|
422
|
+
|
|
423
|
+
<PaginationItem>
|
|
424
|
+
<PaginationNext onClick={goToNext} disabled={!canGoNext}>
|
|
425
|
+
<ChevronRight className='size-4' />
|
|
426
|
+
</PaginationNext>
|
|
427
|
+
</PaginationItem>
|
|
428
|
+
</PaginationContent>
|
|
429
|
+
</PaginationRoot>
|
|
430
|
+
|
|
431
|
+
<PaginationRoot>
|
|
432
|
+
<PaginationContent>
|
|
433
|
+
<PaginationItem>
|
|
434
|
+
<PaginationPrevious
|
|
435
|
+
size='icon'
|
|
436
|
+
onClick={goToPrevious}
|
|
437
|
+
disabled={!canGoPrevious}
|
|
438
|
+
>
|
|
439
|
+
<ChevronLeft className='size-4' />
|
|
440
|
+
</PaginationPrevious>
|
|
441
|
+
</PaginationItem>
|
|
442
|
+
|
|
443
|
+
{pages.map((page, i) => (
|
|
444
|
+
<PaginationItem key={i}>
|
|
445
|
+
{page === 'ellipsis' ? (
|
|
446
|
+
<PaginationEllipsis size='icon'>
|
|
447
|
+
<Ellipsis className='size-4' />
|
|
448
|
+
</PaginationEllipsis>
|
|
449
|
+
) : (
|
|
450
|
+
<PaginationButton
|
|
451
|
+
size='icon'
|
|
452
|
+
isActive={page === currentPage}
|
|
453
|
+
onClick={() => goToPage(page)}
|
|
454
|
+
>
|
|
455
|
+
{page}
|
|
456
|
+
</PaginationButton>
|
|
457
|
+
)}
|
|
458
|
+
</PaginationItem>
|
|
459
|
+
))}
|
|
460
|
+
|
|
461
|
+
<PaginationItem>
|
|
462
|
+
<PaginationNext size='icon' onClick={goToNext} disabled={!canGoNext}>
|
|
463
|
+
<ChevronRight className='size-4' />
|
|
464
|
+
</PaginationNext>
|
|
465
|
+
</PaginationItem>
|
|
466
|
+
</PaginationContent>
|
|
467
|
+
</PaginationRoot>
|
|
468
|
+
|
|
469
|
+
<PaginationRoot>
|
|
470
|
+
<PaginationContent>
|
|
471
|
+
<PaginationItem>
|
|
472
|
+
<PaginationPrevious
|
|
473
|
+
size='icon-lg'
|
|
474
|
+
onClick={goToPrevious}
|
|
475
|
+
disabled={!canGoPrevious}
|
|
476
|
+
>
|
|
477
|
+
<ChevronLeft className='size-4' />
|
|
478
|
+
</PaginationPrevious>
|
|
479
|
+
</PaginationItem>
|
|
480
|
+
|
|
481
|
+
{pages.map((page, i) => (
|
|
482
|
+
<PaginationItem key={i}>
|
|
483
|
+
{page === 'ellipsis' ? (
|
|
484
|
+
<PaginationEllipsis size='icon-lg'>
|
|
485
|
+
<Ellipsis className='size-4' />
|
|
486
|
+
</PaginationEllipsis>
|
|
487
|
+
) : (
|
|
488
|
+
<PaginationButton
|
|
489
|
+
size='icon-lg'
|
|
490
|
+
isActive={page === currentPage}
|
|
491
|
+
onClick={() => goToPage(page)}
|
|
492
|
+
>
|
|
493
|
+
{page}
|
|
494
|
+
</PaginationButton>
|
|
495
|
+
)}
|
|
496
|
+
</PaginationItem>
|
|
497
|
+
))}
|
|
498
|
+
|
|
499
|
+
<PaginationItem>
|
|
500
|
+
<PaginationNext size='icon-lg' onClick={goToNext} disabled={!canGoNext}>
|
|
501
|
+
<ChevronRight className='size-4' />
|
|
502
|
+
</PaginationNext>
|
|
503
|
+
</PaginationItem>
|
|
504
|
+
</PaginationContent>
|
|
505
|
+
</PaginationRoot>
|
|
506
|
+
</div>
|
|
507
|
+
)
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
## Resources
|
|
512
|
+
|
|
513
|
+
- [Base UI Pagination Documentation](https://base-ui.com/react/components/pagination)
|
|
514
|
+
- [API Reference](https://base-ui.com/react/components/pagination#api-reference)
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Popover
|
|
2
|
+
|
|
3
|
+
An accessible popup anchored to a button.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lglab/compose-ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Import
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { PopoverRoot, PopoverTrigger, PopoverPortal, PopoverBackdrop, PopoverPositioner, PopoverPopup, PopoverArrow, PopoverTitle, PopoverDescription, PopoverClose, PopoverViewport } from '@lglab/compose-ui'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Examples
|
|
18
|
+
|
|
19
|
+
### Basic
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { Button } from '@lglab/compose-ui/button'
|
|
23
|
+
import {
|
|
24
|
+
PopoverArrow,
|
|
25
|
+
PopoverDescription,
|
|
26
|
+
PopoverPopup,
|
|
27
|
+
PopoverPortal,
|
|
28
|
+
PopoverPositioner,
|
|
29
|
+
PopoverRoot,
|
|
30
|
+
PopoverTitle,
|
|
31
|
+
PopoverTrigger,
|
|
32
|
+
} from '@lglab/compose-ui/popover'
|
|
33
|
+
import { Bell } from 'lucide-react'
|
|
34
|
+
|
|
35
|
+
export default function DefaultExample() {
|
|
36
|
+
return (
|
|
37
|
+
<PopoverRoot>
|
|
38
|
+
<PopoverTrigger
|
|
39
|
+
render={(props) => (
|
|
40
|
+
<Button {...props} variant='outline' size='icon'>
|
|
41
|
+
<Bell className='size-4' aria-label='Notifications' />
|
|
42
|
+
</Button>
|
|
43
|
+
)}
|
|
44
|
+
/>
|
|
45
|
+
<PopoverPortal>
|
|
46
|
+
<PopoverPositioner>
|
|
47
|
+
<PopoverPopup className='space-y-0.5'>
|
|
48
|
+
<PopoverArrow />
|
|
49
|
+
<PopoverTitle>Notifications</PopoverTitle>
|
|
50
|
+
<PopoverDescription>You are all caught up. Good job!</PopoverDescription>
|
|
51
|
+
</PopoverPopup>
|
|
52
|
+
</PopoverPositioner>
|
|
53
|
+
</PopoverPortal>
|
|
54
|
+
</PopoverRoot>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Open on Hover
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { Button } from '@lglab/compose-ui/button'
|
|
63
|
+
import {
|
|
64
|
+
PopoverArrow,
|
|
65
|
+
PopoverDescription,
|
|
66
|
+
PopoverPopup,
|
|
67
|
+
PopoverPortal,
|
|
68
|
+
PopoverPositioner,
|
|
69
|
+
PopoverRoot,
|
|
70
|
+
PopoverTitle,
|
|
71
|
+
PopoverTrigger,
|
|
72
|
+
} from '@lglab/compose-ui/popover'
|
|
73
|
+
import { Bell } from 'lucide-react'
|
|
74
|
+
|
|
75
|
+
export default function OpenOnHoverExample() {
|
|
76
|
+
return (
|
|
77
|
+
<PopoverRoot>
|
|
78
|
+
<PopoverTrigger
|
|
79
|
+
openOnHover
|
|
80
|
+
delay={300}
|
|
81
|
+
render={(props) => (
|
|
82
|
+
<Button {...props} variant='outline' size='icon'>
|
|
83
|
+
<Bell className='size-4' aria-label='Notifications' />
|
|
84
|
+
</Button>
|
|
85
|
+
)}
|
|
86
|
+
/>
|
|
87
|
+
<PopoverPortal>
|
|
88
|
+
<PopoverPositioner>
|
|
89
|
+
<PopoverPopup className='space-y-0.5'>
|
|
90
|
+
<PopoverArrow />
|
|
91
|
+
<PopoverTitle>Notifications</PopoverTitle>
|
|
92
|
+
<PopoverDescription>
|
|
93
|
+
Hover over the bell icon to see this popover. It opens after a 300ms delay.
|
|
94
|
+
</PopoverDescription>
|
|
95
|
+
</PopoverPopup>
|
|
96
|
+
</PopoverPositioner>
|
|
97
|
+
</PopoverPortal>
|
|
98
|
+
</PopoverRoot>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### With Close Button
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { Button } from '@lglab/compose-ui/button'
|
|
107
|
+
import {
|
|
108
|
+
PopoverArrow,
|
|
109
|
+
PopoverClose,
|
|
110
|
+
PopoverDescription,
|
|
111
|
+
PopoverPopup,
|
|
112
|
+
PopoverPortal,
|
|
113
|
+
PopoverPositioner,
|
|
114
|
+
PopoverRoot,
|
|
115
|
+
PopoverTitle,
|
|
116
|
+
PopoverTrigger,
|
|
117
|
+
} from '@lglab/compose-ui/popover'
|
|
118
|
+
import { Bell } from 'lucide-react'
|
|
119
|
+
|
|
120
|
+
export default function WithCloseExample() {
|
|
121
|
+
return (
|
|
122
|
+
<PopoverRoot>
|
|
123
|
+
<PopoverTrigger
|
|
124
|
+
render={(props) => (
|
|
125
|
+
<Button {...props} variant='outline' size='icon'>
|
|
126
|
+
<Bell className='size-4' aria-label='Notifications' />
|
|
127
|
+
</Button>
|
|
128
|
+
)}
|
|
129
|
+
/>
|
|
130
|
+
<PopoverPortal>
|
|
131
|
+
<PopoverPositioner>
|
|
132
|
+
<PopoverPopup className='space-y-0.5'>
|
|
133
|
+
<PopoverArrow />
|
|
134
|
+
<PopoverTitle>Notifications</PopoverTitle>
|
|
135
|
+
<PopoverDescription>
|
|
136
|
+
You have 3 new notifications. Click the close button to dismiss this
|
|
137
|
+
popover.
|
|
138
|
+
</PopoverDescription>
|
|
139
|
+
<div className='mt-4 flex justify-end'>
|
|
140
|
+
<PopoverClose
|
|
141
|
+
render={(props) => (
|
|
142
|
+
<Button {...props} variant='outline' size='sm'>
|
|
143
|
+
Close
|
|
144
|
+
</Button>
|
|
145
|
+
)}
|
|
146
|
+
/>
|
|
147
|
+
</div>
|
|
148
|
+
</PopoverPopup>
|
|
149
|
+
</PopoverPositioner>
|
|
150
|
+
</PopoverPortal>
|
|
151
|
+
</PopoverRoot>
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Sides
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
import { Button } from '@lglab/compose-ui/button'
|
|
160
|
+
import {
|
|
161
|
+
PopoverArrow,
|
|
162
|
+
PopoverDescription,
|
|
163
|
+
PopoverPopup,
|
|
164
|
+
PopoverPortal,
|
|
165
|
+
PopoverPositioner,
|
|
166
|
+
PopoverRoot,
|
|
167
|
+
PopoverTitle,
|
|
168
|
+
PopoverTrigger,
|
|
169
|
+
} from '@lglab/compose-ui/popover'
|
|
170
|
+
|
|
171
|
+
const sides = ['left', 'bottom', 'top', 'right'] as const
|
|
172
|
+
|
|
173
|
+
export default function SidesExample() {
|
|
174
|
+
return (
|
|
175
|
+
<div className='flex flex-wrap gap-2 items-center'>
|
|
176
|
+
{sides.map((side) => (
|
|
177
|
+
<PopoverRoot key={side}>
|
|
178
|
+
<PopoverTrigger
|
|
179
|
+
render={(props) => (
|
|
180
|
+
<Button {...props} variant='outline' className='capitalize'>
|
|
181
|
+
{side}
|
|
182
|
+
</Button>
|
|
183
|
+
)}
|
|
184
|
+
/>
|
|
185
|
+
<PopoverPortal>
|
|
186
|
+
<PopoverPositioner side={side}>
|
|
187
|
+
<PopoverPopup className='space-y-0.5'>
|
|
188
|
+
<PopoverArrow />
|
|
189
|
+
<PopoverTitle>Popover on {side}</PopoverTitle>
|
|
190
|
+
<PopoverDescription>
|
|
191
|
+
This popover is positioned on the {side} side.
|
|
192
|
+
</PopoverDescription>
|
|
193
|
+
</PopoverPopup>
|
|
194
|
+
</PopoverPositioner>
|
|
195
|
+
</PopoverPortal>
|
|
196
|
+
</PopoverRoot>
|
|
197
|
+
))}
|
|
198
|
+
</div>
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Resources
|
|
204
|
+
|
|
205
|
+
- [Base UI Popover Documentation](https://base-ui.com/react/components/popover)
|
|
206
|
+
- [API Reference](https://base-ui.com/react/components/popover#api-reference)
|