[docs] Separate some pages out of the Docs section (#1626)
This PR changes the structure of the docs site's sidebar. ![image](https://github.com/tldraw/tldraw/assets/15892272/ffe1e152-c921-43f0-9ba2-d084bda5e1e3) I think this signposts more clearly what the different pages are for. And it also paves the way for some work I want to do on expanding+refining the Editor docs. This PR also simplifies URL for all sidebar links. It's a bit scrappy, but I think it feels simple enough to work with, and easy-enough to change in the future. > But hey! I've been doing this a couple times recently. Maybe we should refactor? Or maybe we should keep going with what we've got and focus on getting these docs *done*. ### Change Type - [x] `documentation` — Changes to the documentation only[^2] [^1]: publishes a `patch` release, for devDependencies use `internal` [^2]: will not publish a new version ### Test Plan 1. Check that all the sidebar links go to where you expect. 2. Check that old URLs redirect to the right pages, eg: `/docs/usage` should go to the usage page. ### Release Notes - Documentation: Restructured the sidebar for clarity.
This commit is contained in:
parent
d2c51ae3ba
commit
c5fe399842
9 changed files with 119 additions and 36 deletions
|
@ -15,8 +15,12 @@ export function Breadcrumb({
|
|||
<Link href={`/`}>tldraw</Link>
|
||||
{section && (
|
||||
<>
|
||||
{` / `}
|
||||
<Link href={`/${section.id}`}>{section.title}</Link>
|
||||
{section.title && (
|
||||
<>
|
||||
{` / `}
|
||||
<Link href={`/${section.id}`}>{section.title}</Link>
|
||||
</>
|
||||
)}
|
||||
{category && (
|
||||
<>
|
||||
{category.id === 'ucg' ? null : (
|
||||
|
|
|
@ -106,11 +106,13 @@ function SidebarLink(props: SidebarContentLink) {
|
|||
function SidebarSection({ title, url, children }: SidebarContentSectionLink) {
|
||||
return (
|
||||
<li className="sidebar__section">
|
||||
<Link href={url}>
|
||||
<div className="sidebar__link sidebar__section__title" data-active={false}>
|
||||
{title}
|
||||
</div>
|
||||
</Link>
|
||||
{title && (
|
||||
<Link href={url}>
|
||||
<div className="sidebar__link sidebar__section__title" data-active={false}>
|
||||
{title}
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
<ul className="sidebar__list sidebar__section__list">
|
||||
{children.map((link) => (
|
||||
<SidebarLink key={link.url} {...link} />
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
[
|
||||
{
|
||||
"id": "getting-started",
|
||||
"title": "",
|
||||
"description": "",
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"id": "docs",
|
||||
"title": "Docs",
|
||||
"title": "Documentation",
|
||||
"description": "Developer documentation for tldraw.",
|
||||
"categories": []
|
||||
},
|
||||
|
|
|
@ -8,10 +8,35 @@ const nextConfig = {
|
|||
async redirects() {
|
||||
return [
|
||||
{
|
||||
// For reverse compatibility with old links
|
||||
source: '/:sectionId/ucg/:articleId',
|
||||
destination: '/:sectionId/:articleId',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
// For reverse compatibility with old links
|
||||
source: '/docs/introduction',
|
||||
destination: '/introduction',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
// For reverse compatibility with old links
|
||||
source: '/docs/installation',
|
||||
destination: '/installation',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
// For reverse compatibility with old links
|
||||
source: '/docs/usage',
|
||||
destination: '/usage',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
// To reflect that these are at the top level of the sidebar
|
||||
source: '/getting-started/:childId',
|
||||
destination: '/:childId',
|
||||
permanent: true,
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
|
|
|
@ -3,22 +3,39 @@ import { Mdx } from '@/components/Mdx'
|
|||
import { MetaHead } from '@/components/MetaHead'
|
||||
import { Sidebar } from '@/components/Sidebar'
|
||||
import { Article, Category, Section, SidebarContentList } from '@/types/content-types'
|
||||
import { getArticleSource, getArticles, getSection, getSections } from '@/utils/content'
|
||||
import {
|
||||
getArticle,
|
||||
getArticleSource,
|
||||
getArticles,
|
||||
getCategory,
|
||||
getLinks,
|
||||
getSection,
|
||||
getSections,
|
||||
} from '@/utils/content'
|
||||
import { getSidebarContentList } from '@/utils/getSidebarContentList'
|
||||
import { GetStaticPaths, GetStaticProps } from 'next'
|
||||
import { MDXRemoteSerializeResult } from 'next-mdx-remote'
|
||||
import { useTheme } from 'next-themes'
|
||||
import Link from 'next/link'
|
||||
import ArticlePage, { ArticleProps } from './[childId]/[articleId]'
|
||||
|
||||
type Props = {
|
||||
type SectionProps = {
|
||||
type: 'section'
|
||||
sidebar: SidebarContentList
|
||||
section: Section
|
||||
categories: { category: Category; articles: Article[] }[]
|
||||
mdxSource: MDXRemoteSerializeResult | null
|
||||
}
|
||||
|
||||
export default function SectionListPage({ sidebar, section, categories, mdxSource }: Props) {
|
||||
type Props = SectionProps | ArticleProps
|
||||
|
||||
export default function SectionListPage(props: Props) {
|
||||
const theme = useTheme()
|
||||
if (props.type === 'article') {
|
||||
return <ArticlePage {...props} />
|
||||
}
|
||||
|
||||
const { sidebar, section, categories, mdxSource } = props
|
||||
const ucg = categories.find((category) => category.category.id === 'ucg')!
|
||||
return (
|
||||
<>
|
||||
|
@ -62,20 +79,58 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
|||
const paths: { params: { sectionId: string } }[] = []
|
||||
|
||||
for (const section of sections) {
|
||||
paths.push({ params: { sectionId: section.id } })
|
||||
if (section.id !== 'getting-started') {
|
||||
paths.push({ params: { sectionId: section.id } })
|
||||
continue
|
||||
}
|
||||
|
||||
// Add paths for getting-started articles (not the section itself)
|
||||
// ... because we keep those at the top level of the sidebar
|
||||
for (const category of section.categories) {
|
||||
if (category.id !== 'ucg') continue
|
||||
for (const articleId of category.articleIds) {
|
||||
paths.push({ params: { sectionId: articleId } })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { paths, fallback: false }
|
||||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps<Props> = async (ctx) => {
|
||||
const sectionId = ctx.params?.sectionId?.toString()
|
||||
if (!sectionId) throw Error()
|
||||
const id = ctx.params?.sectionId?.toString()
|
||||
if (!id) throw Error()
|
||||
|
||||
const sidebar = await getSidebarContentList({
|
||||
sectionId,
|
||||
})
|
||||
// If the path goes to an article in the getting-started section
|
||||
// ... show the article page instead
|
||||
// ... because we keep those ones at the top level
|
||||
const sections = await getSections()
|
||||
if (!sections.some((section) => section.id === id)) {
|
||||
const sectionId = 'getting-started'
|
||||
const categoryId = 'ucg'
|
||||
const articleId = id
|
||||
const sidebar = await getSidebarContentList({ sectionId, categoryId, articleId })
|
||||
const section = await getSection(sectionId)
|
||||
const category = await getCategory(sectionId, categoryId)
|
||||
const article = await getArticle(articleId)
|
||||
const links = await getLinks(articleId)
|
||||
const mdxSource = await getArticleSource(articleId)
|
||||
return {
|
||||
props: {
|
||||
type: 'article',
|
||||
sidebar,
|
||||
section,
|
||||
category,
|
||||
article,
|
||||
links,
|
||||
mdxSource,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, show the section page
|
||||
const sectionId = id
|
||||
const sidebar = await getSidebarContentList({ sectionId })
|
||||
const articles = await getArticles()
|
||||
const section = await getSection(sectionId)
|
||||
const categories = [] as { category: Category; articles: Article[] }[]
|
||||
|
@ -87,5 +142,5 @@ export const getStaticProps: GetStaticProps<Props> = async (ctx) => {
|
|||
const article = articles[sectionId + '_index'] ?? null
|
||||
const mdxSource = article ? await getArticleSource(sectionId + '_index') : null
|
||||
|
||||
return { props: { sidebar, section, categories, mdxSource } }
|
||||
return { props: { type: 'section', sidebar, section, categories, mdxSource } }
|
||||
}
|
||||
|
|
|
@ -19,23 +19,14 @@ export async function getSidebarContentList({
|
|||
|
||||
if (section.id === 'gen') {
|
||||
links.push({ type: 'article', title: 'API Reference', url: '/gen' })
|
||||
|
||||
// for (const category of section.categories) {
|
||||
// if (category.id === 'ucg') {
|
||||
// continue
|
||||
// } else {
|
||||
// children.push({
|
||||
// type: 'article',
|
||||
// title: category.title,
|
||||
// url: `/${section.id}/${category.id}`,
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// links.push({ type: 'section', title: 'API Reference', url: '/gen', children })
|
||||
continue
|
||||
}
|
||||
|
||||
// If the article is in the getting-started section
|
||||
// ... we place it at the top level of the sidebar
|
||||
// ... so let's simplify its URL to reflect that
|
||||
const sectionUrl = section.id === 'getting-started' ? '' : `/${section.id}`
|
||||
|
||||
for (const category of section.categories) {
|
||||
if (category.id === 'ucg') {
|
||||
continue
|
||||
|
@ -43,13 +34,13 @@ export async function getSidebarContentList({
|
|||
children.push({
|
||||
type: 'category',
|
||||
title: category.title,
|
||||
url: `/${section.id}/${category.id}`,
|
||||
url: `${sectionUrl}/${category.id}`,
|
||||
children: category.articleIds.map((articleId) => {
|
||||
const article = articles[articleId]
|
||||
return {
|
||||
type: 'article' as const,
|
||||
title: article.title,
|
||||
url: `/${section.id}/${category.id}/${articleId}`,
|
||||
url: `${sectionUrl}/${category.id}/${articleId}`,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
@ -64,14 +55,14 @@ export async function getSidebarContentList({
|
|||
return {
|
||||
type: 'article' as const,
|
||||
title: article.title,
|
||||
url: `/${section.id}/${category.id}/${articleId}`,
|
||||
url: `${sectionUrl}/${articleId}`,
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
links.push({ type: 'section', title: section.title, url: `/${section.id}`, children })
|
||||
links.push({ type: 'section', title: section.title, url: sectionUrl, children })
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
Loading…
Reference in a new issue