@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.
Files changed (48) hide show
  1. package/README.md +11 -0
  2. package/dist/assets/llms/accordion.md +184 -0
  3. package/dist/assets/llms/alert-dialog.md +306 -0
  4. package/dist/assets/llms/autocomplete.md +756 -0
  5. package/dist/assets/llms/avatar.md +166 -0
  6. package/dist/assets/llms/badge.md +478 -0
  7. package/dist/assets/llms/button.md +238 -0
  8. package/dist/assets/llms/card.md +264 -0
  9. package/dist/assets/llms/checkbox-group.md +158 -0
  10. package/dist/assets/llms/checkbox.md +83 -0
  11. package/dist/assets/llms/collapsible.md +165 -0
  12. package/dist/assets/llms/combobox.md +1255 -0
  13. package/dist/assets/llms/context-menu.md +371 -0
  14. package/dist/assets/llms/dialog.md +592 -0
  15. package/dist/assets/llms/drawer.md +437 -0
  16. package/dist/assets/llms/field.md +74 -0
  17. package/dist/assets/llms/form.md +1931 -0
  18. package/dist/assets/llms/input.md +47 -0
  19. package/dist/assets/llms/menu.md +484 -0
  20. package/dist/assets/llms/menubar.md +804 -0
  21. package/dist/assets/llms/meter.md +181 -0
  22. package/dist/assets/llms/navigation-menu.md +187 -0
  23. package/dist/assets/llms/number-field.md +243 -0
  24. package/dist/assets/llms/pagination.md +514 -0
  25. package/dist/assets/llms/popover.md +206 -0
  26. package/dist/assets/llms/preview-card.md +146 -0
  27. package/dist/assets/llms/progress.md +60 -0
  28. package/dist/assets/llms/radio-group.md +105 -0
  29. package/dist/assets/llms/scroll-area.md +132 -0
  30. package/dist/assets/llms/select.md +276 -0
  31. package/dist/assets/llms/separator.md +49 -0
  32. package/dist/assets/llms/skeleton.md +96 -0
  33. package/dist/assets/llms/slider.md +161 -0
  34. package/dist/assets/llms/switch.md +101 -0
  35. package/dist/assets/llms/table.md +1325 -0
  36. package/dist/assets/llms/tabs.md +327 -0
  37. package/dist/assets/llms/textarea.md +38 -0
  38. package/dist/assets/llms/toast.md +349 -0
  39. package/dist/assets/llms/toggle-group.md +261 -0
  40. package/dist/assets/llms/toggle.md +161 -0
  41. package/dist/assets/llms/toolbar.md +148 -0
  42. package/dist/assets/llms/tooltip.md +486 -0
  43. package/dist/assets/llms-full.txt +14515 -0
  44. package/dist/assets/llms.txt +65 -0
  45. package/dist/index.d.mts +1 -0
  46. package/dist/index.mjs +161 -0
  47. package/dist/index.mjs.map +1 -0
  48. 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)