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 (
}
target="_blank"
- href={GITHUB_URL.concat(pathname).concat('.mdx')}
+ href={`${GITHUB_URL}${pathname}.mdx`}
>
Edit page
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}
+
+
+
+
+ >
+ )
+}