@ceed/ads 1.20.0 → 1.20.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.
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
+ NavigationGroup is an expandable container for organizing related navigation items in a sidebar. Built on Joy UI's Accordion component, it provides a collapsible section that can hold NavigationItems or nested Navigator components. NavigationGroup creates hierarchical navigation structures where users can expand and collapse sections to access nested items.
6
+
5
7
  ```text
6
8
  // Unable to derive source for Default
7
9
  ```
@@ -13,5 +15,403 @@
13
15
  ## Usage
14
16
 
15
17
  ```tsx
16
- import { NavigationGroup } from '@ceed/ads';
18
+ import { NavigationGroup, NavigationItem } from '@ceed/ads';
19
+
20
+ function Sidebar() {
21
+ return (
22
+ <NavigationGroup
23
+ title="User Management"
24
+ startDecorator={<PeopleIcon />}
25
+ defaultExpanded={true}
26
+ >
27
+ <NavigationItem id="users" level={1}>All Users</NavigationItem>
28
+ <NavigationItem id="roles" level={1}>Roles</NavigationItem>
29
+ <NavigationItem id="permissions" level={1}>Permissions</NavigationItem>
30
+ </NavigationGroup>
31
+ );
32
+ }
33
+ ```
34
+
35
+ ## Examples
36
+
37
+ ### Default
38
+
39
+ Basic navigation group with a title and content.
40
+
41
+ ```text
42
+ // Unable to derive source for Default
43
+ ```
44
+
45
+ ### Nesting Levels
46
+
47
+ NavigationGroup supports different indentation levels for nested hierarchies.
48
+
49
+ ```text
50
+ // Unable to derive source for Level1
51
+ ```
52
+
53
+ ```text
54
+ // Unable to derive source for Level2
55
+ ```
56
+
57
+ ### With Start Decorator
58
+
59
+ Add an icon before the group title.
60
+
61
+ ```text
62
+ // Unable to derive source for WithStartDecorator
63
+ ```
64
+
65
+ ### Levels with Icons
66
+
67
+ Icons work at any nesting level.
68
+
69
+ ```text
70
+ // Unable to derive source for Level1WithStartDecorator
71
+ ```
72
+
73
+ ```text
74
+ // Unable to derive source for Level2WithStartDecorator
75
+ ```
76
+
77
+ ## When to Use
78
+
79
+ ### ✅ Good Use Cases
80
+
81
+ - **Collapsible sidebar sections**: Organize navigation into expandable categories
82
+ - **Deep navigation hierarchies**: Group related items under collapsible headers
83
+ - **Admin interfaces**: Organize modules and sub-modules
84
+ - **Settings organization**: Group related settings under categories
85
+ - **File system navigation**: Folders containing nested items
86
+
87
+ ### ❌ When Not to Use
88
+
89
+ - **Flat navigation**: When all items are at the same level
90
+ - **Tab-like navigation**: Use Tabs for switching between views
91
+ - **Simple menus**: For 5 or fewer items, consider flat NavigationItems
92
+ - **Modal dialogs**: Use proper modal patterns instead
93
+ - **Accordion content**: For non-navigation accordions, use Accordion directly
94
+
95
+ ## Common Use Cases
96
+
97
+ ### Admin Module Navigation
98
+
99
+ ```tsx
100
+ function AdminNavigation() {
101
+ return (
102
+ <>
103
+ <NavigationGroup
104
+ title="User Management"
105
+ startDecorator={<PeopleIcon />}
106
+ defaultExpanded={true}
107
+ >
108
+ <NavigationItem id="users" level={1}>
109
+ All Users
110
+ </NavigationItem>
111
+ <NavigationItem id="invite" level={1}>
112
+ Invite User
113
+ </NavigationItem>
114
+ <NavigationItem id="roles" level={1}>
115
+ Roles & Permissions
116
+ </NavigationItem>
117
+ </NavigationGroup>
118
+
119
+ <NavigationGroup
120
+ title="Content"
121
+ startDecorator={<ArticleIcon />}
122
+ >
123
+ <NavigationItem id="posts" level={1}>
124
+ Posts
125
+ </NavigationItem>
126
+ <NavigationItem id="categories" level={1}>
127
+ Categories
128
+ </NavigationItem>
129
+ <NavigationItem id="media" level={1}>
130
+ Media Library
131
+ </NavigationItem>
132
+ </NavigationGroup>
133
+
134
+ <NavigationGroup
135
+ title="Settings"
136
+ startDecorator={<SettingsIcon />}
137
+ >
138
+ <NavigationItem id="general" level={1}>
139
+ General
140
+ </NavigationItem>
141
+ <NavigationItem id="security" level={1}>
142
+ Security
143
+ </NavigationItem>
144
+ <NavigationItem id="integrations" level={1}>
145
+ Integrations
146
+ </NavigationItem>
147
+ </NavigationGroup>
148
+ </>
149
+ );
150
+ }
151
+ ```
152
+
153
+ ### Nested Groups
154
+
155
+ ```tsx
156
+ function NestedNavigation() {
157
+ return (
158
+ <NavigationGroup
159
+ title="E-commerce"
160
+ startDecorator={<ShoppingCartIcon />}
161
+ defaultExpanded={true}
162
+ >
163
+ <NavigationItem id="dashboard" level={1}>
164
+ Dashboard
165
+ </NavigationItem>
166
+
167
+ <NavigationGroup
168
+ title="Products"
169
+ level={1}
170
+ defaultExpanded={true}
171
+ >
172
+ <NavigationItem id="all-products" level={2}>
173
+ All Products
174
+ </NavigationItem>
175
+ <NavigationItem id="add-product" level={2}>
176
+ Add Product
177
+ </NavigationItem>
178
+ <NavigationItem id="categories" level={2}>
179
+ Categories
180
+ </NavigationItem>
181
+ </NavigationGroup>
182
+
183
+ <NavigationGroup
184
+ title="Orders"
185
+ level={1}
186
+ >
187
+ <NavigationItem id="all-orders" level={2}>
188
+ All Orders
189
+ </NavigationItem>
190
+ <NavigationItem id="pending" level={2}>
191
+ Pending
192
+ </NavigationItem>
193
+ <NavigationItem id="completed" level={2}>
194
+ Completed
195
+ </NavigationItem>
196
+ </NavigationGroup>
197
+ </NavigationGroup>
198
+ );
199
+ }
200
+ ```
201
+
202
+ ### Documentation Sidebar
203
+
204
+ ```tsx
205
+ function DocsSidebar({ sections, currentPath }) {
206
+ return (
207
+ <nav>
208
+ {sections.map((section) => (
209
+ <NavigationGroup
210
+ key={section.id}
211
+ title={section.title}
212
+ startDecorator={<BookIcon />}
213
+ defaultExpanded={currentPath.startsWith(section.basePath)}
214
+ >
215
+ {section.pages.map((page) => (
216
+ <NavigationItem
217
+ key={page.id}
218
+ id={page.id}
219
+ level={1}
220
+ selected={currentPath === page.path}
221
+ onClick={() => navigate(page.path)}
222
+ >
223
+ {page.title}
224
+ </NavigationItem>
225
+ ))}
226
+ </NavigationGroup>
227
+ ))}
228
+ </nav>
229
+ );
230
+ }
17
231
  ```
