From 97b9d71caa191a20de8571e57f8a1c6e2338c3bb Mon Sep 17 00:00:00 2001 From: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com> Date: Mon, 3 Feb 2025 19:57:14 +0100 Subject: [PATCH] docs: add custom 404 page (#486) --- .../src/components/EditPage/EditPage.tsx | 5 +-- .../src/components/MdxWrapper/index.ts | 3 -- .../PageWithTOC.module.css} | 0 .../PageWithTOC.tsx} | 17 ++++------ .../src/components/PageWithTOC/index.ts | 3 ++ .../TableOfContents/TableOfContents.tsx | 34 +++++++++---------- apps/documentation/src/routes/404.tsx | 19 +++++++++++ apps/documentation/src/routes/__layout.tsx | 7 ++-- .../src/routes/documentation/__layout.tsx | 22 ++++++++++++ 9 files changed, 74 insertions(+), 36 deletions(-) delete mode 100644 apps/documentation/src/components/MdxWrapper/index.ts rename apps/documentation/src/components/{MdxWrapper/MdxWrapper.module.css => PageWithTOC/PageWithTOC.module.css} (100%) rename apps/documentation/src/components/{MdxWrapper/MdxWrapper.tsx => PageWithTOC/PageWithTOC.tsx} (59%) create mode 100644 apps/documentation/src/components/PageWithTOC/index.ts create mode 100644 apps/documentation/src/routes/404.tsx create mode 100644 apps/documentation/src/routes/documentation/__layout.tsx diff --git a/apps/documentation/src/components/EditPage/EditPage.tsx b/apps/documentation/src/components/EditPage/EditPage.tsx index e285f3b1..87491f76 100644 --- a/apps/documentation/src/components/EditPage/EditPage.tsx +++ b/apps/documentation/src/components/EditPage/EditPage.tsx @@ -8,15 +8,16 @@ const GITHUB_URL = export default function EditPage(): JSX.Element { const { pathname } = useRouter() + return ( diff --git a/apps/documentation/src/components/MdxWrapper/index.ts b/apps/documentation/src/components/MdxWrapper/index.ts deleted file mode 100644 index 76ac0e44..00000000 --- a/apps/documentation/src/components/MdxWrapper/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { MdxWrapper } from './MdxWrapper' - -export default MdxWrapper diff --git a/apps/documentation/src/components/MdxWrapper/MdxWrapper.module.css b/apps/documentation/src/components/PageWithTOC/PageWithTOC.module.css similarity index 100% rename from apps/documentation/src/components/MdxWrapper/MdxWrapper.module.css rename to apps/documentation/src/components/PageWithTOC/PageWithTOC.module.css diff --git a/apps/documentation/src/components/MdxWrapper/MdxWrapper.tsx b/apps/documentation/src/components/PageWithTOC/PageWithTOC.tsx similarity index 59% rename from apps/documentation/src/components/MdxWrapper/MdxWrapper.tsx rename to apps/documentation/src/components/PageWithTOC/PageWithTOC.tsx index 3578c58b..e3fdab87 100644 --- a/apps/documentation/src/components/MdxWrapper/MdxWrapper.tsx +++ b/apps/documentation/src/components/PageWithTOC/PageWithTOC.tsx @@ -3,16 +3,13 @@ import { Box, Container } from '@mantine/core' import TableOfContents from '@/components/TableOfContents' -import EditPage from '../EditPage' -import MdxProvider from '../MdxProvider' +import classes from './PageWithTOC.module.css' -import classes from './MdxWrapper.module.css' - -interface MdxWrapperProps { +interface PageWithTOCProps { children: ReactNode } -export function MdxWrapper({ children }: MdxWrapperProps): JSX.Element { +export function PageWithTOC({ children }: PageWithTOCProps): JSX.Element { return ( - {children} - - - - + {children} + + ) } diff --git a/apps/documentation/src/components/PageWithTOC/index.ts b/apps/documentation/src/components/PageWithTOC/index.ts new file mode 100644 index 00000000..ad713934 --- /dev/null +++ b/apps/documentation/src/components/PageWithTOC/index.ts @@ -0,0 +1,3 @@ +import { PageWithTOC } from './PageWithTOC' + +export default PageWithTOC diff --git a/apps/documentation/src/components/TableOfContents/TableOfContents.tsx b/apps/documentation/src/components/TableOfContents/TableOfContents.tsx index c7897714..5299166e 100644 --- a/apps/documentation/src/components/TableOfContents/TableOfContents.tsx +++ b/apps/documentation/src/components/TableOfContents/TableOfContents.tsx @@ -1,9 +1,11 @@ -import type { JSX, MouseEvent } from 'react' +import type { JSX, MouseEventHandler } from 'react' import { useRef, useState, useEffect } from 'react' import { useRouter } from 'tuono' import { Box, Text } from '@mantine/core' -import { getHeadings, type Heading } from './getHeadings' +import { getHeadings } from './getHeadings' +import type { Heading } from './getHeadings' + import classes from './TableOfContents.module.css' export function TableOfContents(): JSX.Element | null { @@ -65,24 +67,22 @@ export function TableOfContents(): JSX.Element | null { } }, [router.pathname]) - const handleHeadingClick = ( - event: MouseEvent, - id: string, + const handleHeadingClick: MouseEventHandler = ( + event, ): void => { event.preventDefault() - const element = document.getElementById(id) - if (element) { - history.pushState(null, '', `#${element.id} `) + const target = event.target as HTMLAnchorElement + const href = target.getAttribute('href') as string + const targetHeading = document.querySelector(href) - element.scrollIntoView({ - behavior: 'instant', - block: 'start', - }) - } + if (!targetHeading) return + + history.pushState(null, '', href) + targetHeading.scrollIntoView({ behavior: 'instant', block: 'start' }) } - // Avoid to show it in case of a TODO page - if (headings.length === 1) { + // Table of contents will not be displayed if the page has one or fewer headings. + if (headings.length <= 1) { return null } @@ -104,9 +104,7 @@ export function TableOfContents(): JSX.Element | null { className={classes.link} mod={{ active: activeHeadingIndex === index + 1 }} href={`#${heading.id}`} - onClick={(e) => { - handleHeadingClick(e, heading.id) - }} + onClick={handleHeadingClick} style={{ paddingLeft: `calc(${heading.order - 1} * var(--mantine-spacing-md))`, }} diff --git a/apps/documentation/src/routes/404.tsx b/apps/documentation/src/routes/404.tsx new file mode 100644 index 00000000..82e48377 --- /dev/null +++ b/apps/documentation/src/routes/404.tsx @@ -0,0 +1,19 @@ +import type { JSX } from 'react' +import { Title, Text } from '@mantine/core' +import { Link } from 'tuono' + +export default function NotFound(): JSX.Element { + return ( + <> + + 404 - Not found + + + + Sorry, we can’t find the page you’re looking for + + + Back to home + + ) +} diff --git a/apps/documentation/src/routes/__layout.tsx b/apps/documentation/src/routes/__layout.tsx index e0892f57..57141a17 100644 --- a/apps/documentation/src/routes/__layout.tsx +++ b/apps/documentation/src/routes/__layout.tsx @@ -11,9 +11,10 @@ import { } from '@mantine/core' import { useDisclosure } from '@mantine/hooks' -import MdxWrapper from '@/components/MdxWrapper' +import PageWithTOC from '@/components/PageWithTOC' import Navbar from '@/components/Navbar' import Sidebar from '@/components/Sidebar' +import MdxProvider from '@/components/MdxProvider' import '@mantine/core/styles.css' import '@mantine/code-highlight/styles.css' @@ -124,7 +125,9 @@ export default function RootRoute({ children }: RootRouteProps): JSX.Element { - {children} + + {children} + diff --git a/apps/documentation/src/routes/documentation/__layout.tsx b/apps/documentation/src/routes/documentation/__layout.tsx new file mode 100644 index 00000000..2b5bb3a0 --- /dev/null +++ b/apps/documentation/src/routes/documentation/__layout.tsx @@ -0,0 +1,22 @@ +import type { JSX, ReactNode } from 'react' +import { Divider } from '@mantine/core' + +import EditPage from '@/components/EditPage' + +interface DocumentationLayoutProps { + children: ReactNode +} + +export default function DocumentationLayout({ + children, +}: DocumentationLayoutProps): JSX.Element { + return ( + <> + {children} + + + + + + ) +}