@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,528 @@
|
|
|
1
|
+
# Sidebar
|
|
2
|
+
|
|
3
|
+
Comprehensive collapsible sidebar system with responsive behavior, keyboard shortcuts, and state persistence.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import {
|
|
9
|
+
Sidebar,
|
|
10
|
+
SidebarProvider,
|
|
11
|
+
SidebarTrigger,
|
|
12
|
+
SidebarInset,
|
|
13
|
+
SidebarContent,
|
|
14
|
+
SidebarHeader,
|
|
15
|
+
SidebarFooter,
|
|
16
|
+
SidebarMenu,
|
|
17
|
+
SidebarMenuItem,
|
|
18
|
+
SidebarMenuButton,
|
|
19
|
+
SidebarMenuSub,
|
|
20
|
+
SidebarMenuSubButton,
|
|
21
|
+
SidebarMenuSubItem,
|
|
22
|
+
SidebarGroup,
|
|
23
|
+
SidebarGroupLabel,
|
|
24
|
+
SidebarGroupContent,
|
|
25
|
+
SidebarGroupAction,
|
|
26
|
+
SidebarSeparator,
|
|
27
|
+
SidebarInput,
|
|
28
|
+
SidebarMenuAction,
|
|
29
|
+
SidebarMenuBadge,
|
|
30
|
+
SidebarMenuSkeleton,
|
|
31
|
+
SidebarRail,
|
|
32
|
+
useSidebar,
|
|
33
|
+
} from "@neynar/ui/sidebar"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Anatomy
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
<SidebarProvider>
|
|
40
|
+
<Sidebar>
|
|
41
|
+
<SidebarHeader>
|
|
42
|
+
<SidebarMenu>
|
|
43
|
+
<SidebarMenuItem>
|
|
44
|
+
<SidebarMenuButton>Header Content</SidebarMenuButton>
|
|
45
|
+
</SidebarMenuItem>
|
|
46
|
+
</SidebarMenu>
|
|
47
|
+
</SidebarHeader>
|
|
48
|
+
|
|
49
|
+
<SidebarContent>
|
|
50
|
+
<SidebarGroup>
|
|
51
|
+
<SidebarGroupLabel>Section</SidebarGroupLabel>
|
|
52
|
+
<SidebarGroupContent>
|
|
53
|
+
<SidebarMenu>
|
|
54
|
+
<SidebarMenuItem>
|
|
55
|
+
<SidebarMenuButton>Item</SidebarMenuButton>
|
|
56
|
+
</SidebarMenuItem>
|
|
57
|
+
</SidebarMenu>
|
|
58
|
+
</SidebarGroupContent>
|
|
59
|
+
</SidebarGroup>
|
|
60
|
+
</SidebarContent>
|
|
61
|
+
|
|
62
|
+
<SidebarFooter>
|
|
63
|
+
<SidebarMenu>
|
|
64
|
+
<SidebarMenuItem>
|
|
65
|
+
<SidebarMenuButton>Footer Content</SidebarMenuButton>
|
|
66
|
+
</SidebarMenuItem>
|
|
67
|
+
</SidebarMenu>
|
|
68
|
+
</SidebarFooter>
|
|
69
|
+
|
|
70
|
+
<SidebarRail />
|
|
71
|
+
</Sidebar>
|
|
72
|
+
|
|
73
|
+
<SidebarInset>
|
|
74
|
+
<header>
|
|
75
|
+
<SidebarTrigger />
|
|
76
|
+
<h1>Page Title</h1>
|
|
77
|
+
</header>
|
|
78
|
+
<main>Main content</main>
|
|
79
|
+
</SidebarInset>
|
|
80
|
+
</SidebarProvider>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Components
|
|
84
|
+
|
|
85
|
+
| Component | Description |
|
|
86
|
+
|-----------|-------------|
|
|
87
|
+
| SidebarProvider | Root provider managing state, keyboard shortcuts, persistence |
|
|
88
|
+
| Sidebar | Main sidebar container with responsive behavior |
|
|
89
|
+
| SidebarTrigger | Toggle button (hamburger icon) |
|
|
90
|
+
| SidebarInset | Main content area that adjusts to sidebar state |
|
|
91
|
+
| SidebarContent | Scrollable content area containing groups |
|
|
92
|
+
| SidebarHeader | Top section for branding/app switcher |
|
|
93
|
+
| SidebarFooter | Bottom section for user profile/settings |
|
|
94
|
+
| SidebarMenu | Menu list container |
|
|
95
|
+
| SidebarMenuItem | Menu item wrapper |
|
|
96
|
+
| SidebarMenuButton | Clickable menu button with variants |
|
|
97
|
+
| SidebarMenuSub | Nested submenu list |
|
|
98
|
+
| SidebarMenuSubButton | Submenu item button |
|
|
99
|
+
| SidebarMenuSubItem | Submenu item wrapper |
|
|
100
|
+
| SidebarGroup | Section container with optional label |
|
|
101
|
+
| SidebarGroupLabel | Section heading |
|
|
102
|
+
| SidebarGroupContent | Section content wrapper |
|
|
103
|
+
| SidebarGroupAction | Action button in group header |
|
|
104
|
+
| SidebarSeparator | Horizontal divider |
|
|
105
|
+
| SidebarInput | Search/filter input |
|
|
106
|
+
| SidebarMenuAction | Secondary action on menu items |
|
|
107
|
+
| SidebarMenuBadge | Notification badge on menu items |
|
|
108
|
+
| SidebarMenuSkeleton | Loading skeleton |
|
|
109
|
+
| SidebarRail | Drag-to-resize rail element |
|
|
110
|
+
| useSidebar | Hook to access sidebar context |
|
|
111
|
+
|
|
112
|
+
## Props
|
|
113
|
+
|
|
114
|
+
### SidebarProvider
|
|
115
|
+
|
|
116
|
+
Root wrapper managing all sidebar state and behavior.
|
|
117
|
+
|
|
118
|
+
| Prop | Type | Default | Description |
|
|
119
|
+
|------|------|---------|-------------|
|
|
120
|
+
| defaultOpen | boolean | true | Initial open state on desktop |
|
|
121
|
+
| open | boolean | - | Controlled open state |
|
|
122
|
+
| onOpenChange | (open: boolean) => void | - | State change callback (persists to cookie) |
|
|
123
|
+
|
|
124
|
+
**Auto-behaviors:**
|
|
125
|
+
- Keyboard shortcut: Cmd/Ctrl+B toggles sidebar
|
|
126
|
+
- Mobile detection: Renders Sheet on mobile
|
|
127
|
+
- Cookie persistence: Saves state as `sidebar_state`
|
|
128
|
+
- 7-day cookie expiration
|
|
129
|
+
|
|
130
|
+
### Sidebar
|
|
131
|
+
|
|
132
|
+
| Prop | Type | Default | Description |
|
|
133
|
+
|------|------|---------|-------------|
|
|
134
|
+
| side | "left" \| "right" | "left" | Which side to display |
|
|
135
|
+
| variant | "sidebar" \| "floating" \| "inset" | "sidebar" | Visual variant |
|
|
136
|
+
| collapsible | "offcanvas" \| "icon" \| "none" | "offcanvas" | Collapse behavior |
|
|
137
|
+
|
|
138
|
+
**Variants:**
|
|
139
|
+
- `sidebar`: Standard edge-to-edge sidebar
|
|
140
|
+
- `floating`: Sidebar with padding and rounded corners
|
|
141
|
+
- `inset`: Sidebar with inset content area
|
|
142
|
+
|
|
143
|
+
**Collapsible modes:**
|
|
144
|
+
- `offcanvas`: Slides completely off screen
|
|
145
|
+
- `icon`: Collapses to icon-only mode
|
|
146
|
+
- `none`: Always visible, non-collapsible
|
|
147
|
+
|
|
148
|
+
### SidebarMenuButton
|
|
149
|
+
|
|
150
|
+
| Prop | Type | Default | Description |
|
|
151
|
+
|------|------|---------|-------------|
|
|
152
|
+
| isActive | boolean | false | Mark as active/current page |
|
|
153
|
+
| variant | "default" \| "outline" | "default" | Button variant |
|
|
154
|
+
| size | "default" \| "sm" \| "lg" | "default" | Button size |
|
|
155
|
+
| tooltip | string \| TooltipProps | - | Tooltip shown when collapsed |
|
|
156
|
+
| render | ReactElement | - | Custom element to render as |
|
|
157
|
+
|
|
158
|
+
### SidebarMenuAction
|
|
159
|
+
|
|
160
|
+
| Prop | Type | Default | Description |
|
|
161
|
+
|------|------|---------|-------------|
|
|
162
|
+
| showOnHover | boolean | false | Only show on hover/focus |
|
|
163
|
+
| render | ReactElement | - | Custom element to render as |
|
|
164
|
+
|
|
165
|
+
### SidebarMenuSkeleton
|
|
166
|
+
|
|
167
|
+
| Prop | Type | Default | Description |
|
|
168
|
+
|------|------|---------|-------------|
|
|
169
|
+
| showIcon | boolean | false | Show icon skeleton |
|
|
170
|
+
|
|
171
|
+
**Auto-behaviors:**
|
|
172
|
+
- Randomizes width between 50-90% for realistic loading state
|
|
173
|
+
|
|
174
|
+
### SidebarMenuSubButton
|
|
175
|
+
|
|
176
|
+
| Prop | Type | Default | Description |
|
|
177
|
+
|------|------|---------|-------------|
|
|
178
|
+
| size | "sm" \| "md" | "md" | Button size |
|
|
179
|
+
| isActive | boolean | false | Mark as active/current page |
|
|
180
|
+
| render | ReactElement | - | Custom element to render as |
|
|
181
|
+
|
|
182
|
+
## Render Prop Pattern
|
|
183
|
+
|
|
184
|
+
Components with `render` prop support custom elements:
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
// Render as link
|
|
188
|
+
<SidebarMenuButton render={<a href="/dashboard" />}>
|
|
189
|
+
Dashboard
|
|
190
|
+
</SidebarMenuButton>
|
|
191
|
+
|
|
192
|
+
// Render as Next.js Link
|
|
193
|
+
<SidebarMenuButton render={<Link href="/settings" />}>
|
|
194
|
+
Settings
|
|
195
|
+
</SidebarMenuButton>
|
|
196
|
+
|
|
197
|
+
// Render as custom component
|
|
198
|
+
<SidebarMenuSubButton render={<NavLink to="/docs" />}>
|
|
199
|
+
Documentation
|
|
200
|
+
</SidebarMenuSubButton>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Data Attributes
|
|
204
|
+
|
|
205
|
+
| Attribute | When Present | Applied To |
|
|
206
|
+
|-----------|--------------|------------|
|
|
207
|
+
| data-state | "expanded" \| "collapsed" | Sidebar container |
|
|
208
|
+
| data-collapsible | "offcanvas" \| "icon" | Sidebar when collapsed |
|
|
209
|
+
| data-variant | "sidebar" \| "floating" \| "inset" | Sidebar container |
|
|
210
|
+
| data-side | "left" \| "right" | Sidebar container |
|
|
211
|
+
| data-active | When isActive=true | SidebarMenuButton |
|
|
212
|
+
| data-open | When tooltip open | SidebarMenuButton |
|
|
213
|
+
| data-mobile | "true" | Mobile sidebar (Sheet) |
|
|
214
|
+
|
|
215
|
+
## Examples
|
|
216
|
+
|
|
217
|
+
### Basic Sidebar
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import { SidebarProvider, Sidebar, SidebarContent, SidebarInset, SidebarTrigger } from "@neynar/ui/sidebar"
|
|
221
|
+
import { HomeIcon } from "lucide-react"
|
|
222
|
+
|
|
223
|
+
function App() {
|
|
224
|
+
return (
|
|
225
|
+
<SidebarProvider>
|
|
226
|
+
<Sidebar>
|
|
227
|
+
<SidebarContent>
|
|
228
|
+
<SidebarMenu>
|
|
229
|
+
<SidebarMenuItem>
|
|
230
|
+
<SidebarMenuButton isActive>
|
|
231
|
+
<HomeIcon className="size-4" />
|
|
232
|
+
<span>Home</span>
|
|
233
|
+
</SidebarMenuButton>
|
|
234
|
+
</SidebarMenuItem>
|
|
235
|
+
</SidebarMenu>
|
|
236
|
+
</SidebarContent>
|
|
237
|
+
</Sidebar>
|
|
238
|
+
|
|
239
|
+
<SidebarInset>
|
|
240
|
+
<header className="flex h-16 items-center gap-4 border-b px-6">
|
|
241
|
+
<SidebarTrigger />
|
|
242
|
+
<h1>Dashboard</h1>
|
|
243
|
+
</header>
|
|
244
|
+
<main className="p-6">Content</main>
|
|
245
|
+
</SidebarInset>
|
|
246
|
+
</SidebarProvider>
|
|
247
|
+
)
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### With Header and Footer
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
<Sidebar>
|
|
255
|
+
<SidebarHeader>
|
|
256
|
+
<SidebarMenu>
|
|
257
|
+
<SidebarMenuItem>
|
|
258
|
+
<SidebarMenuButton className="h-12">
|
|
259
|
+
<div className="bg-primary/10 flex size-8 items-center justify-center rounded-lg">
|
|
260
|
+
<LayoutDashboardIcon className="size-4" />
|
|
261
|
+
</div>
|
|
262
|
+
<div className="flex flex-col">
|
|
263
|
+
<span className="font-semibold">Neynar</span>
|
|
264
|
+
<span className="text-muted-foreground text-xs">Developer Portal</span>
|
|
265
|
+
</div>
|
|
266
|
+
</SidebarMenuButton>
|
|
267
|
+
</SidebarMenuItem>
|
|
268
|
+
</SidebarMenu>
|
|
269
|
+
</SidebarHeader>
|
|
270
|
+
|
|
271
|
+
<SidebarContent>
|
|
272
|
+
{/* Menu groups */}
|
|
273
|
+
</SidebarContent>
|
|
274
|
+
|
|
275
|
+
<SidebarFooter>
|
|
276
|
+
<SidebarMenu>
|
|
277
|
+
<SidebarMenuItem>
|
|
278
|
+
<SidebarMenuButton className="h-12">
|
|
279
|
+
<Avatar className="size-8">
|
|
280
|
+
<AvatarFallback>JD</AvatarFallback>
|
|
281
|
+
</Avatar>
|
|
282
|
+
<div className="flex flex-col">
|
|
283
|
+
<span className="text-sm font-medium">John Developer</span>
|
|
284
|
+
<span className="text-muted-foreground text-xs">john@example.com</span>
|
|
285
|
+
</div>
|
|
286
|
+
</SidebarMenuButton>
|
|
287
|
+
</SidebarMenuItem>
|
|
288
|
+
</SidebarMenu>
|
|
289
|
+
</SidebarFooter>
|
|
290
|
+
</Sidebar>
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Grouped Navigation
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
<SidebarContent>
|
|
297
|
+
<SidebarGroup>
|
|
298
|
+
<SidebarGroupLabel>Dashboard</SidebarGroupLabel>
|
|
299
|
+
<SidebarGroupContent>
|
|
300
|
+
<SidebarMenu>
|
|
301
|
+
<SidebarMenuItem>
|
|
302
|
+
<SidebarMenuButton isActive>
|
|
303
|
+
<HomeIcon className="size-4" />
|
|
304
|
+
<span>Overview</span>
|
|
305
|
+
</SidebarMenuButton>
|
|
306
|
+
</SidebarMenuItem>
|
|
307
|
+
<SidebarMenuItem>
|
|
308
|
+
<SidebarMenuButton>
|
|
309
|
+
<BarChartIcon className="size-4" />
|
|
310
|
+
<span>Analytics</span>
|
|
311
|
+
</SidebarMenuButton>
|
|
312
|
+
</SidebarMenuItem>
|
|
313
|
+
</SidebarMenu>
|
|
314
|
+
</SidebarGroupContent>
|
|
315
|
+
</SidebarGroup>
|
|
316
|
+
|
|
317
|
+
<SidebarSeparator />
|
|
318
|
+
|
|
319
|
+
<SidebarGroup>
|
|
320
|
+
<SidebarGroupLabel>Settings</SidebarGroupLabel>
|
|
321
|
+
<SidebarGroupContent>
|
|
322
|
+
<SidebarMenu>
|
|
323
|
+
<SidebarMenuItem>
|
|
324
|
+
<SidebarMenuButton>
|
|
325
|
+
<SettingsIcon className="size-4" />
|
|
326
|
+
<span>General</span>
|
|
327
|
+
</SidebarMenuButton>
|
|
328
|
+
</SidebarMenuItem>
|
|
329
|
+
</SidebarMenu>
|
|
330
|
+
</SidebarGroupContent>
|
|
331
|
+
</SidebarGroup>
|
|
332
|
+
</SidebarContent>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### With Nested Submenus
|
|
336
|
+
|
|
337
|
+
```tsx
|
|
338
|
+
<SidebarMenu>
|
|
339
|
+
<SidebarMenuItem>
|
|
340
|
+
<SidebarMenuButton>
|
|
341
|
+
<BookOpenIcon className="size-4" />
|
|
342
|
+
<span>Documentation</span>
|
|
343
|
+
</SidebarMenuButton>
|
|
344
|
+
<SidebarMenuSub>
|
|
345
|
+
<SidebarMenuSubItem>
|
|
346
|
+
<SidebarMenuSubButton href="#intro">
|
|
347
|
+
Introduction
|
|
348
|
+
</SidebarMenuSubButton>
|
|
349
|
+
</SidebarMenuSubItem>
|
|
350
|
+
<SidebarMenuSubItem>
|
|
351
|
+
<SidebarMenuSubButton href="#install" isActive>
|
|
352
|
+
Installation
|
|
353
|
+
</SidebarMenuSubButton>
|
|
354
|
+
</SidebarMenuSubItem>
|
|
355
|
+
<SidebarMenuSubItem>
|
|
356
|
+
<SidebarMenuSubButton href="#quickstart">
|
|
357
|
+
Quick Start
|
|
358
|
+
</SidebarMenuSubButton>
|
|
359
|
+
</SidebarMenuSubItem>
|
|
360
|
+
</SidebarMenuSub>
|
|
361
|
+
</SidebarMenuItem>
|
|
362
|
+
</SidebarMenu>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### With Badges and Actions
|
|
366
|
+
|
|
367
|
+
```tsx
|
|
368
|
+
<SidebarMenu>
|
|
369
|
+
<SidebarMenuItem>
|
|
370
|
+
<SidebarMenuButton>
|
|
371
|
+
<MessageSquareIcon className="size-4" />
|
|
372
|
+
<span>Messages</span>
|
|
373
|
+
<Badge className="ml-auto">5</Badge>
|
|
374
|
+
</SidebarMenuButton>
|
|
375
|
+
</SidebarMenuItem>
|
|
376
|
+
|
|
377
|
+
<SidebarMenuItem>
|
|
378
|
+
<SidebarMenuButton>
|
|
379
|
+
<KeyIcon className="size-4" />
|
|
380
|
+
<span>API Keys</span>
|
|
381
|
+
</SidebarMenuButton>
|
|
382
|
+
<SidebarMenuAction showOnHover>
|
|
383
|
+
<PlusIcon className="size-4" />
|
|
384
|
+
</SidebarMenuAction>
|
|
385
|
+
</SidebarMenuItem>
|
|
386
|
+
</SidebarMenu>
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Controlled State
|
|
390
|
+
|
|
391
|
+
```tsx
|
|
392
|
+
function App() {
|
|
393
|
+
const [open, setOpen] = useState(true)
|
|
394
|
+
|
|
395
|
+
return (
|
|
396
|
+
<SidebarProvider open={open} onOpenChange={setOpen}>
|
|
397
|
+
<Sidebar>
|
|
398
|
+
{/* sidebar content */}
|
|
399
|
+
</Sidebar>
|
|
400
|
+
|
|
401
|
+
<SidebarInset>
|
|
402
|
+
<button onClick={() => setOpen(!open)}>
|
|
403
|
+
{open ? "Close" : "Open"} Sidebar
|
|
404
|
+
</button>
|
|
405
|
+
</SidebarInset>
|
|
406
|
+
</SidebarProvider>
|
|
407
|
+
)
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### With Collapsible Groups
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@neynar/ui/collapsible"
|
|
415
|
+
|
|
416
|
+
<SidebarGroup>
|
|
417
|
+
<Collapsible defaultOpen>
|
|
418
|
+
<SidebarGroupLabel>
|
|
419
|
+
<CollapsibleTrigger className="flex w-full items-center">
|
|
420
|
+
<BookOpenIcon className="mr-2 size-4" />
|
|
421
|
+
Documentation
|
|
422
|
+
<ChevronDownIcon className="ml-auto size-4 transition-transform group-data-[state=open]:rotate-180" />
|
|
423
|
+
</CollapsibleTrigger>
|
|
424
|
+
</SidebarGroupLabel>
|
|
425
|
+
<CollapsibleContent>
|
|
426
|
+
<SidebarGroupContent>
|
|
427
|
+
<SidebarMenuSub>
|
|
428
|
+
{/* submenu items */}
|
|
429
|
+
</SidebarMenuSub>
|
|
430
|
+
</SidebarGroupContent>
|
|
431
|
+
</CollapsibleContent>
|
|
432
|
+
</Collapsible>
|
|
433
|
+
</SidebarGroup>
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Loading State
|
|
437
|
+
|
|
438
|
+
```tsx
|
|
439
|
+
<SidebarMenu>
|
|
440
|
+
<SidebarMenuItem>
|
|
441
|
+
<SidebarMenuSkeleton showIcon />
|
|
442
|
+
</SidebarMenuItem>
|
|
443
|
+
<SidebarMenuItem>
|
|
444
|
+
<SidebarMenuSkeleton showIcon />
|
|
445
|
+
</SidebarMenuItem>
|
|
446
|
+
<SidebarMenuItem>
|
|
447
|
+
<SidebarMenuSkeleton />
|
|
448
|
+
</SidebarMenuItem>
|
|
449
|
+
</SidebarMenu>
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### With Search Input
|
|
453
|
+
|
|
454
|
+
```tsx
|
|
455
|
+
<SidebarHeader>
|
|
456
|
+
<SidebarInput
|
|
457
|
+
type="search"
|
|
458
|
+
placeholder="Search..."
|
|
459
|
+
onChange={(e) => handleSearch(e.target.value)}
|
|
460
|
+
/>
|
|
461
|
+
</SidebarHeader>
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Using useSidebar Hook
|
|
465
|
+
|
|
466
|
+
```tsx
|
|
467
|
+
import { useSidebar } from "@neynar/ui/sidebar"
|
|
468
|
+
|
|
469
|
+
function CustomComponent() {
|
|
470
|
+
const { state, open, toggleSidebar, isMobile } = useSidebar()
|
|
471
|
+
|
|
472
|
+
return (
|
|
473
|
+
<div>
|
|
474
|
+
<p>Sidebar is {state}</p>
|
|
475
|
+
<p>Mobile: {isMobile ? "Yes" : "No"}</p>
|
|
476
|
+
<button onClick={toggleSidebar}>Toggle</button>
|
|
477
|
+
</div>
|
|
478
|
+
)
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Keyboard
|
|
483
|
+
|
|
484
|
+
| Key | Action |
|
|
485
|
+
|-----|--------|
|
|
486
|
+
| Cmd/Ctrl+B | Toggle sidebar open/closed |
|
|
487
|
+
| Escape | Close sidebar (mobile only) |
|
|
488
|
+
| Tab | Navigate between menu items |
|
|
489
|
+
|
|
490
|
+
## Accessibility
|
|
491
|
+
|
|
492
|
+
- Full keyboard navigation support with Tab/Shift+Tab
|
|
493
|
+
- Screen reader labels on SidebarTrigger and SidebarRail
|
|
494
|
+
- ARIA attributes managed automatically via data-attributes
|
|
495
|
+
- Focus management when toggling sidebar state
|
|
496
|
+
- Semantic HTML structure (nav, ul, li, button elements)
|
|
497
|
+
- Mobile sidebar uses Sheet with proper dialog semantics
|
|
498
|
+
|
|
499
|
+
## CSS Variables
|
|
500
|
+
|
|
501
|
+
| Variable | Description |
|
|
502
|
+
|----------|-------------|
|
|
503
|
+
| --sidebar-width | Desktop sidebar width (16rem) |
|
|
504
|
+
| --sidebar-width-mobile | Mobile sidebar width (18rem) |
|
|
505
|
+
| --sidebar-width-icon | Icon-only mode width (3rem) |
|
|
506
|
+
|
|
507
|
+
## Styling
|
|
508
|
+
|
|
509
|
+
Use data attributes for conditional styling:
|
|
510
|
+
|
|
511
|
+
```tsx
|
|
512
|
+
// Style based on sidebar state
|
|
513
|
+
className="hidden md:block group-data-[state=collapsed]:md:hidden"
|
|
514
|
+
|
|
515
|
+
// Style based on collapse mode
|
|
516
|
+
className="group-data-[collapsible=icon]:hidden"
|
|
517
|
+
|
|
518
|
+
// Style based on variant
|
|
519
|
+
className="group-data-[variant=floating]:rounded-lg"
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
## Related
|
|
523
|
+
|
|
524
|
+
- [Sheet](/components/sheet) - Used for mobile sidebar
|
|
525
|
+
- [Collapsible](/components/collapsible) - For collapsible groups
|
|
526
|
+
- [Button](/components/button) - SidebarMenuButton inherits from Button
|
|
527
|
+
- [Tooltip](/components/tooltip) - For collapsed state tooltips
|
|
528
|
+
- [Separator](/components/separator) - SidebarSeparator
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Skeleton
|
|
2
|
+
|
|
3
|
+
Loading placeholder with pulse animation to indicate content is being fetched.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Skeleton } from "@neynar/ui/skeleton"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Anatomy
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<Skeleton className="h-4 w-full" />
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
|
|
19
|
+
Accepts all standard HTML `div` attributes via `React.ComponentProps<"div">`:
|
|
20
|
+
|
|
21
|
+
| Prop | Type | Default | Description |
|
|
22
|
+
|------|------|---------|-------------|
|
|
23
|
+
| className | string | - | Additional CSS classes for custom sizing and shape |
|
|
24
|
+
|
|
25
|
+
The Skeleton component applies default styling: `bg-muted rounded-md animate-pulse`. Use `className` to override dimensions and border radius.
|
|
26
|
+
|
|
27
|
+
## Data Attributes
|
|
28
|
+
|
|
29
|
+
| Attribute | When Present |
|
|
30
|
+
|-----------|--------------|
|
|
31
|
+
| data-slot="skeleton" | Always present for styling hooks |
|
|
32
|
+
|
|
33
|
+
## Examples
|
|
34
|
+
|
|
35
|
+
### Text Line
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
<Skeleton className="h-4 w-full" />
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Multiple Lines
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
<div className="space-y-2">
|
|
45
|
+
<Skeleton className="h-4 w-full" />
|
|
46
|
+
<Skeleton className="h-4 w-5/6" />
|
|
47
|
+
<Skeleton className="h-4 w-4/6" />
|
|
48
|
+
</div>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Avatar
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
<Skeleton className="size-12 rounded-full" />
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### User Profile Card
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
<div className="flex items-center gap-4">
|
|
61
|
+
<Skeleton className="size-16 rounded-full" />
|
|
62
|
+
<div className="flex-1 space-y-2">
|
|
63
|
+
<Skeleton className="h-5 w-32" />
|
|
64
|
+
<Skeleton className="h-4 w-24" />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Button
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
<Skeleton className="h-10 w-24" />
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Card with Image
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
<div className="border rounded-lg p-4">
|
|
79
|
+
<Skeleton className="aspect-video w-full mb-4" />
|
|
80
|
+
<Skeleton className="h-5 w-3/4 mb-2" />
|
|
81
|
+
<Skeleton className="h-4 w-full" />
|
|
82
|
+
<Skeleton className="h-4 w-5/6 mt-2" />
|
|
83
|
+
</div>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Cast Feed Item
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
<div className="flex gap-3">
|
|
90
|
+
<Skeleton className="size-10 rounded-full" />
|
|
91
|
+
<div className="flex-1 space-y-3">
|
|
92
|
+
<div className="flex items-center gap-2">
|
|
93
|
+
<Skeleton className="h-4 w-24" />
|
|
94
|
+
<Skeleton className="h-3 w-16" />
|
|
95
|
+
</div>
|
|
96
|
+
<div className="space-y-2">
|
|
97
|
+
<Skeleton className="h-4 w-full" />
|
|
98
|
+
<Skeleton className="h-4 w-5/6" />
|
|
99
|
+
</div>
|
|
100
|
+
<div className="flex gap-4">
|
|
101
|
+
<Skeleton className="h-8 w-16" />
|
|
102
|
+
<Skeleton className="h-8 w-16" />
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### API Analytics Card
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
<div className="border rounded-lg p-4">
|
|
112
|
+
<Skeleton className="h-4 w-24 mb-2" />
|
|
113
|
+
<Skeleton className="h-8 w-16 mb-4" />
|
|
114
|
+
<Skeleton className="h-2 w-full" />
|
|
115
|
+
</div>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Data Table Row
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
<div className="flex items-center gap-4 p-4">
|
|
122
|
+
<Skeleton className="size-8 rounded" />
|
|
123
|
+
<Skeleton className="h-4 flex-1" />
|
|
124
|
+
<Skeleton className="h-4 w-24" />
|
|
125
|
+
<Skeleton className="h-4 w-32" />
|
|
126
|
+
<Skeleton className="size-8 rounded" />
|
|
127
|
+
</div>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Accessibility
|
|
131
|
+
|
|
132
|
+
- Skeleton is purely visual and doesn't convey semantic meaning
|
|
133
|
+
- Ensure parent containers have appropriate ARIA live regions when content updates
|
|
134
|
+
- Consider using `aria-busy="true"` on loading containers
|
|
135
|
+
- Maintain proper layout structure so screen readers understand context when content loads
|
|
136
|
+
|
|
137
|
+
## Related
|
|
138
|
+
|
|
139
|
+
- [Spinner](./spinner.llm.md) - For indeterminate loading states
|
|
140
|
+
- [Progress](./progress.llm.md) - For determinate loading states
|