Skip to content

Commit 7b38ce1

Browse files
committed
Allow children in mobile nav
Adds some finishing touches to @olayway's work to allow the mobile nav to render arbitrary children which can be useful for things like site-wide navigation. Also adds some stories to demonstrate the new functionality and migrates to the Storybook NextJs 'framework' which allows the Nav component to be rendered in a story with all the routing automatically stubbed and taken care of.
1 parent f7f03fd commit 7b38ce1

File tree

6 files changed

+7034
-3327
lines changed

6 files changed

+7034
-3327
lines changed

package-lock.json

Lines changed: 6788 additions & 3262 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/.storybook/main.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { StorybookConfig } from '@storybook/react-webpack5';
1+
import type { StorybookConfig } from '@storybook/nextjs';
22

33
const config: StorybookConfig = {
44
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
@@ -7,15 +7,26 @@ const config: StorybookConfig = {
77
'@storybook/addon-interactions',
88
'@storybook/addon-a11y',
99
'@nrwl/react/plugins/storybook',
10-
'storybook-tailwind-dark-mode'
10+
'storybook-tailwind-dark-mode',
1111
],
1212
framework: {
13-
name: '@storybook/react-webpack5',
13+
name: '@storybook/nextjs',
1414
options: {},
1515
},
1616
docs: {
1717
autodocs: 'tag',
1818
},
19+
webpackFinal: async (config) => {
20+
config.resolve = {
21+
...config.resolve,
22+
fallback: {
23+
...(config.resolve || {}).fallback,
24+
crypto: false,
25+
},
26+
};
27+
28+
return config;
29+
},
1930
};
2031

2132
export default config;

packages/core/package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"access": "public"
1818
},
1919
"scripts": {
20-
"prepare": "nx build core"
20+
"prepare": "nx build core",
21+
"storybook": "storybook dev"
2122
},
2223
"files": [
2324
"dist"
@@ -53,6 +54,10 @@
5354
"react-dom": "^18.2.0"
5455
},
5556
"devDependencies": {
56-
"@storybook/addon-a11y": "^7.4.6"
57+
"@storybook/addon-a11y": "^7.4.6",
58+
"@storybook/nextjs": "^7.6.12"
59+
},
60+
"browser": {
61+
"crypto": false
5762
}
5863
}
Lines changed: 147 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,160 @@
11
import type { Meta, StoryObj } from '@storybook/react';
2+
import React from 'react';
23

3-
import { NavTitle } from './NavTitle';
4+
import { Nav } from './Nav';
5+
import { SiteToc } from '../SiteToc';
46

