@syscore/ui-library 1.5.2 → 1.6.0

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.
@@ -1,5 +1,43 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
- import { Navigation } from "@/components/ui/navigation";
2
+ ("use client");
3
+
4
+ import {
5
+ Navigation,
6
+ NavigationBrand,
7
+ NavigationBack,
8
+ NavigationLogo,
9
+ NavigationMenu,
10
+ NavigationTray,
11
+ NavigationColumn,
12
+ NavigationLink,
13
+ NavigationActions,
14
+ NavigationAccount,
15
+ } from "@/components/ui/navigation";
16
+ import { StandardLogo } from "@/components/icons/StandardLogo";
17
+ import { AlphaIcon } from "@/components/icons/AlphaIcon";
18
+ import * as React from "react";
19
+ import { Globe } from "lucide-react";
20
+ import { Button } from "@/components/ui/button";
21
+
22
+ // Mock Link component for Storybook (simulates Next.js Link)
23
+ const Link = React.forwardRef<
24
+ HTMLAnchorElement,
25
+ { href: string; children?: React.ReactNode; className?: string }
26
+ >(({ href, children, className, ...props }, ref) => (
27
+ <a
28
+ ref={ref}
29
+ href={href}
30
+ className={className}
31
+ onClick={(e) => {
32
+ e.preventDefault();
33
+ console.log("Navigate to:", href);
34
+ }}
35
+ {...props}
36
+ >
37
+ {children}
38
+ </a>
39
+ ));
40
+ Link.displayName = "Link";
3
41
 
