Skip to content

Commit

Permalink
Allow children in mobile nav
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
homostellaris committed Feb 2, 2024
1 parent f7f03fd commit 3334166
Show file tree
Hide file tree
Showing 6 changed files with 7,048 additions and 3,339 deletions.
10,050 changes: 6,788 additions & 3,262 deletions package-lock.json

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions packages/core/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { StorybookConfig } from '@storybook/react-webpack5';
import type { StorybookConfig } from '@storybook/nextjs';

const config: StorybookConfig = {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
Expand All @@ -7,15 +7,26 @@ const config: StorybookConfig = {
'@storybook/addon-interactions',
'@storybook/addon-a11y',
'@nrwl/react/plugins/storybook',
'storybook-tailwind-dark-mode'
'storybook-tailwind-dark-mode',
],
framework: {
name: '@storybook/react-webpack5',
name: '@storybook/nextjs',
options: {},
},
docs: {
autodocs: 'tag',
},
webpackFinal: async (config) => {
config.resolve = {
...config.resolve,
fallback: {
...(config.resolve || {}).fallback,
crypto: false,
},
};

return config;
},
};

export default config;
Expand Down
9 changes: 7 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"access": "public"
},
"scripts": {
"prepare": "nx build core"
"prepare": "nx build core",
"storybook": "storybook dev"
},
"files": [
"dist"
Expand Down Expand Up @@ -53,6 +54,10 @@
"react-dom": "^18.2.0"
},
"devDependencies": {
"@storybook/addon-a11y": "^7.4.6"
"@storybook/addon-a11y": "^7.4.6",
"@storybook/nextjs": "^7.6.12"
},
"browser": {
"crypto": false
}
}
161 changes: 147 additions & 14 deletions packages/core/src/ui/Nav/Nav.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,160 @@
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';

import { NavTitle } from './NavTitle';
import { Nav } from './Nav';
import { SiteToc } from '../SiteToc';

