feat: implement visibility logic for sidebar nodes

Add support for hiding file tree nodes and headings based on path
revelation status. This allows the sidebar to dynamically show only
the relevant parts of the file structure and table of contents.
This commit is contained in:
2026-07-07 09:27:04 +08:00
parent c5e1167beb
commit adf28a7cf1
2 changed files with 40 additions and 3 deletions
+34 -1
View File
@@ -2,6 +2,7 @@ import { Component, createMemo, createSignal, onMount, Show } from "solid-js";
import { generateToc, type FileNode, type TocNode } from "../data-loader";
import { useLocation } from "@solidjs/router";
import { FileTreeNode, HeadingNode } from "./FileTree";
import { isPathRevealed } from "./stores/journalStream";
export interface SidebarProps {
isOpen: boolean;
@@ -33,6 +34,32 @@ const SidebarContent: Component<SidebarContentProps> = (props) => {
props.pathHeadings[pathname] || props.pathHeadings[`${pathname}.md`] || []
);
});
const revealedHeadings = createMemo(() => {
const pathname = decodeURIComponent(location.pathname);
const set = new Set<string>();
function traverse(node: TocNode, cb: (node: TocNode) => void) {
cb(node);
node.children?.forEach((child) => traverse(child, cb));
}
for (const node of currentFileHeadings()) {
traverse(node, (anode) => {
if (isPathRevealed(pathname, anode.title)) {
traverse(anode, (each) => set.add(each.title));
}
});
}
return set;
});
const isFileHidden = (node: FileNode): boolean => {
if (isPathRevealed(node.path)) return false;
if (node.children?.some((child) => !isFileHidden(child))) return false;
return true;
};
const isHeadingHidden = (node: TocNode): boolean => {
if (revealedHeadings().has(node.title)) return false;
if (node.children?.some((child) => !isHeadingHidden(child))) return false;
return true;
};
return (
<div class="flex flex-col h-full">
@@ -72,6 +99,7 @@ const SidebarContent: Component<SidebarContentProps> = (props) => {
pathHeadings={props.pathHeadings}
depth={0}
onClose={props.onClose}
isHidden={isFileHidden}
/>
))}
</div>
@@ -83,7 +111,12 @@ const SidebarContent: Component<SidebarContentProps> = (props) => {
</h3>
{currentFileHeadings().map((node) => (
<HeadingNode node={node} basePath={location.pathname} depth={0} />
<HeadingNode
node={node}
basePath={location.pathname}
depth={0}
isHidden={isHeadingHidden}
/>
))}
</div>
</Show>