Skip to content

Commit bc7eb27

Browse files
authored
refactor: remove dead layouts, extract shared utilities, and deduplicate docs routes (#1248)
* refactor: remove dead ApiLayout, extract shared loader utilities - Delete ApiLayout component (unused in production routes) - Inline makeBreadcrumbs into ApiRoute.res (its only consumer) - Remove test file that only tested the dead component - Clean up DocsLayout: remove unused makeBreadcrumbs, NavItem/Category aliases, and StaticContent module type - Extract FrontmatterUtils.getField to replace ~150 lines of duplicated frontmatter switch blocks across 6 route files - Extract TocUtils.buildEntries to replace duplicated TOC construction logic across 4 route files * refactor: introduce DocsLayoutRoute for shared NavbarSecondary Add a React Router layout route that renders <NavbarSecondary /> and <Outlet />, eliminating the duplicated <NavbarSecondary /> from 7 child route modules. - Create app/layouts/DocsLayoutRoute.res as a layout route - Nest all docs, API, and syntax-lookup routes under the layout - Remove <NavbarSecondary /> from ApiOverviewRoute, ApiRoute, DocsGuidelinesRoute, DocsManualRoute, DocsReactRoute, SyntaxLookupRoute, and SyntaxLookupDetailRoute - DocsOverview remains a flat route (it uses MainLayout, not the docs sidebar pattern) * refactor: inline ApiOverviewLayout into its route - Move categories data directly into ApiOverviewRoute.res - Replace <ApiOverviewLayout.Docs> with <DocsLayout categories theme=#Js> - Update tests to use DocsLayout and MemoryRouter - Delete src/layouts/ApiOverviewLayout.res and .resi * refactor: rename LandingPageLayout to LandingPage Move from src/layouts/ to src/components/ since it is a self-contained page component, not a layout wrapper. It does not accept children and does not provide structural wrapping like the other layouts do. * refactor: consolidate dual sidebar into DocsLayout DocsLayout now owns both the desktop sidebar (via SidebarLayout.Sidebar) and the mobile sidebar (via NavbarTertiary dialog). Routes pass data instead of constructing sidebar JSX inline. - Add ~breadcrumbs and ~editHref props to DocsLayout - DocsLayout renders NavbarTertiary internally with mobile sidebar - Simplify DocsManualRoute, DocsReactRoute, ApiOverviewRoute, and DocsGuidelinesRoute by removing ~30 lines of duplicated sidebar construction and NavbarTertiary rendering from each - ApiRoute is unchanged (uses a different sidebar structure) - CommunityRoute is unchanged (already handles both sidebars internally) * fix: update tests for DocsLayout NavbarTertiary integration DocsLayout now renders NavbarTertiary internally, which creates a mobile sidebar dialog. This caused two test issues: - Duplicate element matches: sidebar text appeared in both the desktop sidebar and the mobile dialog. Fixed by scoping queries to the sidebar-content testId. - Screenshot dimension mismatches: NavbarTertiary adds height to the rendered layout. Regenerated all affected reference screenshots. Also fixed BrowserRouter -> MemoryRouter in DocsLayout tests per project conventions. * fix: extract DocsSidebar component, keep NavbarTertiary in routes The previous approach of rendering NavbarTertiary inside DocsLayout placed it in the wrong DOM position (inside the layout content area instead of above it), causing visual bugs on mobile and desktop. Fix by reverting DocsLayout to a simple SidebarLayout wrapper and extracting the duplicated mobile sidebar JSX into a shared DocsSidebar component. Routes keep rendering NavbarTertiary at the correct position (above DocsLayout) but use DocsSidebar to avoid the 25-line copy-paste. - Create src/components/DocsSidebar.res with shared sidebar content - Revert DocsLayout to pre-NavbarTertiary state (remove breadcrumbs, editHref props and NavbarTertiary rendering) - Update DocsManualRoute, DocsReactRoute, ApiOverviewRoute, and DocsGuidelinesRoute to use DocsSidebar with NavbarTertiary - Scope ApiOverviewLayout test sidebar queries to sidebar-content testId to avoid matching pagination links - Regenerate reference screenshots
1 parent 77d3bb1 commit bc7eb27

33 files changed

Lines changed: 215 additions & 589 deletions

__tests__/ApiLayout_.test.res

Lines changed: 0 additions & 87 deletions
This file was deleted.

__tests__/ApiOverviewLayout_.test.res

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,54 @@
11
open ReactRouter
22
open Vitest
33

4+
let categories: array<SidebarLayout.Sidebar.Category.t> = [
5+
{
6+
name: "Overview",
7+
items: [
8+
{name: "Introduction", href: "/docs/manual/api"},
9+
{name: "Stdlib", href: "/docs/manual/api/stdlib"},
10+
],
11+
},
12+
{
13+
name: "Additional Libraries",
14+
items: [
15+
{name: "Belt", href: "/docs/manual/api/belt"},
16+
{name: "Dom", href: "/docs/manual/api/dom"},
17+
],
18+
},
19+
]
20+
421
test("desktop API overview shows sidebar categories and content", async () => {
522
await viewport(1440, 900)
623

724
let screen = await render(
8-
<BrowserRouter>
25+
<MemoryRouter initialEntries=["/docs/manual/api"]>
926
<div dataTestId="api-overview-wrapper">
10-
<ApiOverviewLayout.Docs>
27+
<DocsLayout categories theme=#Js>
1128
<div> {React.string("API documentation content.")} </div>
12-
</ApiOverviewLayout.Docs>
29+
</DocsLayout>
1330
</div>
14-
</BrowserRouter>,
31+
</MemoryRouter>,
1532
)
1633

17-
let overview = await screen->getByText("Overview")
34+
let sidebar = await screen->getByTestId("sidebar-content")
35+
36+
let overview = await sidebar->getByText("Overview")
1837
await element(overview)->toBeVisible
1938

20-
let introduction = await screen->getByText("Introduction")
39+
let introduction = await sidebar->getByText("Introduction")
2140
await element(introduction)->toBeVisible
2241

23-
let stdlib = await screen->getByText("Stdlib")
42+
let stdlib = await sidebar->getByText("Stdlib")
2443
await element(stdlib)->toBeVisible
2544

26-
let additionalLibraries = await screen->getByText("Additional Libraries")
45+
let additionalLibraries = await sidebar->getByText("Additional Libraries")
2746
await element(additionalLibraries)->toBeVisible
2847

29-
let belt = await screen->getByText("Belt")
48+
let belt = await sidebar->getByText("Belt")
3049
await element(belt)->toBeVisible
3150

32-
let dom = await screen->getByText("Dom")
51+
let dom = await sidebar->getByText("Dom")
3352
await element(dom)->toBeVisible
3453

3554
let mainContent = await screen->getByTestId("side-layout-children")
@@ -43,22 +62,24 @@ test("mobile API overview hides sidebar", async () => {
4362
await viewport(600, 1200)
4463

4564
let screen = await render(
46-
<BrowserRouter>
65+
<MemoryRouter initialEntries=["/docs/manual/api"]>
4766
<div dataTestId="api-overview-wrapper">
48-
<ApiOverviewLayout.Docs>
67+
<DocsLayout categories theme=#Js>
4968
<div> {React.string("API documentation content.")} </div>
50-
</ApiOverviewLayout.Docs>
69+
</DocsLayout>
5170
</div>
52-
</BrowserRouter>,
71+
</MemoryRouter>,
5372
)
5473

55-
let introduction = await screen->getByText("Introduction")
74+
let sidebar = await screen->getByTestId("sidebar-content")
75+
76+
let introduction = await sidebar->getByText("Introduction")
5677
await element(introduction)->notToBeVisible
5778

58-
let stdlib = await screen->getByText("Stdlib")
79+
let stdlib = await sidebar->getByText("Stdlib")
5980
await element(stdlib)->notToBeVisible
6081

61-
let belt = await screen->getByText("Belt")
82+
let belt = await sidebar->getByText("Belt")
6283
await element(belt)->notToBeVisible
6384

6485
let wrapper = await screen->getByTestId("api-overview-wrapper")
@@ -69,16 +90,16 @@ test("desktop API overview shows all category items", async () => {
6990
await viewport(1440, 900)
7091

7192
let screen = await render(
72-
<BrowserRouter>
93+
<MemoryRouter initialEntries=["/docs/manual/api"]>
7394
<div dataTestId="api-overview-wrapper">
74-
<ApiOverviewLayout.Docs>
95+
<DocsLayout categories theme=#Js>
7596
<div>
7697
<Markdown.H1> {React.string("API Reference")} </Markdown.H1>
7798
<Markdown.P> {React.string("Welcome to the ReScript API documentation.")} </Markdown.P>
7899
</div>
79-
</ApiOverviewLayout.Docs>
100+
</DocsLayout>
80101
</div>
81-
</BrowserRouter>,
102+
</MemoryRouter>,
82103
)
83104

84105
let apiTitle = await screen->getByText("API Reference")
@@ -95,16 +116,18 @@ test("tablet API overview", async () => {
95116
await viewport(900, 900)
96117

97118
let screen = await render(
98-
<BrowserRouter>
119+
<MemoryRouter initialEntries=["/docs/manual/api"]>
99120
<div dataTestId="api-overview-wrapper">
100-
<ApiOverviewLayout.Docs>
121+
<DocsLayout categories theme=#Js>
101122
<div> {React.string("API documentation content.")} </div>
102-
</ApiOverviewLayout.Docs>
123+
</DocsLayout>
103124
</div>
104-
</BrowserRouter>,
125+
</MemoryRouter>,
105126
)
106127

107-
let overview = await screen->getByText("Overview")
128+
let sidebar = await screen->getByTestId("sidebar-content")
129+
130+
let overview = await sidebar->getByText("Overview")
108131
await element(overview)->toBeVisible
109132

110133
let wrapper = await screen->getByTestId("api-overview-wrapper")

__tests__/DocsLayout_.test.res

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ test("desktop docs layout shows sidebar with categories", async () => {
3232
await viewport(1440, 900)
3333

3434
let screen = await render(
35-
<BrowserRouter>
35+
<MemoryRouter initialEntries=["/docs/manual/introduction"]>
3636
<div dataTestId="docs-layout-wrapper">
3737
<DocsLayout categories=mockCategories activeToc=mockToc>
3838
<div> {React.string("This is the documentation content.")} </div>
3939
</DocsLayout>
4040
</div>
41-
</BrowserRouter>,
41+
</MemoryRouter>,
4242
)
4343

4444
let overviewHeading = await screen->getByText("Overview")
@@ -61,13 +61,13 @@ test("desktop docs layout shows table of contents entries", async () => {
6161
await viewport(1440, 900)
6262

6363
let screen = await render(
64-
<BrowserRouter>
64+
<MemoryRouter initialEntries=["/docs/manual/introduction"]>
6565
<div dataTestId="docs-layout-wrapper">
6666
<DocsLayout categories=mockCategories activeToc=mockToc>
6767
<div> {React.string("This is the documentation content.")} </div>
6868
</DocsLayout>
6969
</div>
70-
</BrowserRouter>,
70+
</MemoryRouter>,
7171
)
7272

7373
// The TOC entries render inside the sidebar under the active nav item.
@@ -88,13 +88,13 @@ test("mobile docs layout hides sidebar by default", async () => {
8888
await viewport(600, 1200)
8989

9090
let screen = await render(
91-
<BrowserRouter>
91+
<MemoryRouter initialEntries=["/docs/manual/introduction"]>
9292
<div dataTestId="docs-layout-wrapper">
9393
<DocsLayout categories=mockCategories activeToc=mockToc>
9494
<div> {React.string("This is the documentation content.")} </div>
9595
</DocsLayout>
9696
</div>
97-
</BrowserRouter>,
97+
</MemoryRouter>,
9898
)
9999

100100
let introItem = await screen->getByText("Introduction")
809 Bytes
Loading
644 Bytes
Loading
936 Bytes
Loading
1.05 KB
Loading
4.69 KB
Loading
4.69 KB
Loading
1.11 KB
Loading

0 commit comments

Comments
 (0)