@neynar/ui 1.0.0 → 1.0.2

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 (69) hide show
  1. package/README.md +1 -1
  2. package/context7.json +17 -0
  3. package/llm/components/accordion.llm.md +205 -0
  4. package/llm/components/alert-dialog.llm.md +289 -0
  5. package/llm/components/alert.llm.md +310 -0
  6. package/llm/components/aspect-ratio.llm.md +110 -0
  7. package/llm/components/avatar.llm.md +282 -0
  8. package/llm/components/badge.llm.md +185 -0
  9. package/llm/components/blockquote.llm.md +86 -0
  10. package/llm/components/breadcrumb.llm.md +245 -0
  11. package/llm/components/button-group.llm.md +248 -0
  12. package/llm/components/button.llm.md +247 -0
  13. package/llm/components/calendar.llm.md +252 -0
  14. package/llm/components/card.llm.md +356 -0
  15. package/llm/components/carousel.llm.md +281 -0
  16. package/llm/components/chart.llm.md +278 -0
  17. package/llm/components/checkbox.llm.md +234 -0
  18. package/llm/components/code.llm.md +75 -0
  19. package/llm/components/collapsible.llm.md +271 -0
  20. package/llm/components/color-mode.llm.md +196 -0
  21. package/llm/components/combobox.llm.md +346 -0
  22. package/llm/components/command.llm.md +353 -0
  23. package/llm/components/context-menu.llm.md +368 -0
  24. package/llm/components/dialog.llm.md +283 -0
  25. package/llm/components/drawer.llm.md +326 -0
  26. package/llm/components/dropdown-menu.llm.md +404 -0
  27. package/llm/components/empty.llm.md +282 -0
  28. package/llm/components/field.llm.md +303 -0
  29. package/llm/components/first-light.llm.md +129 -0
  30. package/llm/components/hover-card.llm.md +278 -0
  31. package/llm/components/input-group.llm.md +334 -0
  32. package/llm/components/input-otp.llm.md +270 -0
  33. package/llm/components/input.llm.md +197 -0
  34. package/llm/components/item.llm.md +347 -0
  35. package/llm/components/kbd.llm.md +221 -0
  36. package/llm/components/label.llm.md +219 -0
  37. package/llm/components/menubar.llm.md +378 -0
  38. package/llm/components/navigation-menu.llm.md +320 -0
  39. package/llm/components/pagination.llm.md +337 -0
  40. package/llm/components/popover.llm.md +278 -0
  41. package/llm/components/progress.llm.md +259 -0
  42. package/llm/components/radio-group.llm.md +269 -0
  43. package/llm/components/resizable.llm.md +222 -0
  44. package/llm/components/scroll-area.llm.md +290 -0
  45. package/llm/components/select.llm.md +338 -0
  46. package/llm/components/separator.llm.md +129 -0
  47. package/llm/components/sheet.llm.md +275 -0
  48. package/llm/components/sidebar.llm.md +528 -0
  49. package/llm/components/skeleton.llm.md +140 -0
  50. package/llm/components/slider.llm.md +213 -0
  51. package/llm/components/sonner.llm.md +299 -0
  52. package/llm/components/spinner.llm.md +187 -0
  53. package/llm/components/switch.llm.md +258 -0
  54. package/llm/components/table.llm.md +334 -0
  55. package/llm/components/tabs.llm.md +245 -0
  56. package/llm/components/text.llm.md +108 -0
  57. package/llm/components/textarea.llm.md +236 -0
  58. package/llm/components/title.llm.md +88 -0
  59. package/llm/components/toggle-group.llm.md +228 -0
  60. package/llm/components/toggle.llm.md +235 -0
  61. package/llm/components/tooltip.llm.md +191 -0
  62. package/llm/contributing.llm.md +273 -0
  63. package/llm/hooks.llm.md +91 -0
  64. package/llm/index.llm.md +178 -0
  65. package/llm/theming.llm.md +381 -0
  66. package/llm/utilities.llm.md +97 -0
  67. package/llms-full.txt +15995 -0
  68. package/llms.txt +182 -0
  69. package/package.json +6 -2
