@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.
- package/README.md +1 -1
- package/context7.json +17 -0
- package/llm/components/accordion.llm.md +205 -0
- package/llm/components/alert-dialog.llm.md +289 -0
- package/llm/components/alert.llm.md +310 -0
- package/llm/components/aspect-ratio.llm.md +110 -0
- package/llm/components/avatar.llm.md +282 -0
- package/llm/components/badge.llm.md +185 -0
- package/llm/components/blockquote.llm.md +86 -0
- package/llm/components/breadcrumb.llm.md +245 -0
- package/llm/components/button-group.llm.md +248 -0
- package/llm/components/button.llm.md +247 -0
- package/llm/components/calendar.llm.md +252 -0
- package/llm/components/card.llm.md +356 -0
- package/llm/components/carousel.llm.md +281 -0
- package/llm/components/chart.llm.md +278 -0
- package/llm/components/checkbox.llm.md +234 -0
- package/llm/components/code.llm.md +75 -0
- package/llm/components/collapsible.llm.md +271 -0
- package/llm/components/color-mode.llm.md +196 -0
- package/llm/components/combobox.llm.md +346 -0
- package/llm/components/command.llm.md +353 -0
- package/llm/components/context-menu.llm.md +368 -0
- package/llm/components/dialog.llm.md +283 -0
- package/llm/components/drawer.llm.md +326 -0
- package/llm/components/dropdown-menu.llm.md +404 -0
- package/llm/components/empty.llm.md +282 -0
- package/llm/components/field.llm.md +303 -0
- package/llm/components/first-light.llm.md +129 -0
- package/llm/components/hover-card.llm.md +278 -0
- package/llm/components/input-group.llm.md +334 -0
- package/llm/components/input-otp.llm.md +270 -0
- package/llm/components/input.llm.md +197 -0
- package/llm/components/item.llm.md +347 -0
- package/llm/components/kbd.llm.md +221 -0
- package/llm/components/label.llm.md +219 -0
- package/llm/components/menubar.llm.md +378 -0
- package/llm/components/navigation-menu.llm.md +320 -0
- package/llm/components/pagination.llm.md +337 -0
- package/llm/components/popover.llm.md +278 -0
- package/llm/components/progress.llm.md +259 -0
- package/llm/components/radio-group.llm.md +269 -0
- package/llm/components/resizable.llm.md +222 -0
- package/llm/components/scroll-area.llm.md +290 -0
- package/llm/components/select.llm.md +338 -0
- package/llm/components/separator.llm.md +129 -0
- package/llm/components/sheet.llm.md +275 -0
- package/llm/components/sidebar.llm.md +528 -0
- package/llm/components/skeleton.llm.md +140 -0
- package/llm/components/slider.llm.md +213 -0
- package/llm/components/sonner.llm.md +299 -0
- package/llm/components/spinner.llm.md +187 -0
- package/llm/components/switch.llm.md +258 -0
- package/llm/components/table.llm.md +334 -0
- package/llm/components/tabs.llm.md +245 -0
- package/llm/components/text.llm.md +108 -0
- package/llm/components/textarea.llm.md +236 -0
- package/llm/components/title.llm.md +88 -0
- package/llm/components/toggle-group.llm.md +228 -0
- package/llm/components/toggle.llm.md +235 -0
- package/llm/components/tooltip.llm.md +191 -0
- package/llm/contributing.llm.md +273 -0
- package/llm/hooks.llm.md +91 -0
- package/llm/index.llm.md +178 -0
- package/llm/theming.llm.md +381 -0
- package/llm/utilities.llm.md +97 -0
- package/llms-full.txt +15995 -0
- package/llms.txt +182 -0
- package/package.json +6 -2
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
# DropdownMenu
|
|
2
|
+
|
|
3
|
+
A versatile dropdown menu component for displaying contextual actions and selections.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import {
|
|
9
|
+
DropdownMenu,
|
|
10
|
+
DropdownMenuTrigger,
|
|
11
|
+
DropdownMenuContent,
|
|
12
|
+
DropdownMenuItem,
|
|
13
|
+
DropdownMenuCheckboxItem,
|
|
14
|
+
DropdownMenuRadioGroup,
|
|
15
|
+
DropdownMenuRadioItem,
|
|
16
|
+
DropdownMenuLabel,
|
|
17
|
+
DropdownMenuSeparator,
|
|
18
|
+
DropdownMenuGroup,
|
|
19
|
+
DropdownMenuSub,
|
|
20
|
+
DropdownMenuSubTrigger,
|
|
21
|
+
DropdownMenuSubContent,
|
|
22
|
+
DropdownMenuShortcut,
|
|
23
|
+
} from "@neynar/ui/dropdown-menu"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Anatomy
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<DropdownMenu>
|
|
30
|
+
<DropdownMenuTrigger>
|
|
31
|
+
<Button>Open</Button>
|
|
32
|
+
</DropdownMenuTrigger>
|
|
33
|
+
<DropdownMenuContent>
|
|
34
|
+
<DropdownMenuLabel>Section</DropdownMenuLabel>
|
|
35
|
+
<DropdownMenuSeparator />
|
|
36
|
+
<DropdownMenuGroup>
|
|
37
|
+
<DropdownMenuItem>Item</DropdownMenuItem>
|
|
38
|
+
</DropdownMenuGroup>
|
|
39
|
+
</DropdownMenuContent>
|
|
40
|
+
</DropdownMenu>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Components
|
|
44
|
+
|
|
45
|
+
| Component | Description |
|
|
46
|
+
|-----------|-------------|
|
|
47
|
+
| DropdownMenu | Root container, manages open/close state and keyboard navigation |
|
|
48
|
+
| DropdownMenuTrigger | Button that opens the menu |
|
|
49
|
+
| DropdownMenuContent | Content container with automatic portal and positioning |
|
|
50
|
+
| DropdownMenuItem | Individual menu item with optional variants |
|
|
51
|
+
| DropdownMenuCheckboxItem | Menu item with checkbox for independent toggles |
|
|
52
|
+
| DropdownMenuRadioGroup | Container for mutually exclusive radio items |
|
|
53
|
+
| DropdownMenuRadioItem | Radio item for single selection within a group |
|
|
54
|
+
| DropdownMenuLabel | Label for grouping related items |
|
|
55
|
+
| DropdownMenuSeparator | Visual divider between menu sections |
|
|
56
|
+
| DropdownMenuGroup | Logical container for related items |
|
|
57
|
+
| DropdownMenuSub | Root container for nested submenus |
|
|
58
|
+
| DropdownMenuSubTrigger | Trigger for opening a submenu |
|
|
59
|
+
| DropdownMenuSubContent | Content container for submenu items |
|
|
60
|
+
| DropdownMenuShortcut | Visual display of keyboard shortcuts |
|
|
61
|
+
|
|
62
|
+
## Props
|
|
63
|
+
|
|
64
|
+
### DropdownMenu
|
|
65
|
+
|
|
66
|
+
| Prop | Type | Default | Description |
|
|
67
|
+
|------|------|---------|-------------|
|
|
68
|
+
| open | boolean | - | Controlled open state |
|
|
69
|
+
| onOpenChange | (open: boolean) => void | - | Called when open state changes |
|
|
70
|
+
| defaultOpen | boolean | false | Uncontrolled initial open state |
|
|
71
|
+
|
|
72
|
+
### DropdownMenuTrigger
|
|
73
|
+
|
|
74
|
+
Uses `render` prop pattern for custom trigger elements:
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
<DropdownMenuTrigger render={<Button variant="outline" />}>
|
|
78
|
+
Open Menu
|
|
79
|
+
</DropdownMenuTrigger>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### DropdownMenuContent
|
|
83
|
+
|
|
84
|
+
Automatically renders in a portal with positioning system.
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Description |
|
|
87
|
+
|------|------|---------|-------------|
|
|
88
|
+
| align | "start" \| "center" \| "end" | "start" | Horizontal alignment relative to trigger |
|
|
89
|
+
| alignOffset | number | 0 | Offset in pixels from aligned position |
|
|
90
|
+
| side | "top" \| "right" \| "bottom" \| "left" | "bottom" | Preferred side to position menu |
|
|
91
|
+
| sideOffset | number | 4 | Distance in pixels from trigger |
|
|
92
|
+
|
|
93
|
+
### DropdownMenuItem
|
|
94
|
+
|
|
95
|
+
| Prop | Type | Default | Description |
|
|
96
|
+
|------|------|---------|-------------|
|
|
97
|
+
| variant | "default" \| "destructive" \| "success" \| "warning" \| "info" | "default" | Visual style variant |
|
|
98
|
+
| inset | boolean | false | Add extra left padding for alignment |
|
|
99
|
+
| disabled | boolean | false | Disable item interaction |
|
|
100
|
+
|
|
101
|
+
### DropdownMenuCheckboxItem
|
|
102
|
+
|
|
103
|
+
| Prop | Type | Default | Description |
|
|
104
|
+
|------|------|---------|-------------|
|
|
105
|
+
| checked | boolean \| "indeterminate" | - | Checked state |
|
|
106
|
+
| onCheckedChange | (checked: boolean) => void | - | Called when checked state changes |
|
|
107
|
+
|
|
108
|
+
### DropdownMenuRadioGroup
|
|
109
|
+
|
|
110
|
+
| Prop | Type | Default | Description |
|
|
111
|
+
|------|------|---------|-------------|
|
|
112
|
+
| value | string | - | Currently selected value |
|
|
113
|
+
| onValueChange | (value: string) => void | - | Called when selection changes |
|
|
114
|
+
|
|
115
|
+
### DropdownMenuRadioItem
|
|
116
|
+
|
|
117
|
+
| Prop | Type | Default | Description |
|
|
118
|
+
|------|------|---------|-------------|
|
|
119
|
+
| value | string | - | Value for this radio item |
|
|
120
|
+
|
|
121
|
+
### DropdownMenuLabel
|
|
122
|
+
|
|
123
|
+
| Prop | Type | Default | Description |
|
|
124
|
+
|------|------|---------|-------------|
|
|
125
|
+
| inset | boolean | false | Add extra left padding for alignment with icon items |
|
|
126
|
+
|
|
127
|
+
### DropdownMenuSubTrigger
|
|
128
|
+
|
|
129
|
+
| Prop | Type | Default | Description |
|
|
130
|
+
|------|------|---------|-------------|
|
|
131
|
+
| inset | boolean | false | Add extra left padding for alignment |
|
|
132
|
+
|
|
133
|
+
Automatically displays chevron icon on the right.
|
|
134
|
+
|
|
135
|
+
### DropdownMenuSubContent
|
|
136
|
+
|
|
137
|
+
Same props as DropdownMenuContent, but with different defaults:
|
|
138
|
+
|
|
139
|
+
| Prop | Type | Default | Description |
|
|
140
|
+
|------|------|---------|-------------|
|
|
141
|
+
| side | "top" \| "right" \| "bottom" \| "left" | "right" | Preferred side to position submenu |
|
|
142
|
+
| alignOffset | number | -3 | Offset for better visual alignment |
|
|
143
|
+
|
|
144
|
+
## Data Attributes (for styling)
|
|
145
|
+
|
|
146
|
+
| Attribute | When Present |
|
|
147
|
+
|-----------|--------------|
|
|
148
|
+
| data-open | Menu or submenu is open |
|
|
149
|
+
| data-closed | Menu or submenu is closed |
|
|
150
|
+
| data-highlighted | Item is keyboard-highlighted or hovered |
|
|
151
|
+
| data-disabled | Item is disabled |
|
|
152
|
+
| data-inset | Item or label has inset padding |
|
|
153
|
+
|
|
154
|
+
## Variants
|
|
155
|
+
|
|
156
|
+
DropdownMenuItem supports semantic variants:
|
|
157
|
+
|
|
158
|
+
| Variant | Use Case |
|
|
159
|
+
|---------|----------|
|
|
160
|
+
| default | Standard actions |
|
|
161
|
+
| destructive | Delete, remove, or dangerous actions |
|
|
162
|
+
| success | Confirmations or positive actions |
|
|
163
|
+
| warning | Caution-required actions |
|
|
164
|
+
| info | Informational actions |
|
|
165
|
+
|
|
166
|
+
## Examples
|
|
167
|
+
|
|
168
|
+
### Basic Menu
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
<DropdownMenu>
|
|
172
|
+
<DropdownMenuTrigger>
|
|
173
|
+
<Button variant="outline">Open Menu</Button>
|
|
174
|
+
</DropdownMenuTrigger>
|
|
175
|
+
<DropdownMenuContent>
|
|
176
|
+
<DropdownMenuItem>
|
|
177
|
+
<EditIcon />
|
|
178
|
+
Edit
|
|
179
|
+
</DropdownMenuItem>
|
|
180
|
+
<DropdownMenuItem>
|
|
181
|
+
<CopyIcon />
|
|
182
|
+
Duplicate
|
|
183
|
+
</DropdownMenuItem>
|
|
184
|
+
<DropdownMenuSeparator />
|
|
185
|
+
<DropdownMenuItem variant="destructive">
|
|
186
|
+
<TrashIcon />
|
|
187
|
+
Delete
|
|
188
|
+
</DropdownMenuItem>
|
|
189
|
+
</DropdownMenuContent>
|
|
190
|
+
</DropdownMenu>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### User Account Menu
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
<DropdownMenu>
|
|
197
|
+
<DropdownMenuTrigger>
|
|
198
|
+
<Button variant="ghost" size="icon">
|
|
199
|
+
<UserIcon />
|
|
200
|
+
</Button>
|
|
201
|
+
</DropdownMenuTrigger>
|
|
202
|
+
<DropdownMenuContent align="end" className="w-56">
|
|
203
|
+
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
204
|
+
<DropdownMenuSeparator />
|
|
205
|
+
<DropdownMenuItem>
|
|
206
|
+
<UserIcon />
|
|
207
|
+
Profile
|
|
208
|
+
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
|
|
209
|
+
</DropdownMenuItem>
|
|
210
|
+
<DropdownMenuItem>
|
|
211
|
+
<SettingsIcon />
|
|
212
|
+
Settings
|
|
213
|
+
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
|
|
214
|
+
</DropdownMenuItem>
|
|
215
|
+
<DropdownMenuSeparator />
|
|
216
|
+
<DropdownMenuItem variant="destructive">
|
|
217
|
+
<LogOutIcon />
|
|
218
|
+
Log Out
|
|
219
|
+
</DropdownMenuItem>
|
|
220
|
+
</DropdownMenuContent>
|
|
221
|
+
</DropdownMenu>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Checkbox Items
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
function NotificationMenu() {
|
|
228
|
+
const [notifications, setNotifications] = useState(true)
|
|
229
|
+
const [marketing, setMarketing] = useState(false)
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<DropdownMenu>
|
|
233
|
+
<DropdownMenuTrigger>
|
|
234
|
+
<Button variant="outline">Preferences</Button>
|
|
235
|
+
</DropdownMenuTrigger>
|
|
236
|
+
<DropdownMenuContent>
|
|
237
|
+
<DropdownMenuLabel>Notifications</DropdownMenuLabel>
|
|
238
|
+
<DropdownMenuSeparator />
|
|
239
|
+
<DropdownMenuCheckboxItem
|
|
240
|
+
checked={notifications}
|
|
241
|
+
onCheckedChange={setNotifications}
|
|
242
|
+
>
|
|
243
|
+
<BellIcon />
|
|
244
|
+
Push Notifications
|
|
245
|
+
</DropdownMenuCheckboxItem>
|
|
246
|
+
<DropdownMenuCheckboxItem
|
|
247
|
+
checked={marketing}
|
|
248
|
+
onCheckedChange={setMarketing}
|
|
249
|
+
>
|
|
250
|
+
<MailIcon />
|
|
251
|
+
Marketing Emails
|
|
252
|
+
</DropdownMenuCheckboxItem>
|
|
253
|
+
</DropdownMenuContent>
|
|
254
|
+
</DropdownMenu>
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Radio Group
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
function ThemeSelector() {
|
|
263
|
+
const [theme, setTheme] = useState("system")
|
|
264
|
+
|
|
265
|
+
return (
|
|
266
|
+
<DropdownMenu>
|
|
267
|
+
<DropdownMenuTrigger>
|
|
268
|
+
<Button variant="outline">Theme: {theme}</Button>
|
|
269
|
+
</DropdownMenuTrigger>
|
|
270
|
+
<DropdownMenuContent>
|
|
271
|
+
<DropdownMenuLabel>Theme</DropdownMenuLabel>
|
|
272
|
+
<DropdownMenuSeparator />
|
|
273
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
274
|
+
<DropdownMenuRadioItem value="light">
|
|
275
|
+
<SunIcon />
|
|
276
|
+
Light
|
|
277
|
+
</DropdownMenuRadioItem>
|
|
278
|
+
<DropdownMenuRadioItem value="dark">
|
|
279
|
+
<MoonIcon />
|
|
280
|
+
Dark
|
|
281
|
+
</DropdownMenuRadioItem>
|
|
282
|
+
<DropdownMenuRadioItem value="system">
|
|
283
|
+
<MonitorIcon />
|
|
284
|
+
System
|
|
285
|
+
</DropdownMenuRadioItem>
|
|
286
|
+
</DropdownMenuRadioGroup>
|
|
287
|
+
</DropdownMenuContent>
|
|
288
|
+
</DropdownMenu>
|
|
289
|
+
)
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Nested Submenus
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
<DropdownMenu>
|
|
297
|
+
<DropdownMenuTrigger>
|
|
298
|
+
<Button variant="outline">Actions</Button>
|
|
299
|
+
</DropdownMenuTrigger>
|
|
300
|
+
<DropdownMenuContent>
|
|
301
|
+
<DropdownMenuItem>
|
|
302
|
+
<EditIcon />
|
|
303
|
+
Edit
|
|
304
|
+
</DropdownMenuItem>
|
|
305
|
+
<DropdownMenuItem>
|
|
306
|
+
<CopyIcon />
|
|
307
|
+
Duplicate
|
|
308
|
+
</DropdownMenuItem>
|
|
309
|
+
<DropdownMenuSeparator />
|
|
310
|
+
<DropdownMenuSub>
|
|
311
|
+
<DropdownMenuSubTrigger>
|
|
312
|
+
<ShareIcon />
|
|
313
|
+
Share
|
|
314
|
+
</DropdownMenuSubTrigger>
|
|
315
|
+
<DropdownMenuSubContent>
|
|
316
|
+
<DropdownMenuItem>
|
|
317
|
+
<MailIcon />
|
|
318
|
+
Email
|
|
319
|
+
</DropdownMenuItem>
|
|
320
|
+
<DropdownMenuItem>
|
|
321
|
+
<CopyIcon />
|
|
322
|
+
Copy Link
|
|
323
|
+
</DropdownMenuItem>
|
|
324
|
+
<DropdownMenuItem>
|
|
325
|
+
<DownloadIcon />
|
|
326
|
+
Export
|
|
327
|
+
</DropdownMenuItem>
|
|
328
|
+
</DropdownMenuSubContent>
|
|
329
|
+
</DropdownMenuSub>
|
|
330
|
+
<DropdownMenuSeparator />
|
|
331
|
+
<DropdownMenuItem variant="destructive">
|
|
332
|
+
<TrashIcon />
|
|
333
|
+
Delete
|
|
334
|
+
</DropdownMenuItem>
|
|
335
|
+
</DropdownMenuContent>
|
|
336
|
+
</DropdownMenu>
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Organized with Groups
|
|
340
|
+
|
|
341
|
+
```tsx
|
|
342
|
+
<DropdownMenu>
|
|
343
|
+
<DropdownMenuTrigger>
|
|
344
|
+
<Button variant="outline">Menu</Button>
|
|
345
|
+
</DropdownMenuTrigger>
|
|
346
|
+
<DropdownMenuContent className="w-56">
|
|
347
|
+
<DropdownMenuGroup>
|
|
348
|
+
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
349
|
+
</DropdownMenuGroup>
|
|
350
|
+
<DropdownMenuSeparator />
|
|
351
|
+
<DropdownMenuGroup>
|
|
352
|
+
<DropdownMenuItem>
|
|
353
|
+
<UserIcon />
|
|
354
|
+
Profile
|
|
355
|
+
</DropdownMenuItem>
|
|
356
|
+
<DropdownMenuItem>
|
|
357
|
+
<SettingsIcon />
|
|
358
|
+
Settings
|
|
359
|
+
</DropdownMenuItem>
|
|
360
|
+
</DropdownMenuGroup>
|
|
361
|
+
<DropdownMenuSeparator />
|
|
362
|
+
<DropdownMenuGroup>
|
|
363
|
+
<DropdownMenuLabel>Team</DropdownMenuLabel>
|
|
364
|
+
</DropdownMenuGroup>
|
|
365
|
+
<DropdownMenuGroup>
|
|
366
|
+
<DropdownMenuItem>
|
|
367
|
+
<PlusIcon />
|
|
368
|
+
Invite Members
|
|
369
|
+
</DropdownMenuItem>
|
|
370
|
+
<DropdownMenuItem>
|
|
371
|
+
<MailIcon />
|
|
372
|
+
Team Settings
|
|
373
|
+
</DropdownMenuItem>
|
|
374
|
+
</DropdownMenuGroup>
|
|
375
|
+
</DropdownMenuContent>
|
|
376
|
+
</DropdownMenu>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Keyboard
|
|
380
|
+
|
|
381
|
+
| Key | Action |
|
|
382
|
+
|-----|--------|
|
|
383
|
+
| Space / Enter | Open menu (on trigger) / Activate item (in menu) |
|
|
384
|
+
| ArrowDown / ArrowUp | Navigate between items |
|
|
385
|
+
| ArrowRight | Open submenu |
|
|
386
|
+
| ArrowLeft | Close submenu |
|
|
387
|
+
| Escape | Close menu |
|
|
388
|
+
| Tab | Move focus out and close menu |
|
|
389
|
+
|
|
390
|
+
## Accessibility
|
|
391
|
+
|
|
392
|
+
- Built on Base UI Menu primitives with ARIA menu pattern
|
|
393
|
+
- Automatic focus management and keyboard navigation
|
|
394
|
+
- Screen reader announcements for menu state changes
|
|
395
|
+
- All items are properly labeled and keyboard accessible
|
|
396
|
+
- Checkbox and radio items announce their checked state
|
|
397
|
+
- Disabled items are properly marked with `aria-disabled`
|
|
398
|
+
|
|
399
|
+
## Related
|
|
400
|
+
|
|
401
|
+
- [ContextMenu](/components/context-menu) - Right-click menu with similar structure
|
|
402
|
+
- [Select](/components/select) - For form-based single selection
|
|
403
|
+
- [Combobox](/components/combobox) - For searchable selection
|
|
404
|
+
- [Button](/components/button) - Common trigger element
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# Empty
|
|
2
|
+
|
|
3
|
+
Compound component for displaying empty states with media, messaging, and call-to-action elements.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import {
|
|
9
|
+
Empty,
|
|
10
|
+
EmptyHeader,
|
|
11
|
+
EmptyMedia,
|
|
12
|
+
EmptyTitle,
|
|
13
|
+
EmptyDescription,
|
|
14
|
+
EmptyContent,
|
|
15
|
+
} from "@neynar/ui/empty"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Anatomy
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
<Empty>
|
|
22
|
+
<EmptyHeader>
|
|
23
|
+
<EmptyMedia variant="icon">
|
|
24
|
+
<Icon />
|
|
25
|
+
</EmptyMedia>
|
|
26
|
+
<EmptyTitle>Title</EmptyTitle>
|
|
27
|
+
<EmptyDescription>Description text</EmptyDescription>
|
|
28
|
+
</EmptyHeader>
|
|
29
|
+
<EmptyContent>
|
|
30
|
+
<Button>Action</Button>
|
|
31
|
+
</EmptyContent>
|
|
32
|
+
</Empty>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Components
|
|
36
|
+
|
|
37
|
+
| Component | Description |
|
|
38
|
+
|-----------|-------------|
|
|
39
|
+
| Empty | Root container with centered flex layout and dashed border |
|
|
40
|
+
| EmptyHeader | Vertical stack for media, title, and description |
|
|
41
|
+
| EmptyMedia | Icon/media container with optional background styling |
|
|
42
|
+
| EmptyTitle | Large heading text |
|
|
43
|
+
| EmptyDescription | Supporting text with link styling |
|
|
44
|
+
| EmptyContent | Action area for buttons or links |
|
|
45
|
+
|
|
46
|
+
## Props
|
|
47
|
+
|
|
48
|
+
### Empty
|
|
49
|
+
|
|
50
|
+
Standard div props with centered layout and dashed border.
|
|
51
|
+
|
|
52
|
+
| Prop | Type | Default | Description |
|
|
53
|
+
|------|------|---------|-------------|
|
|
54
|
+
| className | string | - | Additional CSS classes |
|
|
55
|
+
| children | ReactNode | - | Empty state content |
|
|
56
|
+
|
|
57
|
+
### EmptyHeader
|
|
58
|
+
|
|
59
|
+
Standard div props. Groups media, title, and description.
|
|
60
|
+
|
|
61
|
+
| Prop | Type | Default | Description |
|
|
62
|
+
|------|------|---------|-------------|
|
|
63
|
+
| className | string | - | Additional CSS classes |
|
|
64
|
+
| children | ReactNode | - | Header content (media, title, description) |
|
|
65
|
+
|
|
66
|
+
### EmptyMedia
|
|
67
|
+
|
|
68
|
+
| Prop | Type | Default | Description |
|
|
69
|
+
|------|------|---------|-------------|
|
|
70
|
+
| variant | "default" \| "icon" | "default" | Styling variant |
|
|
71
|
+
| className | string | - | Additional CSS classes |
|
|
72
|
+
| children | ReactNode | - | Icon or media element |
|
|
73
|
+
|
|
74
|
+
**Variant Behavior:**
|
|
75
|
+
- `default`: Transparent background, use with custom-sized icons
|
|
76
|
+
- `icon`: Muted background with padding, auto-sizes icons to size-6
|
|
77
|
+
|
|
78
|
+
### EmptyTitle
|
|
79
|
+
|
|
80
|
+
Standard div props for the title heading.
|
|
81
|
+
|
|
82
|
+
| Prop | Type | Default | Description |
|
|
83
|
+
|------|------|---------|-------------|
|
|
84
|
+
| className | string | - | Additional CSS classes |
|
|
85
|
+
| children | ReactNode | - | Title text |
|
|
86
|
+
|
|
87
|
+
### EmptyDescription
|
|
88
|
+
|
|
89
|
+
Standard div props with link styling support.
|
|
90
|
+
|
|
91
|
+
| Prop | Type | Default | Description |
|
|
92
|
+
|------|------|---------|-------------|
|
|
93
|
+
| className | string | - | Additional CSS classes |
|
|
94
|
+
| children | ReactNode | - | Description text (supports inline links) |
|
|
95
|
+
|
|
96
|
+
Inline links (`<a>`) are automatically styled with underlines and hover effects.
|
|
97
|
+
|
|
98
|
+
### EmptyContent
|
|
99
|
+
|
|
100
|
+
Standard div props for action elements.
|
|
101
|
+
|
|
102
|
+
| Prop | Type | Default | Description |
|
|
103
|
+
|------|------|---------|-------------|
|
|
104
|
+
| className | string | - | Additional CSS classes |
|
|
105
|
+
| children | ReactNode | - | Action buttons or links |
|
|
106
|
+
|
|
107
|
+
## Data Attributes
|
|
108
|
+
|
|
109
|
+
All components have unique `data-slot` attributes for styling hooks:
|
|
110
|
+
|
|
111
|
+
| Attribute | Component |
|
|
112
|
+
|-----------|-----------|
|
|
113
|
+
| data-slot="empty" | Empty |
|
|
114
|
+
| data-slot="empty-header" | EmptyHeader |
|
|
115
|
+
| data-slot="empty-icon" | EmptyMedia |
|
|
116
|
+
| data-slot="empty-title" | EmptyTitle |
|
|
117
|
+
| data-slot="empty-description" | EmptyDescription |
|
|
118
|
+
| data-slot="empty-content" | EmptyContent |
|
|
119
|
+
|
|
120
|
+
EmptyMedia also includes:
|
|
121
|
+
- `data-variant`: Current variant value
|
|
122
|
+
|
|
123
|
+
## Variants
|
|
124
|
+
|
|
125
|
+
### Media Variants
|
|
126
|
+
|
|
127
|
+
| Variant | Use Case |
|
|
128
|
+
|---------|----------|
|
|
129
|
+
| default | Large custom-sized icons (size-12), transparent background |
|
|
130
|
+
| icon | Standard icons with muted background, auto-sized to size-6 |
|
|
131
|
+
|
|
132
|
+
## Examples
|
|
133
|
+
|
|
134
|
+
### Basic Empty State
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
<Empty>
|
|
138
|
+
<EmptyHeader>
|
|
139
|
+
<EmptyMedia variant="icon">
|
|
140
|
+
<SearchIcon />
|
|
141
|
+
</EmptyMedia>
|
|
142
|
+
<EmptyTitle>No results found</EmptyTitle>
|
|
143
|
+
<EmptyDescription>
|
|
144
|
+
Try adjusting your search terms or filters.
|
|
145
|
+
</EmptyDescription>
|
|
146
|
+
</EmptyHeader>
|
|
147
|
+
</Empty>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### With Action Button
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
<Empty>
|
|
154
|
+
<EmptyHeader>
|
|
155
|
+
<EmptyMedia variant="icon">
|
|
156
|
+
<WebhookIcon />
|
|
157
|
+
</EmptyMedia>
|
|
158
|
+
<EmptyTitle>No webhooks configured</EmptyTitle>
|
|
159
|
+
<EmptyDescription>
|
|
160
|
+
Get started by creating your first webhook to receive real-time notifications.
|
|
161
|
+
</EmptyDescription>
|
|
162
|
+
</EmptyHeader>
|
|
163
|
+
<EmptyContent>
|
|
164
|
+
<Button>
|
|
165
|
+
<WebhookIcon data-icon="inline-start" />
|
|
166
|
+
Create Webhook
|
|
167
|
+
</Button>
|
|
168
|
+
</EmptyContent>
|
|
169
|
+
</Empty>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### With Multiple Actions
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
<Empty>
|
|
176
|
+
<EmptyHeader>
|
|
177
|
+
<EmptyMedia variant="icon">
|
|
178
|
+
<DatabaseIcon />
|
|
179
|
+
</EmptyMedia>
|
|
180
|
+
<EmptyTitle>No data sources</EmptyTitle>
|
|
181
|
+
<EmptyDescription>
|
|
182
|
+
Connect your first data source to start analyzing data.
|
|
183
|
+
</EmptyDescription>
|
|
184
|
+
</EmptyHeader>
|
|
185
|
+
<EmptyContent>
|
|
186
|
+
<div className="flex flex-col gap-2 sm:flex-row">
|
|
187
|
+
<Button>Connect Data Source</Button>
|
|
188
|
+
<Button variant="outline">View Documentation</Button>
|
|
189
|
+
</div>
|
|
190
|
+
</EmptyContent>
|
|
191
|
+
</Empty>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### With Link in Description
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
<Empty>
|
|
198
|
+
<EmptyHeader>
|
|
199
|
+
<EmptyMedia>
|
|
200
|
+
<DatabaseIcon className="size-12 text-muted-foreground" />
|
|
201
|
+
</EmptyMedia>
|
|
202
|
+
<EmptyTitle>No data available</EmptyTitle>
|
|
203
|
+
<EmptyDescription>
|
|
204
|
+
Start collecting data by setting up your first integration.{" "}
|
|
205
|
+
<a href="#">Learn more</a>
|
|
206
|
+
</EmptyDescription>
|
|
207
|
+
</EmptyHeader>
|
|
208
|
+
</Empty>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Large Icon (Default Variant)
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
<Empty>
|
|
215
|
+
<EmptyHeader>
|
|
216
|
+
<EmptyMedia variant="default">
|
|
217
|
+
<FileTextIcon className="size-12 text-muted-foreground" />
|
|
218
|
+
</EmptyMedia>
|
|
219
|
+
<EmptyTitle>No documents</EmptyTitle>
|
|
220
|
+
<EmptyDescription>
|
|
221
|
+
Use the default variant with manually sized icons for larger displays.
|
|
222
|
+
</EmptyDescription>
|
|
223
|
+
</EmptyHeader>
|
|
224
|
+
</Empty>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Minimal (No Media)
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
<Empty>
|
|
231
|
+
<EmptyHeader>
|
|
232
|
+
<EmptyTitle>No items to display</EmptyTitle>
|
|
233
|
+
<EmptyDescription>
|
|
234
|
+
Empty states can work without media icons for simpler contexts.
|
|
235
|
+
</EmptyDescription>
|
|
236
|
+
</EmptyHeader>
|
|
237
|
+
</Empty>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Success/Completed State
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
<Empty>
|
|
244
|
+
<EmptyHeader>
|
|
245
|
+
<EmptyMedia variant="icon">
|
|
246
|
+
<InboxIcon />
|
|
247
|
+
</EmptyMedia>
|
|
248
|
+
<EmptyTitle>All caught up!</EmptyTitle>
|
|
249
|
+
<EmptyDescription>
|
|
250
|
+
You have no new notifications. We'll notify you when something happens.
|
|
251
|
+
</EmptyDescription>
|
|
252
|
+
</EmptyHeader>
|
|
253
|
+
</Empty>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Composition Patterns
|
|
257
|
+
|
|
258
|
+
### Minimal Pattern
|
|
259
|
+
Header with media and title only (no description, no actions).
|
|
260
|
+
|
|
261
|
+
### Standard Pattern
|
|
262
|
+
Header with media, title, and description (no actions).
|
|
263
|
+
|
|
264
|
+
### Action Pattern
|
|
265
|
+
Complete header + content section with one or more buttons.
|
|
266
|
+
|
|
267
|
+
### Text-Only Pattern
|
|
268
|
+
Header with title and description, no media or actions.
|
|
269
|
+
|
|
270
|
+
## Accessibility
|
|
271
|
+
|
|
272
|
+
- Use semantic HTML elements for text content
|
|
273
|
+
- Ensure sufficient color contrast for text and icons
|
|
274
|
+
- Keep empty state messages clear and actionable
|
|
275
|
+
- Provide keyboard-accessible actions when present
|
|
276
|
+
- Consider loading states vs empty states for better UX
|
|
277
|
+
|
|
278
|
+
## Related
|
|
279
|
+
|
|
280
|
+
- Button - For empty state actions
|
|
281
|
+
- Alert - For error or warning states
|
|
282
|
+
- Card - Often contains empty states
|