Add remaining samples, tooling, and local project assets
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
---
|
||||
import SidebarPersister from "@astrojs/starlight/components/SidebarPersister.astro";
|
||||
import SidebarSublist from "@astrojs/starlight/components/SidebarSublist.astro";
|
||||
import ThemeSelect from "virtual:starlight/components/ThemeSelect";
|
||||
import SidebarToggle from "./SidebarToggle.astro";
|
||||
|
||||
const { sidebar = [] } = Astro.locals.starlightRoute ?? {};
|
||||
const currentPath = decodeURIComponent(Astro.url.pathname);
|
||||
|
||||
const getTopSegment = (value) => {
|
||||
const normalized = decodeURIComponent(value || "")
|
||||
.replace(/^\/+|\/+$/g, "");
|
||||
if (!normalized) return "";
|
||||
return normalized.split("/")[0];
|
||||
};
|
||||
|
||||
const currentTopSegment = getTopSegment(currentPath);
|
||||
|
||||
const entryTopSegment = (entry) => {
|
||||
if (entry.type === "link" && entry.href) {
|
||||
try {
|
||||
const pathname = new URL(entry.href, Astro.url.origin).pathname;
|
||||
return getTopSegment(pathname);
|
||||
} catch {
|
||||
return getTopSegment(entry.href);
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.type === "group" && Array.isArray(entry.entries)) {
|
||||
for (const child of entry.entries) {
|
||||
const segment = entryTopSegment(child);
|
||||
if (segment) return segment;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
const entryContainsPath = (entry) => {
|
||||
if (entry.type === "link" && entry.href) {
|
||||
const linkHref = decodeURIComponent(entry.href);
|
||||
return currentPath.startsWith(linkHref);
|
||||
}
|
||||
|
||||
if (entry.type === "group" && Array.isArray(entry.entries)) {
|
||||
return entry.entries.some(entryContainsPath);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const activeTopLevelGroup = sidebar.find(
|
||||
(entry) =>
|
||||
entry.type === "group" &&
|
||||
(entryContainsPath(entry) || (currentTopSegment && entryTopSegment(entry) === currentTopSegment)),
|
||||
);
|
||||
|
||||
const scopedSidebar =
|
||||
activeTopLevelGroup && Array.isArray(activeTopLevelGroup.entries)
|
||||
? activeTopLevelGroup.entries
|
||||
: sidebar;
|
||||
|
||||
---
|
||||
|
||||
<div class="mobile-theme-bar md:sl-hidden" data-testid="mobile-theme-toggle">
|
||||
<ThemeSelect />
|
||||
<span class="theme-label">Light / Dark</span>
|
||||
</div>
|
||||
<SidebarPersister>
|
||||
<SidebarSublist sublist={scopedSidebar} />
|
||||
</SidebarPersister>
|
||||
<SidebarToggle />
|
||||
|
||||
<style>
|
||||
:global(#starlight__sidebar a[data-cel-hidden="true"]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:global(html.show-hidden-sidebar-items #starlight__sidebar a[data-cel-hidden="true"]) {
|
||||
display: revert;
|
||||
}
|
||||
|
||||
.mobile-theme-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.5rem 0 0.75rem;
|
||||
border-bottom: 1px solid var(--sl-color-hairline);
|
||||
}
|
||||
|
||||
.mobile-theme-bar .nova-theme-select {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
.mobile-theme-bar .theme-label {
|
||||
font-size: 0.9rem;
|
||||
color: var(--sl-color-gray-3);
|
||||
}
|
||||
|
||||
@media (min-width: 50rem) {
|
||||
.mobile-theme-bar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script is:inline>
|
||||
(() => {
|
||||
const SHOW_CLASS = "show-hidden-sidebar-items";
|
||||
const truthy = new Set(["true", "1", "yes", "y", "on"]);
|
||||
|
||||
const shouldShowHidden = () => {
|
||||
const value = new URLSearchParams(window.location.search).get("showHiddens");
|
||||
if (!value) return false;
|
||||
return truthy.has(value.trim().toLowerCase());
|
||||
};
|
||||
|
||||
const applySidebarHiddenToggle = () => {
|
||||
const showHidden = shouldShowHidden();
|
||||
document.documentElement.classList.toggle(SHOW_CLASS, showHidden);
|
||||
|
||||
const sidebar = document.getElementById("starlight__sidebar");
|
||||
if (!sidebar) return;
|
||||
|
||||
const hiddenLinks = sidebar.querySelectorAll("a[data-cel-hidden='true']");
|
||||
for (const link of hiddenLinks) {
|
||||
link.toggleAttribute("hidden", !showHidden);
|
||||
}
|
||||
|
||||
const listItems = sidebar.querySelectorAll("li");
|
||||
for (const item of listItems) {
|
||||
const directLink = item.querySelector(":scope > a[href]");
|
||||
if (directLink) {
|
||||
item.toggleAttribute("hidden", !showHidden && directLink.hasAttribute("hidden"));
|
||||
continue;
|
||||
}
|
||||
|
||||
const descendantLinks = item.querySelectorAll("a[href]");
|
||||
if (descendantLinks.length === 0) continue;
|
||||
|
||||
const hasVisibleLink = Array.from(descendantLinks).some(
|
||||
(link) => !link.hasAttribute("hidden"),
|
||||
);
|
||||
item.toggleAttribute("hidden", !showHidden && !hasVisibleLink);
|
||||
}
|
||||
};
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", applySidebarHiddenToggle, { once: true });
|
||||
} else {
|
||||
applySidebarHiddenToggle();
|
||||
}
|
||||
|
||||
document.addEventListener("astro:page-load", applySidebarHiddenToggle);
|
||||
})();
|
||||
</script>
|
||||
Reference in New Issue
Block a user