Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions apps/site/components/withLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import AboutLayout from '#site/layouts/About';
import ArticlePageLayout from '#site/layouts/ArticlePage';
import BlogLayout from '#site/layouts/Blog';
import DefaultLayout from '#site/layouts/Default';
import DefaultLayout, {
AboutPageLayout,
LearnPageLayout,
} from '#site/layouts/Default';
import DownloadLayout from '#site/layouts/Download';
import DownloadArchiveLayout from '#site/layouts/DownloadArchive';
import GlowingBackdropLayout from '#site/layouts/GlowingBackdrop';
import LearnLayout from '#site/layouts/Learn';
import PostLayout from '#site/layouts/Post';

import type { Layouts } from '#site/types';
import type { FC, PropsWithChildren } from 'react';

const layouts = {
about: AboutLayout,
about: AboutPageLayout,
home: GlowingBackdropLayout,
learn: LearnLayout,
learn: LearnPageLayout,
page: DefaultLayout,
'blog-post': PostLayout,
'blog-category': BlogLayout,
download: DownloadLayout,
'download-archive': DownloadArchiveLayout,
article: ArticlePageLayout,
article: DefaultLayout,
} satisfies Record<Layouts, FC>;

type WithLayoutProps<L = Layouts> = PropsWithChildren<{ layout: L }>;
Expand Down
81 changes: 0 additions & 81 deletions apps/site/components/withMetaBar.tsx

This file was deleted.

98 changes: 83 additions & 15 deletions apps/site/components/withSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
'use client';

import Sidebar from '@node-core/ui-components/Containers/Sidebar';
import { useTranslations } from 'next-intl';
import GitHubIcon from '@node-core/ui-components/Icons/Social/GitHub';
import { defaultLocale } from '@node-core/website-i18n';
import { useFormatter, useLocale, useTranslations } from 'next-intl';
import { useRef } from 'react';

import Link from '#site/components/Link';
import { useClientContext, useScrollToElement } from '#site/hooks/client';
import WithAvatarGroup from '#site/components/withAvatarGroup';
import {
useClientContext,
useScrollToElement,
useMediaQuery,
} from '#site/hooks/client';
import { useSiteNavigation } from '#site/hooks/generic';
import { useRouter, usePathname } from '#site/navigation.mjs';
import { DEFAULT_DATE_FORMAT } from '#site/next.calendar.constants.mjs';
import { TRANSLATION_URL } from '#site/next.constants.mjs';
import { getGitHubBlobUrl } from '#site/util/github';

