Skip to content

move api reference navigation to sidebar #2423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Dev Server",
"type": "shell",
"command": "deno task start",
"group": "serve",
"isBackground": true
},
{
"label": "Dev Server",
"type": "shell",
"command": "deno task start",
"isBackground": true,
"problemMatcher": [
"$deno"
],
"group": "serve"
}
]
}
5 changes: 4 additions & 1 deletion _components/Base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ export default function Base(
return (
<>
<div className="ddoc markdown-body">
<comp.Breadcrumbs parts={data.breadcrumbs_ctx.parts} />
<comp.Breadcrumbs
parts={data.breadcrumbs_ctx.parts}
hasSubNav={false}
/>
<main id="content" tabindex={-1}>
{children}
</main>
Expand Down
2 changes: 1 addition & 1 deletion _components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function getSectionData(data: Lume.Data, currentUrl: string) {
const childItems = categoryPanel.categories;

childItems.push({
name: `View all ${categoryPanel.total_symbols} symbols`,
name: `All ${categoryPanel.total_symbols} symbols`,
href: categoryPanel.all_symbols_href,
active: currentUrl.includes("all_symbols"),
});
Expand Down
267 changes: 250 additions & 17 deletions _components/SidebarNav.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,242 @@
// deno-lint-ignore-file no-explicit-any
export default function (data: Lume.Data) {
const sectionData = data.sectionData;
const currentUrl = data.currentUrl.replace(/\/$/, "");
const isReference = currentUrl.startsWith("/api/");
const isDenoAPI = currentUrl.startsWith("/api/deno/");

// Access global API categories data
const apiCategories = data.apiCategories;

if (isReference) {
// Note: Per-category symbol counts are not available in the generated API data structure
// The categories_panel only provides total symbol counts, not per-category breakdowns
// For API reference, we want to add section headings for the three API types

const apiSections = [
{
title: "Deno APIs",
key: "deno",
isCurrentSection: currentUrl.startsWith("/api/deno"),
items: currentUrl.startsWith("/api/deno") ? sectionData : undefined,
extraItems: [
{ href: "/api/deno", title: "Deno specific APIs" },
{
href: "/api/deno/all_symbols",
title: "All symbols",
},
],
},
{
title: "Web APIs",
key: "web",
isCurrentSection: currentUrl.startsWith("/api/web"),
items: currentUrl.startsWith("/api/web") ? sectionData : undefined,
extraItems: [
{ href: "/api/web", title: "Web Platform Support" },
{
href: "/api/web/all_symbols",
title: "All symbols",
},
],
},
{
title: "Node APIs",
key: "node",
isCurrentSection: currentUrl.startsWith("/api/node"),
items: currentUrl.startsWith("/api/node") ? sectionData : undefined,
extraItems: [
{ href: "/api/node", title: "Node support in deno" },
{
href: "/api/node/all_symbols",
title: "All symbols",
},
],
},
];

return (
<>
{sectionData.map((nav: any) => (
<nav>
{apiSections.map((section) => (
<nav key={section.key}>
<SidebarCategoryHeading
title={section.title}
/>
<SidebarList>
{nav.items?.map((item: any) => (
<li key={item.href}>
{(isDenoAPI && item.name === "Uncategorized")
? null
: (
<SidebarItem
href={item.href}
title={item.name}
isActive={item.active}
/>
)}
{/* Add extra items first */}
{section.extraItems.map((extraItem) => (
<li key={extraItem.href}>
<SidebarItem
href={extraItem.href}
title={extraItem.title}
isActive={extraItem.href.replace(/\/$/, "") ===
currentUrl}
/>
</li>
))}

{/* Add collapsible sections for all API types - always visible */}
{section.key === "deno" && (
<li>
<label
htmlFor="sub-nav-toggle-DenoAPIs"
className="sub-nav-toggle block relative py-1 px-3 after:right-4 [font:inherit] after:translate-y-1/2 after:transition-transfor after:duration-100 after:ease-in after:[background:url(./img/chevron.svg)_no-repeat_center] after:-top-0.5 after:block after:w-4 after:h-4 after:absolute"
>
Deno APIs by category
<input
type="checkbox"
id="sub-nav-toggle-DenoAPIs"
className="sub-nav-toggle-checkbox sr-only"
/>
</label>
<SidebarList>
{section.items
? section.items.map((nav: any) =>
nav.items?.map((item: any) => {
const groupedItems =
apiCategories?.deno?.categories || [];

if (item.name === "Uncategorized") {
return null;
}

if (groupedItems.includes(item.name)) {
return (
<li key={item.href}>
<SidebarItem
href={item.href}
title={item.name}
isActive={item.active}
/>
</li>
);
}
return null;
})
)
: (
// Show static list when not on Deno API page
(apiCategories?.deno?.categories || []).map((
categoryName: string,
) => (
<li key={categoryName}>
<SidebarItem
href={apiCategories?.deno?.getCategoryHref?.(
categoryName,
) ||
`/api/deno/category-${
categoryName.toLowerCase().replace(
/\s+/g,
"-",
)
}/`}
title={categoryName}
isActive={false}
/>
</li>
))
)}
</SidebarList>
</li>
)}

{section.key === "web" && (
<li>
<label
htmlFor="sub-nav-toggle-WebAPIs"
className="sub-nav-toggle block relative py-1 px-3 after:right-4 [font:inherit] after:translate-y-1/2 after:transition-transfor after:duration-100 after:ease-in after:[background:url(./img/chevron.svg)_no-repeat_center] after:-top-0.5 after:block after:w-4 after:h-4 after:absolute"
>
Web APIs by category
<input
type="checkbox"
id="sub-nav-toggle-WebAPIs"
className="sub-nav-toggle-checkbox sr-only"
/>
</label>
<SidebarList>
{section.items
? section.items.map((nav: any) =>
nav.items?.map((item: any) => (
<li key={item.href}>
<SidebarItem
href={item.href}
title={item.name}
isActive={item.active}
/>
</li>
))
)
: (
// Show static list when not on Web API page
(apiCategories?.web?.categories || []).map((
categoryName: string,
) => (
<li key={categoryName}>
<SidebarItem
href={apiCategories?.web?.getCategoryHref?.(
categoryName,
) ||
`/api/web/category-${
categoryName.toLowerCase().replace(
/\s+/g,
"-",
)
}/`}
title={categoryName}
isActive={false}
/>
</li>
))
)}
</SidebarList>
</li>
)}

{section.key === "node" && (
<li>
<label
htmlFor="sub-nav-toggle-NodeAPIs"
className="sub-nav-toggle block relative py-1 px-3 after:right-4 [font:inherit] after:translate-y-1/2 after:transition-transfor after:duration-100 after:ease-in after:[background:url(./img/chevron.svg)_no-repeat_center] after:-top-0.5 after:block after:w-4 after:h-4 after:absolute"
>
Node APIs by namespace
<input
type="checkbox"
id="sub-nav-toggle-NodeAPIs"
className="sub-nav-toggle-checkbox sr-only"
/>
</label>
<SidebarList>
{section.items
? section.items.map((nav: any) =>
nav.items?.map((item: any) => (
<li key={item.href}>
<SidebarItem
href={item.href}
title={item.name}
isActive={item.active}
/>
</li>
))
)
: (
// Show static list when not on Node API page
(apiCategories?.node?.categories || []).map((
categoryName: string,
) => (
<li key={categoryName}>
<SidebarItem
href={apiCategories?.node?.getCategoryHref?.(
categoryName,
) ||
`/api/node/${categoryName}/`}
title={categoryName}
isActive={false}
/>
</li>
))
)}
</SidebarList>
</li>
)}
</SidebarList>
</nav>
))}
Expand All @@ -34,11 +248,13 @@ export default function (data: Lume.Data) {
return (
<>
{sectionData.map((nav: any) => (
<nav>
<nav key={nav.href || nav.title}>
<SidebarCategoryHeading
href={nav.href}
title={nav.title}
isActive={nav.href && nav.href.replace(/\/$/, "") === currentUrl}
isActive={Boolean(
nav.href && nav.href.replace(/\/$/, "") === currentUrl,
)}
/>
{nav.items && Array.isArray(nav.items) && nav.items.length > 0 && (
<SidebarList>
Expand Down Expand Up @@ -93,7 +309,9 @@ export default function (data: Lume.Data) {
);
}

function SidebarList(props: { children: Element; className?: string }) {
function SidebarList(
props: { children: any; className?: string },
) {
return (
<ul
className={`p-0 list-none overflow-y-hidden ${props.className ?? ""}`}
Expand Down Expand Up @@ -132,6 +350,21 @@ function SidebarCategoryHeading(props: {
href?: string;
isActive?: boolean;
}) {
if (props.href) {
return (
<h2 class="block uppercase py-2 pr-4 mt-4 !border-0">
<a
href={props.href}
className={`text-foreground-secondary font-bold leading-none tracking-wide hover:text-primary transition-colors ${
props.isActive ? "text-primary" : ""
}`}
>
{props.title}
</a>
</h2>
);
}

return (
<h2 class="block uppercase py-2 pr-4 mt-4 text-foreground-secondary font-bold leading-[1.2] text-balance tracking-wide !border-0">
{props.title}
Expand Down
26 changes: 7 additions & 19 deletions _components/SubNav.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,26 @@
import { SidebarNav } from "../types.ts";
import { SidebarNavItem } from "../types.ts";

export default function (
{ data, currentUrl }: {
data: Lume.Data;
currentUrl: string;
},
) {
let navData = data.page?.data?.SidebarNav;
const navData = data.page?.data?.SidebarNav;
const isReference = currentUrl.startsWith("/api");
const apiReferenceSubnavItems = [
{
title: "Deno APIs",
href: "/api/deno",
},
{
title: "Web APIs",
href: "/api/web",
},
{
title: "Node APIs",
href: "/api/node",
},
] satisfies SidebarNav;

// We need to hard-code the API Reference subnav, since it's generated elsewhere.
if (isReference && !navData) navData = apiReferenceSubnavItems;
// Don't render SubNav for API reference pages - these will be handled in the sidebar
if (isReference) {
return null;
}

return (
<nav
id="refheader"
class="flex items-center pl-4 bg-header-highlight z-10 h-[var(--subnav-height)] overflow-x-auto xlplus:pl-0"
>
<ul class="flex w-full max-w-7xl mx-auto items-center gap-6">
{navData.map((nav: any) => (
{navData.map((nav: SidebarNavItem) => (
<li key={nav.href}>
<a
className={`whitespace-nowrap text-sm md:text-base p-0 text-gray-800 block relative after:absolute after:bottom-0 after:left-0 after:origin-right after:transition-transform after:scale-x-0 after:block after:w-full after:h-px after:bg-gray-800 hover:after:scale-x-100 hover:after:origin-left ${
Expand Down
Loading
Loading