4
42
  const meta = {
5
43
  title: "Review/Navigation",
@@ -7,6 +45,147 @@ const meta = {
7
45
  tags: ["autodocs"],
8
46
  parameters: {
9
47
  layout: "fullscreen",
48
+ docs: {
49
+ description: {
50
+ component: `
51
+ Navigation component system with support for custom routing libraries.
52
+
53
+ ## Compound Component Pattern
54
+
55
+ The Navigation system uses a **compound component pattern** where multiple sub-components work together to create a cohesive navigation experience. This pattern provides several benefits:
56
+
57
+ - **Flexibility**: Mix and match components to build different navigation layouts
58
+ - **Composability**: Each component handles one concern (brand, menu, actions)
59
+ - **Shared Context**: Components communicate through React Context without prop drilling
60
+ - **Customization**: Override defaults while maintaining consistent behavior
61
+
62
+ ## Composition Pattern (asChild)
63
+
64
+ Most navigation components support the \`asChild\` prop, which enables **component composition** using Radix UI's Slot primitive. This pattern solves a critical problem: how do you add navigation styling and behavior to your routing library's Link component without creating wrapper elements?
65
+
66
+ ### Why asChild is Useful
67
+
68
+ **Problem without asChild:**
69
+ \`\`\`tsx
70
+ // ❌ Creates nested elements (a > a is invalid HTML)
71
+ <NavigationAccount>
72
+ <Link href="/account">
73
+ <NavAccount />
74
+ </Link>
75
+ </NavigationAccount>
76
+ \`\`\`
77
+
78
+ **Solution with asChild:**
79
+ \`\`\`tsx
80
+ // ✅ Merges props into a single element
81
+ <NavigationAccount asChild>
82
+ <Link href="/account" />
83
+ </NavigationAccount>
84
+ // Renders: <Link href="/account" className="navigation-account" aria-label="Account">...</Link>
85
+ \`\`\`
86
+
87
+ ### Benefits
88
+
89
+ 1. **Single DOM Element**: No wrapper divs, the Link becomes the navigation element
90
+ 2. **Props Merging**: Navigation styling, aria labels, and event handlers merge with Link props
91
+ 3. **Routing Library Agnostic**: Works with Next.js, React Router, Remix, or any Link component
92
+ 4. **Type Safety**: Full TypeScript support for both component's props
93
+
94
+ ### Basic Usage
95
+
96
+ \`\`\`tsx
97
+ import Link from "next/link"
98
+
99
+ <NavigationLink asChild>
100
+ <Link href="/about">About</Link>
101
+ </NavigationLink>
102
+
103
+ <NavigationLogo asChild>
104
+ <Link href="/" />
105
+ </NavigationLogo>
106
+
107
+ <NavigationAccount asChild>
108
+ <Link href="/account" />
109
+ </NavigationAccount>
110
+ \`\`\`
111
+
112
+ ### Default vs Custom Content
113
+
114
+ Components like \`NavigationAccount\` and \`NavigationLogo\` intelligently handle content:
115
+
116
+ \`\`\`tsx
117
+ // 1. Default icon (NavAccount injected automatically)
118
+ <NavigationAccount asChild>
119
+ <Link href="/account" />
120
+ </NavigationAccount>
121
+
122
+ // 2. Custom icon (override default)
123
+ <NavigationAccount asChild>
124
+ <Link href="/account">
125
+ <UserCircle className="h-5 w-5 text-bronze-500" />
126
+ </Link>
127
+ </NavigationAccount>
128
+
129
+ // 3. Custom text content
130
+ <NavigationAccount asChild>
131
+ <Link href="/account">
132
+ <span>My Account</span>
133
+ </Link>
134
+ </NavigationAccount>
135
+ \`\`\`
136
+
137
+ ### How It Works
138
+
139
+ When \`asChild={true}\`:
140
+ 1. The component uses Radix UI's \`Slot\` instead of rendering its own element
141
+ 2. Slot merges the component's props (className, aria-label, etc.) with the child element's props
142
+ 3. If the child has no content, the default icon is injected
143
+ 4. If the child has content, that content is used instead
144
+
145
+ \`\`\`tsx
146
+ // Without asChild (default behavior)
147
+ <NavigationAccount />
148
+ // Renders: <a href="/account" className="navigation-account"><NavAccount /></a>
149
+
150
+ // With asChild + no content (default icon injected)
151
+ <NavigationAccount asChild>
152
+ <Link href="/account" />
153
+ </NavigationAccount>
154
+ // Renders: <Link href="/account" className="navigation-account"><NavAccount /></Link>
155
+
156
+ // With asChild + custom content (your content used)
157
+ <NavigationAccount asChild>
158
+ <Link href="/account"><CustomIcon /></Link>
159
+ </NavigationAccount>
160
+ // Renders: <Link href="/account" className="navigation-account"><CustomIcon /></Link>
161
+ \`\`\`
162
+
163
+ ### Advanced Example: Conditional Rendering
164
+
165
+ \`\`\`tsx
166
+ const UserNav = ({ user }) => {
167
+ if (!user) {
168
+ return (
169
+ <NavigationAccount asChild>
170
+ <Link href="/login">
171
+ <LogIn className="h-5 w-5" />
172
+ </Link>
173
+ </NavigationAccount>
174
+ );
175
+ }
176
+
177
+ return (
178
+ <NavigationAccount asChild>
179
+ <Link href="/account">
180
+ <Avatar src={user.avatar} />
181
+ </Link>
182
+ </NavigationAccount>
183
+ );
184
+ };
185
+ \`\`\`
186
+ `,
187
+ },
188
+ },
10
189
  },
11
190
  } satisfies Meta<typeof Navigation>;
12
191
 
@@ -14,53 +193,351 @@ export default meta;
14
193
 
15
194
  type Story = StoryObj<typeof meta>;
16
195
 
17
- const navItems = [
18
- { label: "WELL", active: true },
19
- { label: "Pursuits", active: false },
20
- { label: "Network", active: false },
21
- { label: "Knowledge", active: false },
22
- { label: "IWBI", active: false },
23
- ];
24
-
25
196
  export const Default: Story = {
26
- args: {
27
- isStrategy: false,
28
- onLinkClick: (href) => console.log("Clicked:", href),
29
- pathname: "/",
30
- },
31
- render: (args) => (
197
+ render: () => (
32
198
  <div className="h-screen bg-cyan-900">
33
- <Navigation
34
- {...args}
35
- />
199
+ <Navigation>
200
+ <NavigationBrand>
201
+ <NavigationLogo />
202
+ </NavigationBrand>
36
203
 
204
+ <NavigationActions>
205
+ <NavigationAccount />
206
+ </NavigationActions>
207
+ </Navigation>
37
208
  </div>
38
209
  ),
39
210
  };
40
211
 
41
- export const WithNavItems: Story = {
42
- args: {
43
- navItems: navItems,
44
- isStrategy: false,
45
- onLinkClick: (href) => console.log("Clicked:", href),
46
- pathname: "/",
212
+ export const StandardNavigation: Story = {
213
+ render: () => {
214
+ return (
215
+ <div className="h-screen bg-cyan-900">
216
+ <Navigation>
217
+ <NavigationBrand>
218
+ <NavigationLogo />
219
+ <StandardLogo />
220
+ <AlphaIcon />
221
+ </NavigationBrand>
222
+
223
+ <NavigationActions>
224
+ <NavigationAccount />
225
+ </NavigationActions>
226
+ </Navigation>
227
+ </div>
228
+ );
229
+ },
230
+ };
231
+
232
+ export const WithActions: Story = {
233
+ render: () => {
234
+ const LanguageSwitcher = () => {
235
+ return (
236
+ <Button variant="clear" size="icon">
237
+ <Globe className="h-5 w-5" />
238
+ </Button>
239
+ );
240
+ };
241
+
242
+ return (
243
+ <div className="h-screen bg-cyan-900">
244
+ <Navigation>
245
+ <NavigationBrand>
246
+ <NavigationLogo />
247
+ <StandardLogo />
248
+ <AlphaIcon />
249
+ </NavigationBrand>
250
+
251
+ <NavigationActions>
252
+ <LanguageSwitcher />
253
+ <NavigationAccount />
254
+ </NavigationActions>
255
+ </Navigation>
256
+ </div>
257
+ );
47
258
  },
48
- render: (args) => (
49
- <div className="h-screen bg-cyan-900">
50
- <Navigation {...args} />
51
- </div>
52
- ),
53
259
  };
54
260
 
55
261
  export const StrategyMode: Story = {
56
- args: {
57
- isStrategy: true,
58
- onLinkClick: (href) => console.log("Clicked:", href),
59
- pathname: "/strategy",
262
+ render: () => {
263
+ const isStrategyPage = true;
264
+ return (
265
+ <div className="h-screen bg-white">
266
+ <Navigation light={isStrategyPage}>
267
+ <NavigationBrand>
268
+ <NavigationBack show={isStrategyPage} />
269
+ <NavigationLogo />
270
+ <StandardLogo dark={isStrategyPage} />
271
+ <AlphaIcon dark={isStrategyPage} />
272
+ </NavigationBrand>
273
+
274
+ <NavigationActions>
275
+ <NavigationAccount />
276
+ </NavigationActions>
277
+ </Navigation>
278
+ </div>
279
+ );
280
+ },
281
+ };
282
+
283
+ export const WithNavItems: Story = {
284
+ render: (args) => {
285
+ return (
286
+ <div className="h-screen bg-cyan-900">
287
+ <Navigation>
288
+ <NavigationBrand>
289
+ <NavigationLogo />
290
+ </NavigationBrand>
291
+
292
+ <NavigationMenu>
293
+ {/* WELL Tray */}
294
+ <NavigationTray
295
+ trigger="WELL"
296
+ title="WELL sets the standard for people-first places"
297
+ >
298
+ <NavigationColumn title="Everything">
299
+ {/* asChild pattern: NavigationLink merges its props with Link via Radix UI Slot */}
300
+ <NavigationLink asChild>
301
+ <Link href="/">Explore WELL</Link>
302
+ </NavigationLink>
303
+ <NavigationLink asChild>
304
+ <Link href="/">Enroll in WELL</Link>
305
+ </NavigationLink>
306
+ <NavigationLink asChild>
307
+ <Link href="/">What's new</Link>
308
+ </NavigationLink>
309
+ </NavigationColumn>
310
+ <NavigationColumn title="WHY WELL">
311
+ <NavigationLink asChild>
312
+ <Link href="/">Performance</Link>
313
+ </NavigationLink>
314
+ <NavigationLink asChild>
315
+ <Link href="/">ROI</Link>
316
+ </NavigationLink>
317
+ <NavigationLink asChild>
318
+ <Link href="/">Impact</Link>
319
+ </NavigationLink>
320
+ </NavigationColumn>
321
+ <NavigationColumn title="Standard">
322
+ <NavigationLink asChild>
323
+ <Link href="/">Strategies</Link>
324
+ </NavigationLink>
325
+ <NavigationLink asChild>
326
+ <Link href="/">Themes</Link>
327
+ </NavigationLink>
328
+ <NavigationLink asChild>
329
+ <Link href="/">Milestones</Link>
330
+ </NavigationLink>
331
+ </NavigationColumn>
332
+ <NavigationColumn title="Network">
333
+ <NavigationLink asChild>
334
+ <Link href="/">Organizations</Link>
335
+ </NavigationLink>
336
+ <NavigationLink asChild>
337
+ <Link href="/">People</Link>
338
+ </NavigationLink>
339
+ </NavigationColumn>
340
+ <NavigationColumn title="Solutions">
341
+ <NavigationLink asChild>
342
+ <Link href="/">Products</Link>
343
+ </NavigationLink>
344
+ <NavigationLink asChild>
345
+ <Link href="/">Services</Link>
346
+ </NavigationLink>
347
+ </NavigationColumn>
348
+ <NavigationColumn title="Places">
349
+ <NavigationLink asChild>
350
+ <Link href="/">Locations</Link>
351
+ </NavigationLink>
352
+ <NavigationLink asChild>
353
+ <Link href="/">Portfolios</Link>
354
+ </NavigationLink>
355
+ </NavigationColumn>
356
+ </NavigationTray>
357
+
358
+ {/* Pursuits Tray */}
359
+ <NavigationTray
360
+ trigger="Pursuits"
361
+ title="WELL works everywhere, at any scale"
362
+ >
363
+ <NavigationColumn title="SUBSCRIBE">
364
+ <NavigationLink asChild>
365
+ <Link href="/">WELL at scale</Link>
366
+ </NavigationLink>
367
+ <NavigationLink sub asChild>
368
+ <Link href="/">Pricing</Link>
369
+ </NavigationLink>
370
+ <NavigationLink sub asChild>
371
+ <Link href="/">Leaderboard</Link>
372
+ </NavigationLink>
373
+ </NavigationColumn>
374
+ <NavigationColumn title="Certify">
375
+ <NavigationLink asChild>
376
+ <Link href="/">WELL Certification</Link>
377
+ </NavigationLink>
378
+ <NavigationLink badge="PILOT" asChild>
379
+ <Link href="/">WELL Residence</Link>
380
+ </NavigationLink>
381
+ </NavigationColumn>
382
+ <NavigationColumn title="Get rated">
383
+ <NavigationLink asChild>
384
+ <Link href="/">WELL Ratings</Link>
385
+ </NavigationLink>
386
+ <NavigationLink sub bullet="#F3E7D8" asChild>
387
+ <Link href="/">Health-Safety Rating</Link>
388
+ </NavigationLink>
389
+ <NavigationLink sub bullet="#0F748A" asChild>
390
+ <Link href="/">Performance Rating</Link>
391
+ </NavigationLink>
392
+ <NavigationLink sub bullet="#17AA8D" asChild>
393
+ <Link href="/">Equity Rating</Link>
394
+ </NavigationLink>
395
+ </NavigationColumn>
396
+ </NavigationTray>
397
+
398
+ {/* Network Tray */}
399
+ <NavigationTray
400
+ trigger="Network"
401
+ title="Our network drives our movement"
402
+ >
403
+ <NavigationColumn title="JOIN">
404
+ <NavigationLink asChild>
405
+ <Link href="/">Membership</Link>
406
+ </NavigationLink>
407
+ <NavigationLink asChild>
408
+ <Link href="/">Works with WELL</Link>
409
+ </NavigationLink>
410
+ <NavigationLink sub bullet="#2E74AD" asChild>
411
+ <Link href="/">Enterprise Provider</Link>
412
+ </NavigationLink>
413
+ <NavigationLink sub bullet="#149EBD" asChild>
414
+ <Link href="/">Product Provider</Link>
415
+ </NavigationLink>
416
+ <NavigationLink sub bullet="#ED896F" asChild>
417
+ <Link href="/">Performance Testing Provider</Link>
418
+ </NavigationLink>
419
+ </NavigationColumn>
420
+ <NavigationColumn title="EARN">
421
+ <NavigationLink asChild>
422
+ <Link href="/">WELL AP</Link>
423
+ </NavigationLink>
424
+ <NavigationLink asChild>
425
+ <Link href="/">WELL Faculty</Link>
426
+ </NavigationLink>
427
+ </NavigationColumn>
428
+ </NavigationTray>
429
+
430
+ {/* Knowledge Tray */}
431
+ <NavigationTray
432
+ trigger="Knowledge"
433
+ title="Learn from the experts on health"
434
+ >
435
+ <NavigationColumn title="LEARN">
436
+ <NavigationLink asChild>
437
+ <Link href="/">WELL Forum</Link>
438
+ </NavigationLink>
439
+ <NavigationLink sub asChild>
440
+ <Link href="/">Threads</Link>
441
+ </NavigationLink>
442
+ <NavigationLink sub asChild>
443
+ <Link href="/">Webcasts</Link>
444
+ </NavigationLink>
445
+ <NavigationLink sub asChild>
446
+ <Link href="/">Trainings</Link>
447
+ </NavigationLink>
448
+ </NavigationColumn>
449
+ <NavigationColumn title="ATTEND">
450
+ <NavigationLink asChild>
451
+ <Link href="/">WELL 2025</Link>
452
+ </NavigationLink>
453
+ <NavigationLink sub asChild>
454
+ <Link href="/">Flagship events</Link>
455
+ </NavigationLink>
456
+ <NavigationLink sub asChild>
457
+ <Link href="/">Thematic summits</Link>
458
+ </NavigationLink>
459
+ <NavigationLink sub asChild>
460
+ <Link href="/">Regional summits</Link>
461
+ </NavigationLink>
462
+ </NavigationColumn>
463
+ <NavigationColumn title="GUIDANCE">
464
+ <NavigationLink asChild>
465
+ <Link href="/">Knowledge base</Link>
466
+ </NavigationLink>
467
+ <NavigationLink sub asChild>
468
+ <Link href="/">Tutorials</Link>
469
+ </NavigationLink>
470
+ <NavigationLink sub asChild>
471
+ <Link href="/">Guides</Link>
472
+ </NavigationLink>
473
+ <NavigationLink sub asChild>
474
+ <Link href="/">FAQs</Link>
475
+ </NavigationLink>
476
+ </NavigationColumn>
477
+ <NavigationColumn title="Resources">
478
+ <NavigationLink asChild>
479
+ <Link href="/">Resource library</Link>
480
+ </NavigationLink>
481
+ <NavigationLink sub asChild>
482
+ <Link href="/">Technical tools</Link>
483
+ </NavigationLink>
484
+ <NavigationLink sub asChild>
485
+ <Link href="/">Sales tools</Link>
486
+ </NavigationLink>
487
+ <NavigationLink sub asChild>
488
+ <Link href="/">Media</Link>
489
+ </NavigationLink>
490
+ </NavigationColumn>
491
+ </NavigationTray>
492
+
493
+ {/* IWBI Tray */}
494
+ <NavigationTray
495
+ trigger="IWBI"
496
+ title="The International WELL Building Institute (IWBI)"
497
+ >
498
+ <NavigationColumn title="About">
499
+ <NavigationLink asChild>
500
+ <Link href="/">IWBI</Link>
501
+ </NavigationLink>
502
+ <NavigationLink asChild>
503
+ <Link href="/">Research</Link>
504
+ </NavigationLink>
505
+ <NavigationLink asChild>
506
+ <Link href="/">Advocacy</Link>
507
+ </NavigationLink>
508
+ </NavigationColumn>
509
+ <NavigationColumn title="Meet">
510
+ <NavigationLink asChild>
511
+ <Link href="/">Team</Link>
512
+ </NavigationLink>
513
+ <NavigationLink asChild>
514
+ <Link href="/">Advisories</Link>
515
+ </NavigationLink>
516
+ <NavigationLink asChild>
517
+ <Link href="/">Governance Council</Link>
518
+ </NavigationLink>
519
+ </NavigationColumn>
520
+ <NavigationColumn title="Explore">
521
+ <NavigationLink asChild>
522
+ <Link href="/">Newsroom</Link>
523
+ </NavigationLink>
524
+ <NavigationLink asChild>
525
+ <Link href="/">Jobs</Link>
526
+ </NavigationLink>
527
+ <NavigationLink asChild>
528
+ <Link href="/">Blog</Link>
529
+ </NavigationLink>
530
+ </NavigationColumn>
531
+ </NavigationTray>
532
+ </NavigationMenu>
533
+
534
+ <NavigationActions>
535
+ <NavigationAccount asChild>
536
+ <Link href="/account" />
537
+ </NavigationAccount>
538
+ </NavigationActions>
539
+ </Navigation>
540
+ </div>
541
+ );
60
542
  },
61
- render: (args) => (
62
- <div className="h-screen bg-white">
63
- <Navigation {...args} />
64
- </div>
65
- ),
66
543
  };