import type { NavigationKeys } from '#site/types';
import type { RichTranslationValues } from 'next-intl';
Expand All @@ -21,24 +31,29 @@ type WithSidebarProps = {
const WithSidebar: FC<WithSidebarProps> = ({ navKeys, context, ...props }) => {
const { getSideNavigation } = useSiteNavigation();
const pathname = usePathname()!;
const locale = useLocale();
const t = useTranslations();
const formatter = useFormatter();
const { push } = useRouter();
const { frontmatter } = useClientContext();
const { frontmatter, readingTime, filename } = useClientContext();
const sidebarRef = useRef<HTMLElement>(null);
const sideNavigation = getSideNavigation(navKeys, context);

// Preserve sidebar scroll position across navigations
useScrollToElement('sidebar', sidebarRef);

const mappedSidebarItems =
// If there's only a single navigation key, use its sub-items
// as our navigation.
(navKeys.length === 1 ? sideNavigation[0][1].items : sideNavigation).map(
([, { label, items }]) => ({
groupName: label,
items: items.map(([, item]) => item),
})
);
const sideNavigation = getSideNavigation(navKeys, context);
const mappedSidebarItems = (
navKeys.length === 1 ? sideNavigation[0][1].items : sideNavigation
).map(([, { label, items }]) => ({
groupName: label,
items: items.map(([, item]) => item),
}));

const usernames =
frontmatter.authors?.split(',').map(author => author.trim()) ?? [];
const isMobileResolution = useMediaQuery('(max-width: 670px)');
const isTabletResolution = useMediaQuery(
'(min-width: 670px) and (max-width: 1280px)'
);

return (
<Sidebar
Expand All @@ -50,7 +65,60 @@ const WithSidebar: FC<WithSidebarProps> = ({ navKeys, context, ...props }) => {
onSelect={push}
as={Link}
{...props}
/>
>
<dl>
{frontmatter.date && (
<>
<dt>{t('components.common.sidebar.lastUpdated')}</dt>
<dd>
{formatter.dateTime(
new Date(frontmatter.date),
DEFAULT_DATE_FORMAT
)}
</dd>
</>
)}

<dt>{t('components.common.sidebar.readingTime')}</dt>
<dd>
{formatter.number(readingTime.minutes, {
style: 'unit',
unit: 'minute',
maximumFractionDigits: 0,
})}
</dd>

{usernames.length > 0 && (
<>
<dt>
{t(
`components.common.sidebar.${usernames.length > 1 ? 'authors' : 'author'}`
)}
</dt>
<dd>
<WithAvatarGroup
usernames={usernames}
limit={isMobileResolution ? 7 : isTabletResolution ? 5 : 9}
/>
</dd>
</>
)}

<dt>{t('components.common.sidebar.contribute')}</dt>
<dd>
<GitHubIcon className="fill-neutral-700 dark:fill-neutral-100" />
<Link
href={
locale === defaultLocale.code
? getGitHubBlobUrl(filename)
: TRANSLATION_URL
}
>
{t('components.common.sidebar.contributeText')}
</Link>
</dd>
</dl>
</Sidebar>
);
};

Expand Down
20 changes: 20 additions & 0 deletions apps/site/components/withTOC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import TableOfContents from '@node-core/ui-components/Common/TableOfContents';
import { useTranslations } from 'next-intl';

import type { FC } from 'react';

import { useClientContext } from '../hooks/server';

const WithTOC: FC = () => {
const { headings } = useClientContext();
const t = useTranslations();

return (
<TableOfContents
headings={headings}
summaryTitle={t('components.common.onThisPage')}
/>
);
};

export default WithTOC;
33 changes: 0 additions & 33 deletions apps/site/layouts/About.tsx

This file was deleted.

30 changes: 0 additions & 30 deletions apps/site/layouts/ArticlePage.tsx

This file was deleted.

36 changes: 34 additions & 2 deletions apps/site/layouts/Default.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,59 @@
import Article from '@node-core/ui-components/Containers/Article';

import WithBreadcrumbs from '#site/components/withBreadcrumbs';
import WithFooter from '#site/components/withFooter';
import WithNavBar from '#site/components/withNavBar';
import WithSidebar from '#site/components/withSidebar';
import WithSidebarCrossLinks from '#site/components/withSidebarCrossLinks';
import WithTOC from '#site/components/withTOC';

import type { NavigationKeys } from '../types';
import type { FC, PropsWithChildren } from 'react';

const DefaultLayout: FC<PropsWithChildren> = ({ children }) => (
type DefaultLayoutProps = {
navKeys?: Array<NavigationKeys>;
showBreadcrumbs?: boolean;
};

const DefaultLayout: FC<PropsWithChildren<DefaultLayoutProps>> = ({
children,
navKeys = [],
showBreadcrumbs = false,
}) => (
<>
<WithNavBar />

<Article>
<WithSidebar navKeys={[]} />
<WithSidebar navKeys={navKeys} />

<div>
<WithTOC />

<main id="main" tabIndex={-1}>
{children}
</main>
</div>

{showBreadcrumbs && <WithBreadcrumbs navKeys={navKeys} />}
</Article>

<WithFooter />
</>
);

export default DefaultLayout;

export const AboutPageLayout: FC<PropsWithChildren> = props => (
<DefaultLayout
navKeys={['about', 'getInvolved']}
showBreadcrumbs={true}
{...props}
/>
);

export const LearnPageLayout: FC<PropsWithChildren> = ({ children }) => (
<DefaultLayout navKeys={['learn']} showBreadcrumbs={true}>
{children}
<WithSidebarCrossLinks navKey="learn" />
</DefaultLayout>
);
Loading
Loading