Skip to content

Commit e1cb638

Browse files
committed
chore: updated nav
1 parent 97fa3fc commit e1cb638

26 files changed

Lines changed: 3371 additions & 297 deletions

package.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
},
1717
"dependencies": {
1818
"@fumadocs/mdx-remote": "^1.4.0",
19-
"@netlify/plugin-nextjs": "^5.13.0",
19+
"@netlify/plugin-nextjs": "^5.13.1",
20+
"@radix-ui/react-collapsible": "^1.1.12",
21+
"@radix-ui/react-popover": "^1.1.15",
22+
"@radix-ui/react-presence": "^1.1.5",
23+
"@radix-ui/react-scroll-area": "^1.2.10",
2024
"@radix-ui/react-separator": "^1.1.7",
2125
"class-variance-authority": "^0.7.1",
2226
"clsx": "^2.1.1",
@@ -27,7 +31,7 @@
2731
"glob": "^11.0.3",
2832
"katex": "^0.16.22",
2933
"lucide-react": "^0.540.0",
30-
"mermaid": "^11.10.1",
34+
"mermaid": "^11.11.0",
3135
"next": "15.4.5",
3236
"next-themes": "^0.4.6",
3337
"react": "^19.1.1",
@@ -41,15 +45,15 @@
4145
"tailwind-merge": "^3.3.1"
4246
},
4347
"devDependencies": {
44-
"@biomejs/biome": "^2.2.2",
45-
"@tailwindcss/postcss": "^4.1.12",
48+
"@biomejs/biome": "^2.2.3",
49+
"@tailwindcss/postcss": "^4.1.13",
4650
"@types/mdx": "^2.0.13",
4751
"@types/node": "24.1.0",
4852
"@types/react": "^19.1.12",
4953
"@types/react-dom": "^19.1.9",
5054
"postcss": "^8.5.6",
51-
"tailwindcss": "^4.1.12",
52-
"tw-animate-css": "^1.3.7",
55+
"tailwindcss": "^4.1.13",
56+
"tw-animate-css": "^1.3.8",
5357
"typescript": "^5.9.2"
5458
}
5559
}

pnpm-lock.yaml

