Files
v10/site/src/components/docs/SidebarItem.astro
T
2026-04-14 09:50:53 -05:00

117 lines
3.3 KiB
Plaintext

---
import GithubSlugger from 'github-slugger';
import DropdownIcon from '@/assets/icons/dropdown-arrow.svg?react';
import type { Guide, Section, SupportedFramework } from '@/types/docs';
import { isSection } from '@/types/docs';
type Props = {
item: Guide | Section;
framework: SupportedFramework;
docTitles: Map<string, string>;
depth?: number;
};
const { item, framework, docTitles, depth = 0 } = Astro.props;
const currentPath = Astro.url.pathname;
const slugger = new GithubSlugger();
// Helper to check if this item or any of its children contains the active path
function containsActivePath(item: Guide | Section): boolean {
if (isSection(item)) {
return item.contents.some((child) => containsActivePath(child));
} else {
const itemPath = `/docs/framework/${framework}/${item.slug}`;
return itemPath === currentPath;
}
}
const isActive = containsActivePath(item);
function getGroup(depth: number) {
if (depth === 0) return 'group';
if (depth === 1) return 'group/1';
if (depth === 2) return 'group/2';
return '';
}
function getGroupMargin(depth: number) {
if (depth === 1) return 'group-open/1:mb-1';
if (depth === 2) return 'group-open/2:mb-1';
return '';
}
function getGroupRotate(depth: number) {
if (depth === 0) return 'group-open:rotate-180';
if (depth === 1) return 'group-open/1:rotate-180';
if (depth === 2) return 'group-open/2:rotate-180';
return '';
}
---
{
isSection(item) ? (
<details
id={slugger.slug(item.sidebarLabel)}
open={isActive || item.defaultOpen !== false}
class:list={[getGroup(depth), depth === 0 && "my-4 first:mt-0"]}
>
<summary
class:list={[
"flex items-center gap-4 py-2 text-faded-black dark:text-manila-light",
"cursor-pointer",
depth === 0
? "font-display text-h4 leading-tight uppercase"
: "text-p3",
depth > 0 && "border-l pl-4",
isActive ? "border-orange" : "border-manila-75 dark:border-warm-gray",
getGroupMargin(depth),
]}
style={
depth ? `margin-left: calc(var(--spacing) * ${(depth - 1) * 4})` : ``
}
>
<span class="flex-1">{item.sidebarLabel}</span>
<DropdownIcon
width={"0.65rem"}
className={getGroupRotate(depth)}
aria-hidden="true"
/>
</summary>
<div>
{item.contents.map((contentItem) => (
<Astro.self
item={contentItem}
framework={framework}
docTitles={docTitles}
depth={depth + 1}
/>
))}
</div>
</details>
) : (
<a
aria-current={isActive ? "page" : undefined}
class:list={[
"flex items-center gap-4 py-2 text-p3 text-faded-black dark:text-manila-light",
"cursor-pointer",
depth === 0 && "font-bold",
depth > 0 && "border-l pl-4",
depth > 0 && isActive && "font-bold",
isActive ? "border-orange" : "border-manila-75 dark:border-warm-gray",
]}
style={`margin-left: calc(var(--spacing) * ${(depth - 1) * 4})`}
href={`/docs/framework/${framework}/${item.slug}`}
>
{item.devOnly ? "[Dev only] " : ""}
{item.sidebarLabel || docTitles.get(item.slug) || item.slug}
</a>
)
}
<style>
summary {
list-style: none;
}
summary::-webkit-details-marker {
display: none;
}
</style>