diff --git a/app/components/DocsLayout.tsx b/app/components/DocsLayout.tsx index 9c955f91..23538313 100644 --- a/app/components/DocsLayout.tsx +++ b/app/components/DocsLayout.tsx @@ -48,10 +48,6 @@ const useMenuConfig = ({ framework: string repo: string }) => { - const frameworkMenuItems = - config.frameworkMenus.find((d) => d.framework === framework)?.menuItems ?? - [] - const localMenu: MenuItem = { label: 'Menu', children: [ @@ -81,19 +77,26 @@ const useMenuConfig = ({ return [ localMenu, // Merge the two menus together based on their group labels - ...config.menu.map((d) => { - const match = frameworkMenuItems.find((d2) => d2.label === d.label) + ...config.sections.map((section) => { + const frameworkDocs = section.frameworks?.find( + (f) => f.label === framework + ) + const frameworkItems = frameworkDocs?.children ?? [] + + const children = [ + ...section.children.map((d) => ({ ...d, badge: 'core' })), + ...frameworkItems.map((d) => ({ ...d, badge: framework })), + ] + + if (children.length === 0) { + return undefined + } + return { - label: d.label, - children: [ - ...d.children.map((d) => ({ ...d, badge: 'core' })), - ...(match?.children ?? []).map((d) => ({ ...d, badge: framework })), - ], + label: section.label, + children, } }), - ...frameworkMenuItems.filter( - (d) => !config.menu.find((dd) => dd.label === d.label) - ), ].filter(Boolean) } @@ -212,7 +215,7 @@ export function DocsLayout({ const detailsRef = React.useRef(null!) const flatMenu = React.useMemo( - () => menuConfig.flatMap((d) => d.children), + () => menuConfig.flatMap((d) => d?.children), [menuConfig] ) @@ -223,7 +226,7 @@ export function DocsLayout({ '' ) - const index = flatMenu.findIndex((d) => d.to === relativePathname) + const index = flatMenu.findIndex((d) => d?.to === relativePathname) const prevItem = flatMenu[index - 1] const nextItem = flatMenu[index + 1] @@ -232,10 +235,10 @@ export function DocsLayout({ const menuItems = menuConfig.map((group, i) => { return (
-
{group.label}
+
{group?.label}
- {group.children?.map((child, i) => { + {group?.children?.map((child, i) => { const linkClasses = `flex items-center justify-between group px-2 py-1 rounded-lg hover:bg-gray-500 hover:bg-opacity-10` return ( diff --git a/app/utils/config.ts b/app/utils/config.ts index ab1e5b16..b079a03e 100644 --- a/app/utils/config.ts +++ b/app/utils/config.ts @@ -1,11 +1,6 @@ import { z } from 'zod' import { fetchRepoFile } from './documents.server' -export type FrameworkMenu = { - framework: string - menuItems: MenuItem[] -} - export type MenuItem = { label: string | React.ReactNode children: { @@ -15,30 +10,38 @@ export type MenuItem = { }[] } -const menuItemSchema = z.object({ - label: z.string(), - children: z.array( - z.object({ - label: z.string(), - to: z.string(), - badge: z.string().optional(), - }) - ), -}) - -const frameworkMenuSchema = z.object({ - framework: z.string(), - menuItems: z.array(menuItemSchema), -}) - const configSchema = z.object({ docSearch: z.object({ appId: z.string(), apiKey: z.string(), indexName: z.string(), }), - menu: z.array(menuItemSchema), - frameworkMenus: z.array(frameworkMenuSchema), + sections: z.array( + z.object({ + label: z.string(), + children: z.array( + z.object({ + label: z.string(), + to: z.string(), + badge: z.string().optional(), + }) + ), + frameworks: z + .array( + z.object({ + label: z.string(), + children: z.array( + z.object({ + label: z.string(), + to: z.string(), + badge: z.string().optional(), + }) + ), + }) + ) + .optional(), + }) + ), users: z.array(z.string()).optional(), }) diff --git a/tanstack-docs-config.schema.json b/tanstack-docs-config.schema.json index cb791dd8..8fb1bef5 100644 --- a/tanstack-docs-config.schema.json +++ b/tanstack-docs-config.schema.json @@ -4,7 +4,7 @@ "title": "TanStack Docs Config", "description": "Config file for the documentation of a TanStack project.", "type": "object", - "required": ["docSearch", "menu", "frameworkMenus"], + "required": ["docSearch", "sections"], "additionalProperties": false, "properties": { "$schema": { @@ -26,8 +26,8 @@ } } }, - "menu": { - "description": "Doc pages that are NOT framework-specific.", + "sections": { + "description": "Section groups for the sidebar.", "type": "array", "items": { "type": "object", @@ -38,6 +38,7 @@ "type": "string" }, "children": { + "description": "Framework-agnostic docs go here.", "type": "array", "items": { "type": "object", @@ -55,36 +56,20 @@ } } } - } - } - } - }, - "frameworkMenus": { - "description": "Doc pages that are framework-specific.", - "type": "array", - "items": { - "type": "object", - "required": ["framework", "menuItems"], - "additionalProperties": false, - "properties": { - "framework": { - "type": "string" }, - "menuItems": { + "frameworks": { "type": "array", "items": { "type": "object", - "required": ["label", "children"], - "additionalProperties": false, "properties": { - "label": { - "type": "string" - }, + "label": { "type": "string" }, "children": { + "description": "Framework-specific docs go here.", "type": "array", "items": { "type": "object", "required": ["label", "to"], + "additionalProperties": false, "properties": { "label": { "type": "string" @@ -98,7 +83,9 @@ } } } - } + }, + "required": ["label", "children"], + "additionalProperties": false } } }