Lines changed: 190 additions & 267 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/(docs)/[...slug]/layout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { DocsLayout } from "fumadocs-ui/layouts/docs";
1+
import { DocsLayout } from "fumadocs-ui/layouts/notebook";
22
import type { ReactNode } from "react";
3-
43
import { baseOptions } from "@/app/layout.config";
4+
55
import {
66
ArbitrumIcon,
77
EthereumIcon,
@@ -58,6 +58,7 @@ export default async function Layout({
5858
return (
5959
<DocsLayout
6060
tree={currentTree}
61+
nav={{...baseOptions, mode: 'top', transparentMode: 'none'}}
6162
{...baseOptions}
6263
sidebar={{
6364
tabs: [

src/app/layout.config.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
1+
import type { BaseLayoutProps } from "@/components/layout/shared";
22
import { GlobeIcon, HomeIcon, MessageSquareMoreIcon } from "lucide-react";
33

44
/**

src/components/language-toggle.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
'use client';
2+
import { type ButtonHTMLAttributes, type HTMLAttributes } from 'react';
3+
import { useI18n } from 'fumadocs-ui/contexts/i18n';
4+
import {
5+
Popover,
6+
PopoverContent,
7+
PopoverTrigger,
8+
} from './ui/popover';
9+
import { cn } from '../lib/cn';
10+
import { buttonVariants } from './ui/button';
11+
12+
export type LanguageSelectProps = ButtonHTMLAttributes<HTMLButtonElement>;
13+
14+
export function LanguageToggle(props: LanguageSelectProps): React.ReactElement {
15+
const context = useI18n();
16+
if (!context.locales) throw new Error('Missing `<I18nProvider />`');
17+
18+
return (
19+
<Popover>
20+
<PopoverTrigger
21+
aria-label={context.text.chooseLanguage}
22+
{...props}
23+
className={cn(
24+
buttonVariants({
25+
color: 'ghost',
26+
className: 'gap-1.5 p-1.5',
27+
}),
28+
props.className,
29+
)}
30+
>
31+
{props.children}
32+
</PopoverTrigger>
33+
<PopoverContent className="flex flex-col overflow-hidden p-0">
34+
<p className="mb-1 p-2 text-xs font-medium text-fd-muted-foreground">
35+
{context.text.chooseLanguage}
36+
</p>
37+
{context.locales.map((item) => (
38+
<button
39+
key={item.locale}
40+
type="button"
41+
className={cn(
42+
'p-2 text-start text-sm',
43+
item.locale === context.locale
44+
? 'bg-fd-primary/10 font-medium text-fd-primary'
45+
: 'hover:bg-fd-accent hover:text-fd-accent-foreground',
46+
)}
47+
onClick={() => {
48+
context.onChange?.(item.locale);
49+
}}
50+
>
51+
{item.name}
52+
</button>
53+
))}
54+
</PopoverContent>
55+
</Popover>
56+
);
57+
}
58+
59+
export function LanguageToggleText(
60+
props: HTMLAttributes<HTMLSpanElement>,
61+
): React.ReactElement {
62+
const context = useI18n();
63+
const text = context.locales?.find(
64+
(item) => item.locale === context.locale,
65+
)?.name;
66+
67+
return <span {...props}>{text}</span>;
68+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
'use client';
2+
import { cn } from '../../../lib/cn';
3+
import { type ComponentProps, useMemo } from 'react';
4+
import { useSidebar } from 'fumadocs-ui/contexts/sidebar';
5+
import { useNav } from 'fumadocs-ui/contexts/layout';
6+
import { buttonVariants } from '../../ui/button';
7+
import { Sidebar as SidebarIcon } from 'lucide-react';
8+
import Link from 'fumadocs-core/link';
9+
import { usePathname } from 'fumadocs-core/framework';
10+
import { isTabActive } from '../../../lib/is-active';
11+
import type { Option } from '../../root-toggle';
12+
13+
export function Navbar({
14+
mode,
15+
...props
16+
}: ComponentProps<'header'> & { mode: 'top' | 'auto' }) {
17+
const { open, collapsed } = useSidebar();
18+
const { isTransparent } = useNav();
19+
20+
return (
21+
<header
22+
id="nd-subnav"
23+
{...props}
24+
className={cn(
25+
'fixed flex flex-col top-(--fd-banner-height) left-0 right-(--removed-body-scroll-bar-size,0) z-10 px-(--fd-layout-offset) h-(--fd-nav-height) backdrop-blur-sm transition-colors',
26+
(!isTransparent || open) && 'bg-fd-background/80',
27+
mode === 'auto' &&
28+
!collapsed &&
29+
'ps-[calc(var(--fd-layout-offset)+var(--fd-sidebar-width))]',
30+
props.className,
31+
)}
32+
>
33+
{props.children}
34+
</header>
35+
);
36+
}
37+
38+
export function LayoutBody(props: ComponentProps<'main'>) {
39+
const { collapsed } = useSidebar();
40+
41+
return (
42+
<main
43+
id="nd-docs-layout"
44+
{...props}
45+
className={cn(
46+
'flex flex-1 flex-col transition-[padding] pt-(--fd-nav-height) fd-notebook-layout',
47+
!collapsed && 'mx-(--fd-layout-offset)',
48+
props.className,
49+
)}
50+
style={{
51+
...props.style,
52+
paddingInlineStart: collapsed
53+
? 'min(calc(100vw - var(--fd-page-width)), var(--fd-sidebar-width))'
54+
: 'var(--fd-sidebar-width)',
55+
}}
56+
>
57+
{props.children}
58+
</main>
59+
);
60+
}
61+
62+
export function NavbarSidebarTrigger({
63+
className,
64+
...props
65+
}: ComponentProps<'button'>) {
66+
const { setOpen } = useSidebar();
67+
68+
return (
69+
<button
70+
{...props}
71+
className={cn(
72+
buttonVariants({
73+
color: 'ghost',
74+
size: 'icon-sm',
75+
className,
76+
}),
77+
)}
78+
onClick={() => setOpen((prev) => !prev)}
79+
>
80+
<SidebarIcon />
81+
</button>
82+
);
83+
}
84+
85+
export function LayoutTabs({
86+
options,
87+
...props
88+
}: ComponentProps<'div'> & {
89+
options: Option[];
90+
}) {
91+
const pathname = usePathname();
92+
const selected = useMemo(() => {
93+
return options.findLast((option) => isTabActive(option, pathname));
94+
}, [options, pathname]);
95+
96+
return (
97+
<div
98+
{...props}
99+
className={cn(
100+
'flex flex-row items-end gap-6 overflow-auto',
101+
props.className,
102+
)}
103+
>
104+
{options.map((option) => (
105+
<LayoutTab
106+
key={option.url}
107+
selected={selected === option}
108+
option={option}
109+
/>
110+
))}
111+
</div>
112+
);
113+
}
114+
115+
function LayoutTab({
116+
option: { title, url, unlisted, props },
117+
selected = false,
118+
}: {
119+
option: Option;
120+
selected?: boolean;
121+
}) {
122+
return (
123+
<Link
124+
href={url}
125+
{...props}
126+
className={cn(
127+
'inline-flex border-b-2 border-transparent transition-colors items-center pb-1.5 font-medium gap-2 text-fd-muted-foreground text-sm text-nowrap hover:text-fd-accent-foreground',
128+
unlisted && !selected && 'hidden',
129+
selected && 'border-fd-primary text-fd-primary',
130+
props?.className,
131+
)}
132+
>
133+
{title}
134+
</Link>
135+
);
136+
}

0 commit comments

Comments
 (0)