const meta: Meta<typeof NavTitle> = {
component: NavTitle,
tags: ['autodocs'],
const meta: Meta<typeof Nav> = {
component: Nav,
tags: ['autodocs'],
};

export default meta;

type Story = StoryObj<typeof NavTitle>;
type Story = StoryObj<typeof Nav>;

export const Basic: Story = {
args: {
title: 'Title',
logo: 'https://via.placeholder.com/50',
},
args: {
title: 'Title',
logo: 'https://via.placeholder.com/50',
},
};

export const WithVersion: Story = {
args: {
title: 'Title',
logo: 'https://via.placeholder.com/50',
version: 'Alpha',
export const MobileWithChildren: Story = {
parameters: {
viewport: {
defaultViewport: 'mobile1',
},
},
args: {
title: 'Title',
logo: 'https://via.placeholder.com/50',
links: [
{
name: 'Home',
href: '/',
},
{
name: 'About',
href: '/about',
},
{
name: 'Blog',
href: '/blog',
},
],
children: <SiteToc currentPath="about" nav={getNav()} />,
},
};

function getNav() {
return [
{
name: 'about',
href: 'about',
},
{
name: 'page2',
href: 'page2',
},
{
name: 'page3',
href: 'page3',
},
{
name: 'page4',
href: 'page4',
},
{
name: 'page5',
href: 'page5',
},
{
name: 'page6',
href: 'page6',
},
{
name: 'page7',
href: 'page7',
},
{
name: 'page8',
href: 'page8',
},
{
name: 'page9',
href: 'page9',
},
{
name: 'Blog',
path: 'blog',
level: 0,
children: [
{
name: 'My SEO blog post fail',
href: 'blog/blog-post-fail',
},
{
name: 'Schedule Your Social marketing',
href: 'blog/schedule-your-social-marketing',
},
],
},
{
name: 'Dev',
path: 'dev',
level: 0,
children: [
{
name: 'columns-vs-flex-vs-grid',
href: 'dev/columns-vs-flex-vs-grid',
},
{
name: 'how-to-test-web-apps',
href: 'dev/how-to-test-web-apps',
},
{
name: 'instance-type',
href: 'dev/instance-type',
},
],
},
{
name: 'Marketing',
path: 'marketing',
level: 0,
children: [
{
name: 'seo',
href: 'marketing/seo',
},
],
},
{
name: 'Productivity',
path: 'productivity',
level: 0,
children: [
{
name: 'effective-macos-task-management',
href: 'productivity/effective-macos-task-management',
},
{
name: 'productivity-system',
href: 'productivity/productivity-system',
},
],
},
{
name: 'Tech',
path: 'tech',
level: 0,
children: [
{
name: 'roll-your-own-personal-backups',
href: 'tech/roll-your-own-personal-backups',
},
],
},
];
}
123 changes: 65 additions & 58 deletions packages/core/src/ui/Nav/NavMobile.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Dialog, Menu } from "@headlessui/react";
import Link from "next/link.js";
import { useRouter } from "next/router.js";
import { useEffect, useState } from "react";
import { SearchContext, SearchField } from "../Search";
import { MenuIcon, CloseIcon } from "../Icons";
import { NavLink, SearchProviderConfig } from "../types";
import { Dialog, Menu } from '@headlessui/react';
import Link from 'next/link.js';
import { useRouter } from 'next/router.js';
import { useEffect, useState } from 'react';
import { SearchContext, SearchField } from '../Search';
import { MenuIcon, CloseIcon } from '../Icons';
import { NavLink, SearchProviderConfig } from '../types';

interface Props extends React.PropsWithChildren {
author?: string;
Expand All @@ -30,12 +30,12 @@ export const NavMobile: React.FC<Props> = ({
setIsOpen(false);
}

router.events.on("routeChangeComplete", onRouteChange);
router.events.on("routeChangeError", onRouteChange);
router.events.on('routeChangeComplete', onRouteChange);
router.events.on('routeChangeError', onRouteChange);

return () => {
router.events.off("routeChangeComplete", onRouteChange);
router.events.off("routeChangeError", onRouteChange);
router.events.off('routeChangeComplete', onRouteChange);
router.events.off('routeChangeError', onRouteChange);
};
}, [router, isOpen]);

Expand All @@ -61,54 +61,61 @@ export const NavMobile: React.FC<Props> = ({
className="fixed inset-0 z-50 flex items-start overflow-y-auto bg-background-dark/50 pr-10 backdrop-blur lg:hidden"
aria-label="Navigation"
>
<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">
<div className="flex items-center mb-6">
<button
type="button"
onClick={() => setIsOpen(false)}
aria-label="Close navigation"
>
<CloseIcon className="h-6 w-6 stroke-slate-500" />
</button>
<Link
href="/"
className="ml-6"
aria-label="Home page"
legacyBehavior
>
{/* <Logomark className="h-9 w-9" /> */}
<div className="font-extrabold text-primary dark:text-primary-dark text-2xl ml-6">
{author}
</div>
</Link>
</div>
{Search && (
<Search>
{({ query }: any) => <SearchField mobile onOpen={query.toggle} />}
</Search>
)}
{links && (
<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">
{links.map((link) => (
<Menu as="div" key={link.name} className="relative">
<Menu.Button>
<li key={link.href}>
<Link
href={link.href}
className={`
<Dialog.Panel className="relative min-h-full w-full max-w-xs bg-background dark:bg-background-dark pb-12">
<div className="px-4 sm:px-6 pt-5">
<div className="flex items-center mb-6">
<button
type="button"
onClick={() => setIsOpen(false)}
aria-label="Close navigation"
>
<CloseIcon className="h-6 w-6 stroke-slate-500" />
</button>
<Link
href="/"
className="ml-6"
aria-label="Home page"
legacyBehavior
>
{/* <Logomark className="h-9 w-9" /> */}
<div className="font-extrabold text-primary dark:text-primary-dark text-2xl ml-6">
{author}
</div>
</Link>
</div>
{Search && (
<Search>
{({ query }: any) => (
<SearchField mobile onOpen={query.toggle} />
)}
</Search>
)}
{links && (
<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">
{links.map((link) => (
<Menu as="div" key={link.name} className="relative">
<Menu.Button>
<li key={link.href}>
<Link
href={link.href}
className={`
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`}
>
{link.name}
</Link>
</li>
</Menu.Button>
</Menu>
))}
</ul>
)}
{/* <div className="pt-6 border border-t-2">
{children}
</div> */}
>
{link.name}
</Link>
</li>
</Menu.Button>
</Menu>
))}
</ul>
)}
</div>
{children ? (
<>
<hr className="my-6" />
<div className="pl-8 pr-4 sm:px-6">{children}</div>
</>
) : null}
</Dialog.Panel>
</Dialog>
</>
Expand Down
Loading

0 comments on commit 3334166

Please sign in to comment.