mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 06:31:49 +00:00
UI: fix references problem of sidebar tabs
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-ui': patch
|
||||
---
|
||||
|
||||
Fix references problem of sidebar tabs
|
||||
@@ -7,8 +7,6 @@ import { cn } from '@/utils/cn';
|
||||
import { isActive } from '@/utils/is-active';
|
||||
import { useSidebar } from '@/contexts/sidebar';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
|
||||
import type { PageTree } from 'fumadocs-core/server';
|
||||
import { useTreePath } from '@/contexts/tree';
|
||||
|
||||
export interface Option {
|
||||
/**
|
||||
@@ -21,50 +19,54 @@ export interface Option {
|
||||
description?: ReactNode;
|
||||
|
||||
/**
|
||||
* Detect from page tree nodes
|
||||
* Detect from a list of urls
|
||||
*/
|
||||
folder?: PageTree.Folder;
|
||||
urls?: string[];
|
||||
|
||||
props?: HTMLAttributes<HTMLElement>;
|
||||
}
|
||||
|
||||
export function RootToggle({
|
||||
options,
|
||||
placeholder,
|
||||
...props
|
||||
}: {
|
||||
placeholder?: ReactNode;
|
||||
options: Option[];
|
||||
} & HTMLAttributes<HTMLButtonElement>) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { closeOnRedirect } = useSidebar();
|
||||
const pathname = usePathname();
|
||||
const path = useTreePath();
|
||||
|
||||
const selected = useMemo(() => {
|
||||
return options.findLast((item) =>
|
||||
item.folder
|
||||
? path.includes(item.folder)
|
||||
item.urls
|
||||
? item.urls.includes(pathname)
|
||||
: isActive(item.url, pathname, true),
|
||||
);
|
||||
}, [path, options, pathname]);
|
||||
}, [options, pathname]);
|
||||
|
||||
const onClick = () => {
|
||||
closeOnRedirect.current = false;
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const item = selected ? <Item {...selected} /> : placeholder;
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger
|
||||
{...props}
|
||||
className={cn(
|
||||
'flex flex-row items-center gap-2 rounded-lg px-2 py-1.5 hover:bg-fd-accent/50 hover:text-fd-accent-foreground',
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
{selected ? <Item {...selected} /> : null}
|
||||
|
||||
<ChevronDown className="me-1.5 size-4 text-fd-muted-foreground" />
|
||||
</PopoverTrigger>
|
||||
{item ? (
|
||||
<PopoverTrigger
|
||||
{...props}
|
||||
className={cn(
|
||||
'flex flex-row items-center gap-2 rounded-lg px-2 py-1.5 hover:bg-fd-accent/50 hover:text-fd-accent-foreground',
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
{item}
|
||||
<ChevronDown className="me-1.5 size-4 text-fd-muted-foreground" />
|
||||
</PopoverTrigger>
|
||||
) : null}
|
||||
<PopoverContent className="w-[var(--radix-popover-trigger-width)] overflow-hidden p-0">
|
||||
{options.map((item) => (
|
||||
<Link
|
||||
|
||||
@@ -9,10 +9,10 @@ export function getSidebarTabs(
|
||||
pageTree: PageTree.Root,
|
||||
{ transform }: TabOptions = {},
|
||||
): Option[] {
|
||||
const options: Option[] = [];
|
||||
function findOptions(node: PageTree.Folder): Option[] {
|
||||
const results: Option[] = [];
|
||||
|
||||
function traverse(node: PageTree.Node) {
|
||||
if (node.type === 'folder' && node.root) {
|
||||
if (node.root) {
|
||||
const index = node.index ?? node.children.at(0);
|
||||
|
||||
if (index?.type === 'page') {
|
||||
@@ -20,18 +20,34 @@ export function getSidebarTabs(
|
||||
url: index.url,
|
||||
title: node.name,
|
||||
icon: node.icon,
|
||||
folder: node,
|
||||
description: node.description,
|
||||
|
||||
urls: getFolderUrls(node),
|
||||
};
|
||||
|
||||
const mapped = transform ? transform(option, node) : option;
|
||||
if (mapped) options.push(mapped);
|
||||
if (mapped) results.push(mapped);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type === 'folder') node.children.forEach(traverse);
|
||||
for (const child of node.children) {
|
||||
if (child.type === 'folder') results.push(...findOptions(child));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
pageTree.children.forEach(traverse);
|
||||
return options;
|
||||
return findOptions(pageTree as PageTree.Folder);
|
||||
}
|
||||
|
||||
function getFolderUrls(folder: PageTree.Folder): string[] {
|
||||
const results: string[] = [];
|
||||
if (folder.index) results.push(folder.index.url);
|
||||
|
||||
for (const child of folder.children) {
|
||||
if (child.type === 'page') results.push(child.url);
|
||||
if (child.type === 'folder') results.push(...getFolderUrls(child));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user