1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
'use client';
import { cva } from 'class-variance-authority';
import Link from 'fumadocs-core/link';
import { cn } from '@/lib/utils';
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
import {
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuTrigger,
} from 'fumadocs-ui/components/ui/navigation-menu';
import { BaseLinkItem, type LinkItemType } from 'fumadocs-ui/layouts/links';
import type { ComponentPropsWithoutRef } from 'react';
const menuItemVariants = cva('', {
variants: {
variant: {
main: 'inline-flex items-center gap-2 py-1.5 transition-colors hover:text-fd-popover-foreground/50 data-[active=true]:font-medium data-[active=true]:text-fd-primary [&_svg]:size-4',
icon: buttonVariants({
size: 'icon',
color: 'ghost',
}),
button: buttonVariants({
color: 'secondary',
className: 'gap-1.5 [&_svg]:size-4',
}),
},
},
defaultVariants: {
variant: 'main',
},
});
export const MenuLinkItem = ({
item,
...props
}: {
item: LinkItemType;
className?: string;
}) => {
if (item.type === 'custom')
return <div className={cn('grid', props.className)}>{item.children}</div>;
if (item.type === 'menu') {
const header = (
<>
{item.icon}
{item.text}
</>
);
return (
<div className={cn('mb-4 flex flex-col', props.className)}>
<p className='mb-1 text-fd-muted-foreground text-sm'>
{item.url ? (
<NavigationMenuLink asChild>
<Link href={item.url}>{header}</Link>
</NavigationMenuLink>
) : (
header
)}
</p>
{item.items.map((child, i) => (
<MenuLinkItem key={i.toString()} item={child} />
))}
</div>
);
}
return (
<NavigationMenuLink asChild>
<BaseLinkItem
item={item}
className={cn(
menuItemVariants({ variant: item.type }),
props.className,
)}
aria-label={item.type === 'icon' ? item.label : undefined}
>
{item.icon}
{item.type === 'icon' ? undefined : item.text}
</BaseLinkItem>
</NavigationMenuLink>
);
};
export const Menu = NavigationMenuItem;
export const MenuTrigger = ({
...props
}: ComponentPropsWithoutRef<typeof NavigationMenuTrigger> & {}) => {
return (
<NavigationMenuTrigger
{...props}
className={cn(
buttonVariants({
size: 'icon',
color: 'ghost',
}),
props.className,
)}
>
{props.children}
</NavigationMenuTrigger>
);
};
export const MenuContent = (
props: ComponentPropsWithoutRef<typeof NavigationMenuContent>,
) => {
return (
<NavigationMenuContent
{...props}
className={cn('flex flex-col p-4', props.className)}
>
{props.children}
</NavigationMenuContent>
);
};
|