diff --git a/frontend/src/app/browse/[...slug]/page.tsx b/frontend/src/app/browse/[...slug]/page.tsx index 70f7e19..c95f5ee 100644 --- a/frontend/src/app/browse/[...slug]/page.tsx +++ b/frontend/src/app/browse/[...slug]/page.tsx @@ -5,10 +5,13 @@ import { getModuleDeclarations, listModules } from "@/lib/api"; import DeclarationItem from "@/components/DeclarationItem"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; -import type { ModuleInfo } from "@/types"; +import BrowseSidebar from "@/components/BrowseSidebar"; +import MobileKindFilter from "@/components/MobileKindFilter"; +import type { ModuleInfo, DeclarationKind } from "@/types"; interface Props { params: Promise<{ slug: string[] }>; + searchParams: Promise<{ kinds?: string }>; } function getDirectChildren( @@ -32,96 +35,138 @@ function getDirectChildren( .sort((a, b) => a.name.localeCompare(b.name)); } -export default async function ModulePage({ params }: Props) { +export default async function ModulePage({ params, searchParams }: Props) { const { slug } = await params; + const { kinds: kindsParam } = await searchParams; const moduleName = slug; + const selectedKinds = kindsParam + ? (kindsParam.split(",").filter(Boolean) as DeclarationKind[]) + : []; + const kindsQuery = kindsParam ? `?kinds=${kindsParam}` : ""; + const [declarations, allModules] = await Promise.all([ getModuleDeclarations(moduleName), listModules(), ]); const subModules = getDirectChildren(allModules, moduleName); + const moduleDocstring = allModules.find( + (m) => m.name.length === moduleName.length && m.name.every((p, i) => p === moduleName[i]) + )?.docstring ?? null; + + const filteredDeclarations = + selectedKinds.length > 0 + ? declarations.filter((d) => selectedKinds.includes(d.kind)) + : declarations; return (
-
- - -
-

- {moduleName.join(".")} -

-

- {declarations.length} declaration{declarations.length !== 1 ? "s" : ""} - {subModules.length > 0 && - ` · ${subModules.length} submodule${subModules.length !== 1 ? "s" : ""}`} -

-
+
+
+ - {subModules.length > 0 && ( -
-

- Submodules -

-
- {subModules.map((sub, i) => ( - - - {sub.name} - - - {sub.count} - - +
+ + + + +
+

+ {moduleName.join(".")} +

+ {moduleDocstring && ( +

+ {moduleDocstring} +

+ )} +

+ {filteredDeclarations.length} declaration + {filteredDeclarations.length !== 1 ? "s" : ""} + {selectedKinds.length > 0 && + ` (filtered from ${declarations.length})`} + {subModules.length > 0 && + ` · ${subModules.length} submodule${subModules.length !== 1 ? "s" : ""}`} +

-
- )} - {declarations.length > 0 && ( -
{subModules.length > 0 && ( -

- Declarations -

+
+

+ Submodules +

+
+ {subModules.map((sub, i) => ( + + + {sub.name} + + + {sub.count} + + + ))} +
+
+ )} + + {filteredDeclarations.length > 0 && ( +
+ {subModules.length > 0 && ( +

+ Declarations +

+ )} + {filteredDeclarations.map((decl, i) => ( + + ))} +
)} - {declarations.map((decl, i) => ( - - ))} -
- )} - {subModules.length === 0 && declarations.length === 0 && ( -

- No declarations found in this module. -

- )} + {subModules.length === 0 && filteredDeclarations.length === 0 && ( +

+ {selectedKinds.length > 0 + ? "No declarations match the current filter." + : "No declarations found in this module."} +

+ )} +
+