mirror of
https://github.com/supabase/supabase.git
synced 2026-10-29 15:10:29 +08:00
Closes DOCS-1469 ## Problem Option 1 in the navigation proposal groups the docs into Start, Build, Develop and deploy, Run and manage, Self-Hosting, Reference, and Resources. The `docs-ia-mvp-v1` flag from #52049 switches to an Option 1 config. That config is still a copy of today's navigation. ## Solution - **Top nav:** reads Start, Build, Develop and deploy, Run and manage, Self-Hosting, Reference, and Resources. Menus still open sidebars by URL prefix, as they do today. - **Run and manage:** pages under `/guides/platform`, `/guides/security`, and `/guides/observability` share one sidebar with the outline's seven groups. - **Other sidebars:** follow the outline. REST, GraphQL and Realtime share one sidebar, and Cron and Queues share one sidebar. - **Seven new topics:** keep their outline labels and link to the section on their source page, for example `getting-started/api-keys#leaked-key`. - **No flash of today's nav:** flags load in the browser, so the nav stays invisible until the query param or the flags resolve, with a 1-second fallback. The links stay in the HTML for agents. - **Tests:** each page appears once across the sidebars, and every link goes to a page in today's navigation. With the flag off, `useNavItems` returns today's navigation. **Not changed:** no URLs move. Breadcrumbs still show today's trail, which DOCS-1470 covers. ## Manual testing 1. Open [Database Backups with the flag on](https://docs-git-docs-ia-nav-option-1-supabase.vercel.app/docs/guides/platform/backups?docs-ia-mvp-v1=option-1). The top nav reads Start, Build, Develop and deploy, Run and manage, Self-Hosting, Reference, and Resources. The sidebar shows the seven Run and manage groups. 2. Open [the same page with the flag off](https://docs-git-docs-ia-nav-option-1-supabase.vercel.app/docs/guides/platform/backups?docs-ia-mvp-v1=control). Today's navigation shows. 3. Open [Database with the flag on](https://docs-git-docs-ia-nav-option-1-supabase.vercel.app/docs/guides/database/overview?docs-ia-mvp-v1=option-1). The sidebar starts with Connect to your database. 4. In the sidebar, open Row Level Security, roles and Vault, and select Test RLS policies with pgTAP. The testing overview opens at Database unit testing with pgTAP.
96 lines
3.2 KiB
TypeScript
96 lines
3.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import type { GlobalMenuItems } from '../Navigation.types'
|
|
import * as currentNavItems from './NavigationMenu.constants'
|
|
import * as option1NavItems from '@/features/IaNav/option1.constants'
|
|
|
|
const MAX_ITEMS = 9
|
|
|
|
type Level = { path: string; size: number }
|
|
type NavNode = { name?: string; enabled?: boolean; items?: NavNode[] }
|
|
|
|
// count only what renders: disabled items and their subtrees are hidden
|
|
const isRendered = (item: { enabled?: boolean }) => item.enabled !== false
|
|
|
|
function sidebarLevels(path: string, allItems: NavNode[]): Level[] {
|
|
const items = allItems.filter((item) => isRendered(item))
|
|
|
|
return [
|
|
{ path, size: items.length },
|
|
...items.flatMap((item) =>
|
|
item.items?.length ? sidebarLevels(`${path} > ${item.name}`, item.items) : []
|
|
),
|
|
]
|
|
}
|
|
|
|
function topNavLevels(allSections: GlobalMenuItems): Level[] {
|
|
const menu = allSections.filter(([item]) => isRendered(item))
|
|
|
|
return [
|
|
{ path: 'Top nav', size: menu.length },
|
|
...menu.flatMap(([item]) =>
|
|
(item.menuItems ?? []).map((column, index) => ({
|
|
path: `Top nav > ${item.label} > column ${index + 1}`,
|
|
size: column.filter((columnItem) => isRendered(columnItem)).length,
|
|
}))
|
|
),
|
|
]
|
|
}
|
|
|
|
function oversizedLevels(navItems: Record<string, unknown>): string[] {
|
|
// A sidebar shared by several URL prefixes is exported under each name.
|
|
const sidebars = new Set(
|
|
Object.values(navItems).filter(
|
|
(value): value is { title: string; items: NavNode[] } =>
|
|
typeof value === 'object' &&
|
|
value !== null &&
|
|
'title' in value &&
|
|
Array.isArray((value as { items?: unknown }).items)
|
|
)
|
|
)
|
|
|
|
return [
|
|
...topNavLevels(navItems.GLOBAL_MENU_ITEMS as GlobalMenuItems),
|
|
...[...sidebars].flatMap((sidebar) => sidebarLevels(sidebar.title, sidebar.items)),
|
|
]
|
|
.filter((level) => level.size > MAX_ITEMS)
|
|
.map((level) => level.path)
|
|
}
|
|
|
|
// Levels allowed 10 or more items, such as a list of peers like quickstarts or providers.
|
|
const ALLOWLIST = [
|
|
'Auth',
|
|
'Auth > Flows (How-tos)',
|
|
'Auth > Flows (How-tos) > Social Sign-in (OAuth)',
|
|
'Database',
|
|
'Database > Extensions',
|
|
'Database > Foreign Data Wrappers > Sources',
|
|
'Database > Working with your database (intermediate)',
|
|
'Edge Functions',
|
|
'Edge Functions > Examples',
|
|
'Edge Functions > Third-Party Tools',
|
|
'Platform > Billing > Manage your usage',
|
|
'Platform > Platform Configuration',
|
|
'Self-Hosting',
|
|
'Self-Hosting > How-to Guides',
|
|
'Start with Supabase > Framework Quickstarts',
|
|
'Start with Supabase > Web app demos',
|
|
'Storage > File Buckets',
|
|
]
|
|
const OPTION_1_ALLOWLIST = [
|
|
'Auth > Social Sign-in (OAuth)',
|
|
'Database > Foreign Data Wrappers > Apps and APIs',
|
|
'Database > Foreign Data Wrappers > Databases and warehouses',
|
|
'Start > Framework Quickstarts > JavaScript and TypeScript',
|
|
'Start > Web app demos',
|
|
]
|
|
|
|
describe('navigation level size', () => {
|
|
it.each([
|
|
["today's navigation", currentNavItems, ALLOWLIST],
|
|
['Option 1', option1NavItems, OPTION_1_ALLOWLIST],
|
|
])('%s has no level with 10 or more items outside the allowlist', (_, navItems, allowlist) => {
|
|
expect(oversizedLevels(navItems).sort()).toEqual([...allowlist].sort())
|
|
})
|
|
})
|