232
+
233
+ ## Props and Customization
234
+
235
+ ### Key Props
236
+
237
+ | Prop | Type | Default | Description |
238
+ | ----------------- | --------------------- | ------- | ----------------------------- |
239
+ | `title` | `string \| ReactNode` | - | Group header title |
240
+ | `children` | `ReactNode` | - | Content shown when expanded |
241
+ | `startDecorator` | `ReactNode` | - | Icon before the title |
242
+ | `level` | `number` | `0` | Nesting level for indentation |
243
+ | `defaultExpanded` | `boolean` | `false` | Initial expanded state |
244
+
245
+ ### Accordion Props
246
+
247
+ NavigationGroup extends Joy UI's Accordion, so you can use additional Accordion props:
248
+
249
+ ```tsx
250
+ <NavigationGroup
251
+ title="Settings"
252
+ expanded={isExpanded}
253
+ onChange={(event, expanded) => setIsExpanded(expanded)}
254
+ >
255
+ {/* Content */}
256
+ </NavigationGroup>
257
+ ```
258
+
259
+ ### Custom Styling
260
+
261
+ ```tsx
262
+ <NavigationGroup
263
+ title="Custom Section"
264
+ sx={{
265
+ '& .NavigationGroup-Summary': {
266
+ fontWeight: 600,
267
+ },
268
+ '& .NavigationGroup-Details': {
269
+ backgroundColor: 'background.level2',
270
+ },
271
+ }}
272
+ >
273
+ {/* Content */}
274
+ </NavigationGroup>
275
+ ```
276
+
277
+ ## Accessibility
278
+
279
+ NavigationGroup leverages Joy UI's Accordion accessibility features:
280
+
281
+ ### ARIA Attributes
282
+
283
+ - `role="button"` on the expandable header
284
+ - `aria-expanded` indicates the current state
285
+ - `aria-controls` links header to content
286
+ - Content region has proper `role="region"`
287
+
288
+ ### Keyboard Navigation
289
+
290
+ - **Tab**: Focus the group header
291
+ - **Enter/Space**: Toggle expanded state
292
+ - **Arrow Down**: Move to first item when expanded
293
+ - **Arrow Up**: Move to header from first item
294
+
295
+ ### Screen Reader Support
296
+
297
+ ```tsx
298
+ // Expansion state is announced
299
+ <NavigationGroup title="Settings" defaultExpanded={true}>
300
+ {/* "Settings, expanded, button" */}
301
+ </NavigationGroup>
302
+ ```
303
+
304
+ ## Best Practices
305
+
306
+ ### ✅ Do
307
+
308
+ 1. **Use descriptive titles**: Group titles should clearly indicate the content category
309
+
310
+ ```tsx
311
+ // ✅ Good: Descriptive title
312
+ <NavigationGroup title="User Management">
313
+
314
+ // ❌ Bad: Vague title
315
+ <NavigationGroup title="More">
316
+ ```
317
+
318
+ 2. **Expand active sections**: Auto-expand groups containing the current page
319
+
320
+ ```tsx
321
+ <NavigationGroup
322
+ title="Products"
323
+ defaultExpanded={currentPath.startsWith('/products')}
324
+ >
325
+ ```
326
+
327
+ 3. **Limit group children**: Keep 3-7 items per group for easy scanning
328
+
329
+ 4. **Use consistent icons**: If using icons, apply them to all groups
330
+
331
+ ### ❌ Don't
332
+
333
+ 1. **Don't over-nest**: Maximum 2-3 levels of nesting
334
+
335
+ ```tsx
336
+ // ❌ Bad: Too deep
337
+ <NavigationGroup>
338
+ <NavigationGroup level={1}>
339
+ <NavigationGroup level={2}>
340
+ <NavigationGroup level={3}> {/* Too deep */}
341
+ ```
342
+
343
+ 2. **Don't mix patterns**: Be consistent with structure across all groups
344
+
345
+ 3. **Don't put actions in groups**: Navigation only, not buttons or forms
346
+
347
+ 4. **Don't hide critical navigation**: Important items should be easily discoverable
348
+
349
+ ## Performance Considerations
350
+
351
+ ### Lazy Load Content
352
+
353
+ For groups with heavy content, consider lazy loading:
354
+
355
+ ```tsx
356
+ function LazyNavigationGroup({ title, loadContent }) {
357
+ const [expanded, setExpanded] = useState(false);
358
+ const [content, setContent] = useState(null);
359
+
360
+ const handleChange = async (event, isExpanded) => {
361
+ setExpanded(isExpanded);
362
+ if (isExpanded && !content) {
363
+ const loadedContent = await loadContent();
364
+ setContent(loadedContent);
365
+ }
366
+ };
367
+
368
+ return (
369
+ <NavigationGroup
370
+ title={title}
371
+ expanded={expanded}
372
+ onChange={handleChange}
373
+ >
374
+ {content || <Skeleton />}
375
+ </NavigationGroup>
376
+ );
377
+ }
378
+ ```
379
+
380
+ ### Controlled Expansion
381
+
382
+ For complex navigation, control expansion at the parent level:
383
+
384
+ ```tsx
385
+ function SidebarNavigation() {
386
+ const [expandedGroups, setExpandedGroups] = useState(['products']);
387
+
388
+ const handleGroupChange = (groupId) => (event, isExpanded) => {
389
+ setExpandedGroups((prev) =>
390
+ isExpanded
391
+ ? [...prev, groupId]
392
+ : prev.filter((id) => id !== groupId)
393
+ );
394
+ };
395
+
396
+ return (
397
+ <>
398
+ <NavigationGroup
399
+ title="Products"
400
+ expanded={expandedGroups.includes('products')}
401
+ onChange={handleGroupChange('products')}
402
+ >
403
+ {/* Items */}
404
+ </NavigationGroup>
405
+ <NavigationGroup
406
+ title="Orders"
407
+ expanded={expandedGroups.includes('orders')}
408
+ onChange={handleGroupChange('orders')}
409
+ >
410
+ {/* Items */}
411
+ </NavigationGroup>
412
+ </>
413
+ );
414
+ }
415
+ ```
416
+
417
+ NavigationGroup provides the structure for organizing hierarchical sidebar navigation. Combine it with NavigationItem for individual links, or use it within Navigator for a complete navigation solution.