Wrap nav in suspense

This commit is contained in:
Sam Becker 2024-01-06 14:14:03 -06:00
parent b77b4a3f61
commit 3e45616870
2 changed files with 88 additions and 72 deletions

View File

@ -1,75 +1,12 @@
'use client';
import { clsx } from 'clsx/lite';
import { usePathname } from 'next/navigation';
import Link from 'next/link';
import SiteGrid from '../components/SiteGrid';
import { SITE_DOMAIN_OR_TITLE } from '@/site/config';
import ViewSwitcher, { SwitcherSelection } from '@/site/ViewSwitcher';
import {
PATH_ROOT,
isPathAdmin,
isPathGrid,
isPathProtected,
isPathSets,
isPathSignIn,
} from '@/site/paths';
import AnimateItems from '../components/AnimateItems';
export default function Nav() {
const pathname = usePathname();
const showNav = !isPathSignIn(pathname);
const shouldAnimate = !isPathAdmin(pathname);
const renderLink = (
text: string,
linkOrAction: string | (() => void),
) =>
typeof linkOrAction === 'string'
? <Link href={linkOrAction}>{text}</Link>
: <button onClick={linkOrAction}>{text}</button>;
const switcherSelectionForPath = (): SwitcherSelection | undefined => {
if (pathname === PATH_ROOT) {
return 'full-frame';
} else if (isPathGrid(pathname)) {
return 'grid';
} else if (isPathSets(pathname)) {
return 'sets';
} else if (isPathProtected(pathname)) {
return 'admin';
}
};
import { authCached } from '@/cache';
import NavClient from './NavClient';
import { Suspense } from 'react';
export default async function Nav() {
const session = await authCached();
return (
<SiteGrid
contentMain={
<AnimateItems
type={!shouldAnimate ? 'none' : 'bottom'}
distanceOffset={10}
items={showNav
? [<div
key="nav"
className={clsx(
'flex items-center',
'w-full min-h-[4rem]',
'leading-none',
)}>
<div className="flex flex-grow items-center gap-4">
<ViewSwitcher
currentSelection={switcherSelectionForPath()}
showAdmin={true}
/>
</div>
<div className="hidden xs:block">
{renderLink(SITE_DOMAIN_OR_TITLE, PATH_ROOT)}
</div>
</div>]
: []}
/>
}
/>
<Suspense fallback={<NavClient />}>
<NavClient showAdmin={Boolean(session?.user?.email)} />
</Suspense>
);
};
}

79
src/site/NavClient.tsx Normal file
View File

@ -0,0 +1,79 @@
'use client';
import { clsx } from 'clsx/lite';
import { usePathname } from 'next/navigation';
import Link from 'next/link';
import SiteGrid from '../components/SiteGrid';
import { SITE_DOMAIN_OR_TITLE } from '@/site/config';
import ViewSwitcher, { SwitcherSelection } from '@/site/ViewSwitcher';
import {
PATH_ROOT,
isPathAdmin,
isPathGrid,
isPathProtected,
isPathSets,
isPathSignIn,
} from '@/site/paths';
import AnimateItems from '../components/AnimateItems';
export default function NavClient({
showAdmin,
}: {
showAdmin?: boolean,
}) {
const pathname = usePathname();
const showNav = !isPathSignIn(pathname);
const shouldAnimate = !isPathAdmin(pathname);
const renderLink = (
text: string,
linkOrAction: string | (() => void),
) =>
typeof linkOrAction === 'string'
? <Link href={linkOrAction}>{text}</Link>
: <button onClick={linkOrAction}>{text}</button>;
const switcherSelectionForPath = (): SwitcherSelection | undefined => {
if (pathname === PATH_ROOT) {
return 'full-frame';
} else if (isPathGrid(pathname)) {
return 'grid';
} else if (isPathSets(pathname)) {
return 'sets';
} else if (isPathProtected(pathname)) {
return 'admin';
}
};
return (
<SiteGrid
contentMain={
<AnimateItems
type={!shouldAnimate ? 'none' : 'bottom'}
distanceOffset={10}
items={showNav
? [<div
key="nav"
className={clsx(
'flex items-center',
'w-full min-h-[4rem]',
'leading-none',
)}>
<div className="flex flex-grow items-center gap-4">
<ViewSwitcher
currentSelection={switcherSelectionForPath()}
showAdmin={showAdmin}
/>
</div>
<div className="hidden xs:block">
{renderLink(SITE_DOMAIN_OR_TITLE, PATH_ROOT)}
</div>
</div>]
: []}
/>
}
/>
);
};