Compare commits

...

3 Commits

Author SHA1 Message Date
hypercross a7477666c7 refactor: toc behaviour 2026-03-25 10:49:15 +08:00
hypercross 3aaa991bd8 refactor: toc toggle 2026-03-25 10:26:06 +08:00
hypercross 32e91f7dc8 refactor: sidebar color 2026-03-25 09:42:58 +08:00
2 changed files with 21 additions and 8 deletions

View File

@ -83,9 +83,17 @@ export const HeadingNode: Component<{
const navigate = useNavigate(); const navigate = useNavigate();
const anchor = props.node.id || ""; const anchor = props.node.id || "";
const href = `${props.basePath}#${anchor}`; const href = `${props.basePath}#${anchor}`;
const hasChildren = !!props.node.children;
// 默认收起,除非当前锚点在该节点内
const [isExpanded, setIsExpanded] = createSignal(props.depth <= 0);
const handleClick = (e: MouseEvent) => { const handleExpand = (e: MouseEvent) => {
e.preventDefault(); e.preventDefault();
if (hasChildren) {
setIsExpanded(!isExpanded());
}
};
const handleClick = (e: MouseEvent) => {
navigate(href); navigate(href);
// 滚动到目标元素,考虑导航栏高度偏移 // 滚动到目标元素,考虑导航栏高度偏移
requestAnimationFrame(() => { requestAnimationFrame(() => {
@ -94,7 +102,7 @@ export const HeadingNode: Component<{
const navBarHeight = 80; const navBarHeight = 80;
const elementPosition = element.getBoundingClientRect().top; const elementPosition = element.getBoundingClientRect().top;
const offsetPosition = window.scrollY + elementPosition - navBarHeight; const offsetPosition = window.scrollY + elementPosition - navBarHeight;
window.scrollTo({ top: offsetPosition, behavior: "smooth" }); window.scrollTo({ top: offsetPosition, behavior: "instant" });
} }
}); });
}; };
@ -103,15 +111,20 @@ export const HeadingNode: Component<{
return ( return (
<div> <div>
<span class={`${hasChildren ? "" : "invisible" } ${isExpanded() ? "rotate-90" : ""} inline-block transition-transform cursor-pointer mr-1 text-gray-400 text-xs w-3 flex-shrink-0`}
style={{ "margin-left": `${indent + 8}px` }}
onClick={handleExpand}
>
</span>
<a <a
href={href} href={href}
class="block py-0.5 px-2 text-sm text-gray-600 hover:text-gray-900 hover:bg-gray-50 rounded truncate" class="inline-flex items-center py-0.5 px-2 text-sm text-gray-600 hover:text-gray-900 hover:bg-gray-50 rounded truncate cursor-pointer"
style={{ "padding-left": `${indent + 8}px` }}
onClick={handleClick} onClick={handleClick}
> >
{props.node.title} <span class="truncate">{props.node.title}</span>
</a> </a>
<Show when={props.node.children}> <Show when={hasChildren && isExpanded()}>
<div> <div>
{props.node.children!.map((child) => ( {props.node.children!.map((child) => (
<HeadingNode <HeadingNode

View File

@ -30,7 +30,7 @@ const SidebarContent: Component<SidebarContentProps> = (props) => {
return ( return (
<div class="flex flex-col h-full"> <div class="flex flex-col h-full">
<div class="p-4 border-b"> <div class="p-4 border-b border-b-gray-200">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<h2 class="text-lg font-bold text-gray-900"></h2> <h2 class="text-lg font-bold text-gray-900"></h2>
<Show when={!props.isDesktop}> <Show when={!props.isDesktop}>
@ -63,7 +63,7 @@ const SidebarContent: Component<SidebarContentProps> = (props) => {
{/* 当前文件标题滚动区域 */} {/* 当前文件标题滚动区域 */}
<Show when={currentFileHeadings().length > 0}> <Show when={currentFileHeadings().length > 0}>
<div class="flex-1 border-t overflow-y-auto p-4 min-h-0"> <div class="flex-1 border-t-gray-200 border-t overflow-y-auto p-4 min-h-0">
<h3 class="text-xs font-semibold text-gray-500 uppercase mb-2 px-2"> <h3 class="text-xs font-semibold text-gray-500 uppercase mb-2 px-2">
</h3> </h3>