@@ -0,0 +1,337 @@
1
+ # Pagination
2
+
3
+ A composable pagination component for navigating multi-page data sets with semantic HTML and full keyboard accessibility.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import {
9
+ Pagination,
10
+ PaginationContent,
11
+ PaginationItem,
12
+ PaginationLink,
13
+ PaginationPrevious,
14
+ PaginationNext,
15
+ PaginationEllipsis,
16
+ } from "@neynar/ui/pagination"
17
+ ```
18
+
19
+ ## Anatomy
20
+
21
+ ```tsx
22
+ <Pagination>
23
+ <PaginationContent>
24
+ <PaginationItem>
25
+ <PaginationPrevious href="#" />
26
+ </PaginationItem>
27
+ <PaginationItem>
28
+ <PaginationLink href="#">1</PaginationLink>
29
+ </PaginationItem>
30
+ <PaginationItem>
31
+ <PaginationLink href="#" isActive>2</PaginationLink>
32
+ </PaginationItem>
33
+ <PaginationItem>
34
+ <PaginationLink href="#">3</PaginationLink>
35
+ </PaginationItem>
36
+ <PaginationItem>
37
+ <PaginationEllipsis />
38
+ </PaginationItem>
39
+ <PaginationItem>
40
+ <PaginationLink href="#">10</PaginationLink>
41
+ </PaginationItem>
42
+ <PaginationItem>
43
+ <PaginationNext href="#" />
44
+ </PaginationItem>
45
+ </PaginationContent>
46
+ </Pagination>
47
+ ```
48
+
49
+ ## Components
50
+
51
+ | Component | Description |
52
+ |-----------|-------------|
53
+ | `Pagination` | Root navigation container with semantic `<nav>` element |
54
+ | `PaginationContent` | Flex list container for pagination items |
55
+ | `PaginationItem` | Wrapper for individual pagination elements |
56
+ | `PaginationLink` | Clickable page number link |
57
+ | `PaginationPrevious` | Previous page control with chevron + "Previous" label |
58
+ | `PaginationNext` | Next page control with chevron + "Next" label |
59
+ | `PaginationEllipsis` | Ellipsis indicator for skipped pages |
60
+
61
+ ## Props
62
+
63
+ ### Pagination
64
+
65
+ Extends `React.ComponentProps<"nav">`.
66
+
67
+ Root container with `role="navigation"` and `aria-label="pagination"`.
68
+
69
+ ### PaginationContent
70
+
71
+ Extends `React.ComponentProps<"ul">`.
72
+
73
+ Renders as a flexbox list with gap spacing between items.
74
+
75
+ ### PaginationItem
76
+
77
+ Extends `React.ComponentProps<"li">`.
78
+
79
+ Simple list item wrapper for pagination elements.
80
+
81
+ ### PaginationLink
82
+
83
+ | Prop | Type | Default | Description |
84
+ |------|------|---------|-------------|
85
+ | `isActive` | `boolean` | `false` | Highlights the current active page |
86
+ | `size` | `"default" \| "sm" \| "lg" \| "icon"` | `"icon"` | Button size variant |
87
+ | `href` | `string` | - | Link destination |
88
+
89
+ Plus all standard `<a>` element props.
90
+
91
+ **Notes:**
92
+ - Uses Button component with `render` prop for link semantics
93
+ - Active pages use `outline` variant, inactive use `ghost`
94
+ - Sets `aria-current="page"` when `isActive={true}`
95
+ - Renders with `data-active` attribute for custom styling
96
+
97
+ ### PaginationPrevious
98
+
99
+ Extends `PaginationLink` props.
100
+
101
+ **Auto-behaviors:**
102
+ - Sets `aria-label="Go to previous page"`
103
+ - Uses `size="default"` by default
104
+ - Displays chevron icon + "Previous" text (text hidden on mobile via `hidden sm:block`)
105
+
106
+ ### PaginationNext
107
+
108
+ Extends `PaginationLink` props.
109
+
110
+ **Auto-behaviors:**
111
+ - Sets `aria-label="Go to next page"`
112
+ - Uses `size="default"` by default
113
+ - Displays "Next" text (hidden on mobile) + chevron icon
114
+
115
+ ### PaginationEllipsis
116
+
117
+ Extends `React.ComponentProps<"span">`.
118
+
119
+ **Auto-behaviors:**
120
+ - Sets `aria-hidden` to hide from screen readers
121
+ - Includes screen reader text "More pages"
122
+ - Displays horizontal ellipsis icon
123
+
124
+ ## Data Attributes
125
+
126
+ All components include `data-slot` attributes for targeted styling:
127
+
128
+ | Attribute | Component |
129
+ |-----------|-----------|
130
+ | `data-slot="pagination"` | Pagination |
131
+ | `data-slot="pagination-content"` | PaginationContent |
132
+ | `data-slot="pagination-item"` | PaginationItem |
133
+ | `data-slot="pagination-link"` | PaginationLink |
134
+ | `data-slot="pagination-ellipsis"` | PaginationEllipsis |
135
+
136
+ PaginationLink also includes:
137
+ - `data-active="true"` when `isActive={true}`
138
+
139
+ ## Examples
140
+
141
+ ### Basic Pagination
142
+
143
+ ```tsx
144
+ <Pagination>
145
+ <PaginationContent>
146
+ <PaginationItem>
147
+ <PaginationPrevious href="#" />
148
+ </PaginationItem>
149
+ <PaginationItem>
150
+ <PaginationLink href="#">1</PaginationLink>
151
+ </PaginationItem>
152
+ <PaginationItem>
153
+ <PaginationLink href="#" isActive>2</PaginationLink>
154
+ </PaginationItem>
155
+ <PaginationItem>
156
+ <PaginationLink href="#">3</PaginationLink>
157
+ </PaginationItem>
158
+ <PaginationItem>
159
+ <PaginationNext href="#" />
160
+ </PaginationItem>
161
+ </PaginationContent>
162
+ </Pagination>
163
+ ```
164
+
165
+ ### With Ellipsis (Large Data Sets)
166
+
167
+ ```tsx
168
+ <Pagination>
169
+ <PaginationContent>
170
+ <PaginationItem>
171
+ <PaginationPrevious href="#" />
172
+ </PaginationItem>
173
+ <PaginationItem>
174
+ <PaginationLink href="#">1</PaginationLink>
175
+ </PaginationItem>
176
+ <PaginationItem>
177
+ <PaginationLink href="#" isActive>2</PaginationLink>
178
+ </PaginationItem>
179
+ <PaginationItem>
180
+ <PaginationLink href="#">3</PaginationLink>
181
+ </PaginationItem>
182
+ <PaginationItem>
183
+ <PaginationEllipsis />
184
+ </PaginationItem>
185
+ <PaginationItem>
186
+ <PaginationLink href="#">42</PaginationLink>
187
+ </PaginationItem>
188
+ <PaginationItem>
189
+ <PaginationNext href="#" />
190
+ </PaginationItem>
191
+ </PaginationContent>
192
+ </Pagination>
193
+ ```
194
+
195
+ ### Controlled with React State
196
+
197
+ ```tsx
198
+ function APILogsTable() {
199
+ const [currentPage, setCurrentPage] = useState(1)
200
+ const totalPages = 42
201
+
202
+ function handlePageClick(page: number) {
203
+ setCurrentPage(page)
204
+ }
205
+
206
+ return (
207
+ <div>
208
+ {/* Your table content */}
209
+
210
+ <Pagination>
211
+ <PaginationContent>
212
+ <PaginationItem>
213
+ <PaginationPrevious
214
+ href="#"
215
+ onClick={(e) => {
216
+ e.preventDefault()
217
+ if (currentPage > 1) handlePageClick(currentPage - 1)
218
+ }}
219
+ />
220
+ </PaginationItem>
221
+ <PaginationItem>
222
+ <PaginationLink
223
+ href="#"
224
+ isActive={currentPage === 1}
225
+ onClick={(e) => {
226
+ e.preventDefault()
227
+ handlePageClick(1)
228
+ }}
229
+ >
230
+ 1
231
+ </PaginationLink>
232
+ </PaginationItem>
233
+ <PaginationItem>
234
+ <PaginationLink
235
+ href="#"
236
+ isActive={currentPage === 2}
237
+ onClick={(e) => {
238
+ e.preventDefault()
239
+ handlePageClick(2)
240
+ }}
241
+ >
242
+ 2
243
+ </PaginationLink>
244
+ </PaginationItem>
245
+ <PaginationItem>
246
+ <PaginationEllipsis />
247
+ </PaginationItem>
248
+ <PaginationItem>
249
+ <PaginationLink
250
+ href="#"
251
+ onClick={(e) => {
252
+ e.preventDefault()
253
+ handlePageClick(totalPages)
254
+ }}
255
+ >
256
+ {totalPages}
257
+ </PaginationLink>
258
+ </PaginationItem>
259
+ <PaginationItem>
260
+ <PaginationNext
261
+ href="#"
262
+ onClick={(e) => {
263
+ e.preventDefault()
264
+ if (currentPage < totalPages) handlePageClick(currentPage + 1)
265
+ }}
266
+ />
267
+ </PaginationItem>
268
+ </PaginationContent>
269
+ </Pagination>
270
+ </div>
271
+ )
272
+ }
273
+ ```
274
+
275
+ ### Middle Page State (Dual Ellipsis)
276
+
277
+ ```tsx
278
+ <Pagination>
279
+ <PaginationContent>
280
+ <PaginationItem>
281
+ <PaginationPrevious href="#" />
282
+ </PaginationItem>
283
+ <PaginationItem>
284
+ <PaginationLink href="#">1</PaginationLink>
285
+ </PaginationItem>
286
+ <PaginationItem>
287
+ <PaginationEllipsis />
288
+ </PaginationItem>
289
+ <PaginationItem>
290
+ <PaginationLink href="#">12</PaginationLink>
291
+ </PaginationItem>
292
+ <PaginationItem>
293
+ <PaginationLink href="#" isActive>13</PaginationLink>
294
+ </PaginationItem>
295
+ <PaginationItem>
296
+ <PaginationLink href="#">14</PaginationLink>
297
+ </PaginationItem>
298
+ <PaginationItem>
299
+ <PaginationEllipsis />
300
+ </PaginationItem>
301
+ <PaginationItem>
302
+ <PaginationLink href="#">25</PaginationLink>
303
+ </PaginationItem>
304
+ <PaginationItem>
305
+ <PaginationNext href="#" />
306
+ </PaginationItem>
307
+ </PaginationContent>
308
+ </Pagination>
309
+ ```
310
+
311
+ ### Minimal (Controls Only)
312
+
313
+ ```tsx
314
+ <Pagination>
315
+ <PaginationContent>
316
+ <PaginationItem>
317
+ <PaginationPrevious href="#" />
318
+ </PaginationItem>
319
+ <PaginationItem>
320
+ <PaginationNext href="#" />
321
+ </PaginationItem>
322
+ </PaginationContent>
323
+ </Pagination>
324
+ ```
325
+
326
+ ## Accessibility
327
+
328
+ - Uses semantic `<nav>` element with `role="navigation"` and `aria-label="pagination"`
329
+ - Active page links include `aria-current="page"` for screen reader context
330
+ - Previous/Next controls have descriptive `aria-label` attributes
331
+ - Ellipsis is hidden from screen readers via `aria-hidden` but includes visually hidden text "More pages"
332
+ - All links are keyboard navigable via Tab key
333
+ - Mobile-responsive: "Previous"/"Next" labels hidden on small screens
334
+
335
+ ## Related
336
+
337
+ - [Button](./button.llm.md) - Used internally for pagination links
@@ -0,0 +1,278 @@
1
+ # Popover
2
+
3
+ Floating content panel anchored to a trigger element for contextual information, forms, or interactive content.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import {
9
+ Popover,
10
+ PopoverTrigger,
11
+ PopoverContent,
12
+ PopoverHeader,
13
+ PopoverTitle,
14
+ PopoverDescription,
15
+ } from "@neynar/ui/popover"
16
+ ```
17
+
18
+ ## Anatomy
19
+
20
+ ```tsx
21
+ <Popover>
22
+ <PopoverTrigger>
23
+ <Button>Open</Button>
24
+ </PopoverTrigger>
25
+ <PopoverContent>
26
+ <PopoverHeader>
27
+ <PopoverTitle>Title</PopoverTitle>
28
+ <PopoverDescription>Description</PopoverDescription>
29
+ </PopoverHeader>
30
+ {/* Content */}
31
+ </PopoverContent>
32
+ </Popover>
33
+ ```
34
+
35
+ ## Components
36
+
37
+ | Component | Description |
38
+ |-----------|-------------|
39
+ | Popover | Root container managing open state |
40
+ | PopoverTrigger | Button that opens the popover |
41
+ | PopoverContent | Main content panel with portal and positioning |
42
+ | PopoverHeader | Optional wrapper for title and description |
43
+ | PopoverTitle | Heading label (h2 element) |
44
+ | PopoverDescription | Optional description text |
45
+
46
+ ## Props
47
+
48
+ ### Popover
49
+
50
+ Root component managing state. Use `open`/`onOpenChange` for controlled state.
51
+
52
+ | Prop | Type | Default | Description |
53
+ |------|------|---------|-------------|
54
+ | open | boolean | - | Controlled open state |
55
+ | defaultOpen | boolean | false | Initial open state (uncontrolled) |
56
+ | onOpenChange | (open: boolean) => void | - | Callback when open state changes |
57
+ | modal | boolean \| "trap-focus" | false | Modal behavior: `true` locks scroll and traps focus, `"trap-focus"` only traps focus |
58
+
59
+ ### PopoverTrigger
60
+
61
+ Opens the popover when clicked. Renders a button by default.
62
+
63
+ | Prop | Type | Default | Description |
64
+ |------|------|---------|-------------|
65
+ | render | ReactElement | - | Custom element to use as trigger |
66
+ | openOnHover | boolean | false | Open popover on hover instead of click |
67
+ | delay | number | 300 | Hover delay in ms (requires openOnHover) |
68
+
69
+ ### PopoverContent
70
+
71
+ Automatically renders portal and positioner. Includes fade and zoom animations.
72
+
73
+ | Prop | Type | Default | Description |
74
+ |------|------|---------|-------------|
75
+ | side | "top" \| "right" \| "bottom" \| "left" | "bottom" | Which side of trigger to display on |
76
+ | align | "start" \| "center" \| "end" | "center" | Alignment relative to trigger |
77
+ | sideOffset | number | 4 | Distance from trigger in pixels |
78
+ | alignOffset | number | 0 | Offset along alignment axis in pixels |
79
+ | className | string | - | Additional CSS classes (default width is w-72) |
80
+
81
+ ### PopoverHeader
82
+
83
+ Optional container for title and description with consistent spacing.
84
+
85
+ Standard `div` props.
86
+
87
+ ### PopoverTitle
88
+
89
+ Heading label with ARIA attributes. Renders h2 element.
90
+
91
+ Standard Base UI Title props (className, render, etc).
92
+
93
+ ### PopoverDescription
94
+
95
+ Optional description text styled with muted foreground.
96
+
97
+ Standard Base UI Description props (className, render, etc).
98
+
99
+ ## Data Attributes
100
+
101
+ Available on PopoverContent for styling:
102
+
103
+ | Attribute | When Present |
104
+ |-----------|--------------|
105
+ | data-open | Popover is open |
106
+ | data-closed | Popover is closed |
107
+ | data-side | Value is current side (top/right/bottom/left) |
108
+ | data-starting-style | During opening animation |
109
+ | data-ending-style | During closing animation |
110
+
111
+ ## Examples
112
+
113
+ ### User Profile Preview
114
+
115
+ ```tsx
116
+ <Popover>
117
+ <PopoverTrigger>
118
+ <button className="flex items-center gap-2">
119
+ <Avatar />
120
+ <span>vitalik.eth</span>
121
+ </button>
122
+ </PopoverTrigger>
123
+ <PopoverContent className="w-80" side="bottom" align="start">
124
+ <div className="space-y-3">
125
+ <div className="flex items-start gap-3">
126
+ <Avatar size="lg" />
127
+ <div className="flex-1">
128
+ <p className="font-semibold">vitalik.eth</p>
129
+ <p className="text-muted-foreground text-sm">@vitalik</p>
130
+ </div>
131
+ <Button size="sm">Follow</Button>
132
+ </div>
133
+ <p className="text-sm">Creator of Ethereum...</p>
134
+ </div>
135
+ </PopoverContent>
136
+ </Popover>
137
+ ```
138
+
139
+ ### Filter Form
140
+
141
+ ```tsx
142
+ function FilterPopover() {
143
+ const [open, setOpen] = useState(false)
144
+ const [dateRange, setDateRange] = useState("last-7-days")
145
+
146
+ return (
147
+ <Popover open={open} onOpenChange={setOpen}>
148
+ <PopoverTrigger>
149
+ <Button variant="outline" size="sm">
150
+ <SettingsIcon className="mr-2 size-4" />
151
+ Filters
152
+ </Button>
153
+ </PopoverTrigger>
154
+ <PopoverContent className="w-80" side="bottom" align="end">
155
+ <PopoverHeader>
156
+ <PopoverTitle>Filter Options</PopoverTitle>
157
+ <PopoverDescription>
158
+ Customize the data displayed
159
+ </PopoverDescription>
160
+ </PopoverHeader>
161
+ <div className="space-y-4">
162
+ <div className="space-y-2">
163
+ <Label htmlFor="date-range">Date Range</Label>
164
+ <select
165
+ id="date-range"
166
+ value={dateRange}
167
+ onChange={(e) => setDateRange(e.target.value)}
168
+ >
169
+ <option value="last-7-days">Last 7 days</option>
170
+ <option value="last-30-days">Last 30 days</option>
171
+ </select>
172
+ </div>
173
+ <div className="flex justify-end gap-2">
174
+ <Button variant="ghost" size="sm" onClick={() => setOpen(false)}>
175
+ Cancel
176
+ </Button>
177
+ <Button size="sm" onClick={() => setOpen(false)}>
178
+ Apply
179
+ </Button>
180
+ </div>
181
+ </div>
182
+ </PopoverContent>
183
+ </Popover>
184
+ )
185
+ }
186
+ ```
187
+
188
+ ### Contextual Help
189
+
190
+ ```tsx
191
+ <div className="flex items-center gap-2">
192
+ <Label htmlFor="api-key">API Key</Label>
193
+ <Popover>
194
+ <PopoverTrigger>
195
+ <button className="text-muted-foreground hover:text-foreground">
196
+ <HelpCircleIcon className="size-4" />
197
+ </button>
198
+ </PopoverTrigger>
199
+ <PopoverContent className="w-80" side="right">
200
+ <PopoverHeader>
201
+ <PopoverTitle>About API Keys</PopoverTitle>
202
+ </PopoverHeader>
203
+ <div className="space-y-2 text-sm">
204
+ <p>API keys authenticate requests to the Neynar API...</p>
205
+ <ul className="text-muted-foreground ml-4 list-disc space-y-1">
206
+ <li>Production keys have higher rate limits</li>
207
+ <li>Development keys are for testing only</li>
208
+ </ul>
209
+ </div>
210
+ </PopoverContent>
211
+ </Popover>
212
+ </div>
213
+ ```
214
+
215
+ ### Custom Trigger Element
216
+
217
+ ```tsx
218
+ <Popover>
219
+ <PopoverTrigger>
220
+ <Button variant="ghost" size="icon-sm">
221
+ <InfoIcon className="size-4" />
222
+ </Button>
223
+ </PopoverTrigger>
224
+ <PopoverContent className="w-80" side="left">
225
+ <PopoverHeader>
226
+ <PopoverTitle>Billing Information</PopoverTitle>
227
+ <PopoverDescription>
228
+ Your subscription details
229
+ </PopoverDescription>
230
+ </PopoverHeader>
231
+ <div className="space-y-3 text-sm">
232
+ <div className="flex justify-between">
233
+ <span className="text-muted-foreground">Current plan</span>
234
+ <span className="font-medium">Pro ($99/mo)</span>
235
+ </div>
236
+ <div className="flex justify-between">
237
+ <span className="text-muted-foreground">Next charge</span>
238
+ <span className="font-medium">$99.00</span>
239
+ </div>
240
+ </div>
241
+ </PopoverContent>
242
+ </Popover>
243
+ ```
244
+
245
+ ### Hover Trigger
246
+
247
+ ```tsx
248
+ <Popover>
249
+ <PopoverTrigger openOnHover delay={200}>
250
+ <span className="underline decoration-dotted">Hover me</span>
251
+ </PopoverTrigger>
252
+ <PopoverContent side="top">
253
+ <p className="text-sm">This opens on hover with 200ms delay</p>
254
+ </PopoverContent>
255
+ </Popover>
256
+ ```
257
+
258
+ ## Keyboard
259
+
260
+ | Key | Action |
261
+ |-----|--------|
262
+ | Escape | Close popover |
263
+ | Tab | Navigate focus within popover |
264
+
265
+ ## Accessibility
266
+
267
+ - PopoverTitle automatically provides `aria-labelledby` for the popover
268
+ - PopoverDescription provides `aria-describedby` when present
269
+ - Focus is trapped within popover when `modal` is true or "trap-focus"
270
+ - Popover closes on Escape key press
271
+ - Focus returns to trigger when popover closes
272
+
273
+ ## Related
274
+
275
+ - **Tooltip** - For simple text hints without interaction
276
+ - **Dropdown Menu** - For menus with selectable actions
277
+ - **Dialog** - For modal content requiring user action
278
+ - **Hover Card** - Similar to Popover but specifically for hover interactions