5-
const meta: Meta<typeof NavTitle> = {
6-
component: NavTitle,
7-
tags: ['autodocs'],
7+
const meta: Meta<typeof Nav> = {
8+
component: Nav,
9+
tags: ['autodocs'],
810
};
911

1012
export default meta;
1113

12-
type Story = StoryObj<typeof NavTitle>;
14+
type Story = StoryObj<typeof Nav>;
1315

1416
export const Basic: Story = {
15-
args: {
16-
title: 'Title',
17-
logo: 'https://via.placeholder.com/50',
18-
},
17+
args: {
18+
title: 'Title',
19+
logo: 'https://via.placeholder.com/50',
20+
},
1921
};
2022

21-
export const WithVersion: Story = {
22-
args: {
23-
title: 'Title',
24-
logo: 'https://via.placeholder.com/50',
25-
version: 'Alpha',
23+
export const MobileWithChildren: Story = {
24+
parameters: {
25+
viewport: {
26+
defaultViewport: 'mobile1',
2627
},
28+
},
29+
args: {
30+
title: 'Title',
31+
logo: 'https://via.placeholder.com/50',
32+
links: [
33+
{
34+
name: 'Home',
35+
href: '/',
36+
},
37+
{
38+
name: 'About',
39+
href: '/about',
40+
},
41+
{
42+
name: 'Blog',
43+
href: '/blog',
44+
},
45+
],
46+
children: <SiteToc currentPath="about" nav={getNav()} />,
47+
},
2748
};
49+
50+
function getNav() {
51+
return [
52+
{
53+
name: 'about',
54+
href: 'about',
55+
},
56+
{
57+
name: 'page2',
58+
href: 'page2',
59+
},
60+
{
61+
name: 'page3',
62+
href: 'page3',
63+
},
64+
{
65+
name: 'page4',
66+
href: 'page4',
67+
},
68+
{
69+
name: 'page5',
70+
href: 'page5',
71+
},
72+
{
73+
name: 'page6',
74+
href: 'page6',
75+
},
76+
{
77+
name: 'page7',
78+
href: 'page7',
79+
},
80+
{
81+
name: 'page8',
82+
href: 'page8',
83+
},
84+
{
85+
name: 'page9',
86+
href: 'page9',
87+
},
88+
{
89+
name: 'Blog',
90+
path: 'blog',
91+
level: 0,
92+
children: [
93+
{
94+
name: 'My SEO blog post fail',
95+
href: 'blog/blog-post-fail',
96+
},
97+
{
98+
name: 'Schedule Your Social marketing',
99+
href: 'blog/schedule-your-social-marketing',
100+
},
101+
],
102+
},
103+
{
104+
name: 'Dev',
105+
path: 'dev',
106+
level: 0,
107+
children: [
108+
{
109+
name: 'columns-vs-flex-vs-grid',
110+
href: 'dev/columns-vs-flex-vs-grid',
111+
},
112+
{
113+
name: 'how-to-test-web-apps',
114+
href: 'dev/how-to-test-web-apps',
115+
},
116+
{
117+
name: 'instance-type',
118+
href: 'dev/instance-type',
119+
},
120+
],
121+
},
122+
{
123+
name: 'Marketing',
124+
path: 'marketing',
125+
level: 0,
126+
children: [
127+
{
128+
name: 'seo',
129+
href: 'marketing/seo',
130+
},
131+
],
132+
},
133+
{
134+
name: 'Productivity',
135+
path: 'productivity',
136+
level: 0,
137+
children: [
138+
{
139+
name: 'effective-macos-task-management',
140+
href: 'productivity/effective-macos-task-management',
141+
},
142+
{
143+
name: 'productivity-system',
144+
href: 'productivity/productivity-system',
145+
},
146+
],
147+
},
148+
{
149+
name: 'Tech',
150+
path: 'tech',
151+
level: 0,
152+
children: [
153+
{
154+
name: 'roll-your-own-personal-backups',
155+
href: 'tech/roll-your-own-personal-backups',
156+
},
157+
],
158+
},
159+
];
160+
}

packages/core/src/ui/Nav/NavMobile.tsx

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -62,53 +62,58 @@ export const NavMobile: React.FC<Props> = ({
6262
aria-label="Navigation"
6363
>
6464
<Dialog.Panel className="relative min-h-full w-full max-w-xs bg-background px-4 pt-5 pb-12 dark:bg-background-dark sm:px-6">
65-
<div className="flex items-center mb-6">
66-
<button
67-
type="button"
68-
onClick={() => setIsOpen(false)}
69-
aria-label="Close navigation"
70-
>
71-
<CloseIcon className="h-6 w-6 stroke-slate-500" />
72-
</button>
73-
<Link
74-
href="/"
75-
className="ml-6"
76-
aria-label="Home page"
77-
legacyBehavior
78-
>
79-
{/* <Logomark className="h-9 w-9" /> */}
80-
<div className="font-extrabold text-primary dark:text-primary-dark text-2xl ml-6">
81-
{author}
82-
</div>
83-
</Link>
65+
<div className="px-4 sm:px-6 pt-5">
66+
<div className="flex items-center mb-6">
67+
<button
68+
type="button"
69+
onClick={() => setIsOpen(false)}
70+
aria-label="Close navigation"
71+
>
72+
<CloseIcon className="h-6 w-6 stroke-slate-500" />
73+
</button>
74+
<Link
75+
href="/"
76+
className="ml-6"
77+
aria-label="Home page"
78+
legacyBehavior
79+
>
80+
{/* <Logomark className="h-9 w-9" /> */}
81+
<div className="font-extrabold text-primary dark:text-primary-dark text-2xl ml-6">
82+
{author}
83+
</div>
84+
</Link>
85+
</div>
86+
{Search && (
87+
<Search>
88+
{({ query }: any) => <SearchField mobile onOpen={query.toggle} />}
89+
</Search>
90+
)}
91+
{links && (
92+
<ul className="mt-2 space-y-2 border-l-2 border-slate-100 dark:border-slate-800 lg:mt-4 lg:space-y-4 lg:border-slate-200">
93+
{links.map((link) => (
94+
<Menu as="div" key={link.name} className="relative">
95+
<Menu.Button>
96+
<li key={link.href}>
97+
<Link
98+
href={link.href}
99+
className={`
100+
block w-full pl-3.5 before:pointer-events-none before:absolute before:-left-1 before:top-1/2 before:h-1.5 before:w-1.5 before:-translate-y-1/2 before:rounded-full text-slate-500 before:hidden before:bg-slate-300 hover:text-slate-600 hover:before:block dark:text-slate-400 dark:before:bg-slate-700 dark:hover:text-slate-300`}
101+
>
102+
{link.name}
103+
</Link>
104+
</li>
105+
</Menu.Button>
106+
</Menu>
107+
))}
108+
</ul>
109+
)}
84110
</div>
85-
{Search && (
86-
<Search>
87-
{({ query }: any) => <SearchField mobile onOpen={query.toggle} />}
88-
</Search>
89-
)}
90-
{links && (
91-
<ul className="mt-2 space-y-2 border-l-2 border-slate-100 dark:border-slate-800 lg:mt-4 lg:space-y-4 lg:border-slate-200">
92-
{links.map((link) => (
93-
<Menu as="div" key={link.name} className="relative">
94-
<Menu.Button>
95-
<li key={link.href}>
96-
<Link
97-
href={link.href}
98-
className={`
99-
block w-full pl-3.5 before:pointer-events-none before:absolute before:-left-1 before:top-1/2 before:h-1.5 before:w-1.5 before:-translate-y-1/2 before:rounded-full text-slate-500 before:hidden before:bg-slate-300 hover:text-slate-600 hover:before:block dark:text-slate-400 dark:before:bg-slate-700 dark:hover:text-slate-300`}
100-
>
101-
{link.name}
102-
</Link>
103-
</li>
104-
</Menu.Button>
105-
</Menu>
106-
))}
107-
</ul>
108-
)}
109-
{/* <div className="pt-6 border border-t-2">
110-
{children}
111-
</div> */}
111+
{children ? (
112+
<>
113+
<hr className="my-6" />
114+
<div className="pl-8 pr-4 sm:px-6">{children}</div>
115+
</>
116+
) : null}
112117
</Dialog.Panel>
113118
</Dialog>
114119
</>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { Meta, StoryObj } from '@storybook/react';
2+
3+
import { NavTitle } from './NavTitle';
4+
5+
const meta: Meta<typeof NavTitle> = {
6+
component: NavTitle,
7+
tags: ['autodocs'],
8+
};
9+
10+
export default meta;
11+
12+
type Story = StoryObj<typeof NavTitle>;
13+
14+
export const Basic: Story = {
15+
args: {
16+
title: 'Title',
17+
logo: 'https://via.placeholder.com/50',
18+
},
19+
};
20+
21+
export const WithVersion: Story = {
22+
args: {
23+
title: 'Title',
24+
logo: 'https://via.placeholder.com/50',
25+
version: 'Alpha',
26+
},
27+
};

0 commit comments

Comments
 (0)