mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
UI: support on on docs layout
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'fumadocs-ui': patch
|
||||
'@fumadocs/base-ui': patch
|
||||
---
|
||||
|
||||
support `on` on docs layout
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
SidebarTrigger,
|
||||
SidebarViewport,
|
||||
} from './sidebar';
|
||||
import { type BaseLayoutProps, renderTitleNav, resolveLinkItems } from '@/layouts/shared';
|
||||
import { type BaseLayoutProps, renderTitleNav, useLinkItems } from '@/layouts/shared';
|
||||
import { LinkItem } from '@fumadocs/ui/link-item';
|
||||
import { LanguageToggle, LanguageToggleText } from '@/layouts/shared/language-toggle';
|
||||
import { LayoutBody, LayoutContextProvider, LayoutHeader, LayoutTabs } from './client';
|
||||
@@ -90,16 +90,16 @@ export function DocsLayout({
|
||||
}
|
||||
return [];
|
||||
}, [tree, sidebarTabs]);
|
||||
const links = resolveLinkItems(props);
|
||||
const { menuItems } = useLinkItems(props);
|
||||
|
||||
function sidebar() {
|
||||
const { footer, banner, collapsible = true, component, components, ...rest } = sidebarProps;
|
||||
if (component) return component;
|
||||
|
||||
const iconLinks = links.filter((item) => item.type === 'icon');
|
||||
const iconLinks = menuItems.filter((item) => item.type === 'icon');
|
||||
const viewport = (
|
||||
<SidebarViewport>
|
||||
{links
|
||||
{menuItems
|
||||
.filter((v) => v.type !== 'icon')
|
||||
.map((item, i, list) => (
|
||||
<SidebarLinkItem key={i} item={item} className={cn(i === list.length - 1 && 'mb-4')} />
|
||||
|
||||
@@ -12,12 +12,7 @@ import {
|
||||
import { cva } from 'class-variance-authority';
|
||||
import Link from 'fumadocs-core/link';
|
||||
import { cn } from '@fumadocs/ui/cn';
|
||||
import {
|
||||
type LinkItemType,
|
||||
type NavOptions,
|
||||
renderTitleNav,
|
||||
resolveLinkItems,
|
||||
} from '@/layouts/shared';
|
||||
import { type LinkItemType, type NavOptions, renderTitleNav, useLinkItems } from '@/layouts/shared';
|
||||
import { LinkItem } from '@fumadocs/ui/link-item';
|
||||
import {
|
||||
NavigationMenuRoot,
|
||||
@@ -45,7 +40,7 @@ const MobileMenuContext = createContext<{
|
||||
export const navItemVariants = cva('[&_svg]:size-4', {
|
||||
variants: {
|
||||
variant: {
|
||||
main: 'inline-flex items-center gap-1 p-2 text-fd-muted-foreground transition-colors hover:text-fd-accent-foreground data-[active=true]:text-fd-primary data-[popup-open]:text-fd-primary',
|
||||
main: 'inline-flex items-center gap-1 p-2 text-fd-muted-foreground transition-colors hover:text-fd-accent-foreground data-[active=true]:text-fd-primary data-popup-open:text-fd-primary',
|
||||
button: buttonVariants({
|
||||
color: 'secondary',
|
||||
className: 'gap-1.5',
|
||||
@@ -69,26 +64,7 @@ export function Header({
|
||||
themeSwitch = {},
|
||||
searchToggle = {},
|
||||
}: HomeLayoutProps) {
|
||||
const { navItems, menuItems } = useMemo(() => {
|
||||
const navItems: LinkItemType[] = [];
|
||||
const menuItems: LinkItemType[] = [];
|
||||
|
||||
for (const item of resolveLinkItems({ links, githubUrl })) {
|
||||
switch (item.on ?? 'all') {
|
||||
case 'menu':
|
||||
menuItems.push(item);
|
||||
break;
|
||||
case 'nav':
|
||||
navItems.push(item);
|
||||
break;
|
||||
default:
|
||||
navItems.push(item);
|
||||
menuItems.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return { navItems, menuItems };
|
||||
}, [links, githubUrl]);
|
||||
const { menuItems, navItems } = useLinkItems({ links, githubUrl });
|
||||
|
||||
return (
|
||||
<MobileMenuCollapsible
|
||||
@@ -147,7 +123,7 @@ export function Header({
|
||||
}),
|
||||
)}
|
||||
>
|
||||
<ChevronDown className="transition-transform duration-300 group-data-[panel-open]:rotate-180" />
|
||||
<ChevronDown className="transition-transform duration-300 group-data-panel-open:rotate-180" />
|
||||
</CollapsibleTrigger>
|
||||
</ul>
|
||||
</NavigationMenuList>
|
||||
@@ -180,13 +156,13 @@ export function Header({
|
||||
<NavigationMenu.Portal>
|
||||
<NavigationMenu.Positioner
|
||||
sideOffset={10}
|
||||
className="z-20 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[left,right] duration-(--duration) ease-(--easing) data-[instant]:transition-none"
|
||||
className="z-20 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[left,right] duration-(--duration) ease-(--easing) data-instant:transition-none"
|
||||
style={{
|
||||
['--duration' as string]: '0.35s',
|
||||
['--easing' as string]: 'cubic-bezier(0.22, 1, 0.36, 1)',
|
||||
}}
|
||||
>
|
||||
<NavigationMenu.Popup className="relative w-(--popup-width) h-(--popup-height) max-w-(--fd-layout-width,1400px) origin-(--transform-origin) rounded-xl bg-fd-background/80 border backdrop-blur-lg shadow-lg transition-[opacity,transform,width,height,scale,translate] duration-(--duration) ease-(--easing) data-[ending-style]:scale-90 data-[ending-style]:opacity-0 data-[ending-style]:duration-150 data-[starting-style]:scale-90 data-[starting-style]:opacity-0">
|
||||
<NavigationMenu.Popup className="relative w-(--popup-width) h-(--popup-height) max-w-(--fd-layout-width,1400px) origin-(--transform-origin) rounded-xl bg-fd-background/80 border backdrop-blur-lg shadow-lg transition-[opacity,transform,width,height,scale,translate] duration-(--duration) ease-(--easing) data-ending-style:scale-90 data-ending-style:opacity-0 data-ending-style:duration-150 data-starting-style:scale-90 data-starting-style:opacity-0">
|
||||
<NavigationMenu.Viewport className="relative size-full overflow-hidden" />
|
||||
</NavigationMenu.Popup>
|
||||
</NavigationMenu.Positioner>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type ComponentProps, type FC, type HTMLAttributes, type ReactNode, useMemo } from 'react';
|
||||
import { type BaseLayoutProps, renderTitleNav, resolveLinkItems } from '@/layouts/shared';
|
||||
import { type BaseLayoutProps, renderTitleNav, useLinkItems } from '@/layouts/shared';
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarCollapseTrigger,
|
||||
@@ -76,7 +76,7 @@ export function DocsLayout(props: DocsLayoutProps) {
|
||||
} = props;
|
||||
|
||||
const navMode = nav.mode ?? 'auto';
|
||||
const links = resolveLinkItems(props);
|
||||
const { menuItems, navItems } = useLinkItems(props);
|
||||
const tabs = useMemo(() => {
|
||||
if (Array.isArray(tabOptions)) {
|
||||
return tabOptions;
|
||||
@@ -96,7 +96,7 @@ export function DocsLayout(props: DocsLayoutProps) {
|
||||
function sidebar() {
|
||||
const { banner, footer, components, collapsible = true, ...rest } = sidebarProps;
|
||||
|
||||
const iconLinks = links.filter((item) => item.type === 'icon');
|
||||
const iconLinks = menuItems.filter((item) => item.type === 'icon');
|
||||
const Header =
|
||||
typeof banner === 'function'
|
||||
? banner
|
||||
@@ -124,7 +124,7 @@ export function DocsLayout(props: DocsLayoutProps) {
|
||||
);
|
||||
const viewport = (
|
||||
<SidebarViewport>
|
||||
{links
|
||||
{menuItems
|
||||
.filter((item) => item.type !== 'icon')
|
||||
.map((item, i, arr) => (
|
||||
<SidebarLinkItem
|
||||
@@ -254,7 +254,7 @@ export function DocsLayout(props: DocsLayoutProps) {
|
||||
<Sidebar defaultOpenLevel={defaultOpenLevel} prefetch={prefetch}>
|
||||
<LayoutBody {...props.containerProps}>
|
||||
{sidebar()}
|
||||
<DocsNavbar {...props} links={links} tabs={tabs} />
|
||||
<DocsNavbar {...props} links={navItems} tabs={tabs} />
|
||||
{props.children}
|
||||
</LayoutBody>
|
||||
</Sidebar>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ComponentProps, ReactNode } from 'react';
|
||||
import { useMemo, type ComponentProps, type ReactNode } from 'react';
|
||||
import type { I18nConfig } from 'fumadocs-core/i18n';
|
||||
import type { LinkItemType } from '@fumadocs/ui/link-item';
|
||||
import Link from 'fumadocs-core/link';
|
||||
@@ -99,4 +99,28 @@ export function renderTitleNav(
|
||||
);
|
||||
}
|
||||
|
||||
export function useLinkItems({ githubUrl, links }: Pick<BaseLayoutProps, 'links' | 'githubUrl'>) {
|
||||
return useMemo(() => {
|
||||
const all = resolveLinkItems({ links, githubUrl });
|
||||
const navItems: LinkItemType[] = [];
|
||||
const menuItems: LinkItemType[] = [];
|
||||
|
||||
for (const item of all) {
|
||||
switch (item.on ?? 'all') {
|
||||
case 'menu':
|
||||
menuItems.push(item);
|
||||
break;
|
||||
case 'nav':
|
||||
navItems.push(item);
|
||||
break;
|
||||
default:
|
||||
navItems.push(item);
|
||||
menuItems.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return { navItems, menuItems, all };
|
||||
}, [links, githubUrl]);
|
||||
}
|
||||
|
||||
export type * from '@fumadocs/ui/link-item';
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
SidebarTrigger,
|
||||
SidebarViewport,
|
||||
} from './sidebar';
|
||||
import { type BaseLayoutProps, renderTitleNav, resolveLinkItems } from '@/layouts/shared';
|
||||
import { type BaseLayoutProps, renderTitleNav, useLinkItems } from '@/layouts/shared';
|
||||
import { LinkItem } from '@fumadocs/ui/link-item';
|
||||
import { LanguageToggle, LanguageToggleText } from '@/layouts/shared/language-toggle';
|
||||
import { LayoutBody, LayoutContextProvider, LayoutHeader, LayoutTabs } from './client';
|
||||
@@ -90,16 +90,16 @@ export function DocsLayout({
|
||||
}
|
||||
return [];
|
||||
}, [tree, sidebarTabs]);
|
||||
const links = resolveLinkItems(props);
|
||||
const { menuItems } = useLinkItems(props);
|
||||
|
||||
function sidebar() {
|
||||
const { footer, banner, collapsible = true, component, components, ...rest } = sidebarProps;
|
||||
if (component) return component;
|
||||
|
||||
const iconLinks = links.filter((item) => item.type === 'icon');
|
||||
const iconLinks = menuItems.filter((item) => item.type === 'icon');
|
||||
const viewport = (
|
||||
<SidebarViewport>
|
||||
{links
|
||||
{menuItems
|
||||
.filter((v) => v.type !== 'icon')
|
||||
.map((item, i, list) => (
|
||||
<SidebarLinkItem key={i} item={item} className={cn(i === list.length - 1 && 'mb-4')} />
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
'use client';
|
||||
import { type ComponentProps, Fragment, useMemo, useState } from 'react';
|
||||
import { type ComponentProps, Fragment, useState } from 'react';
|
||||
import { cva } from 'class-variance-authority';
|
||||
import Link from 'fumadocs-core/link';
|
||||
import { cn } from '@fumadocs/ui/cn';
|
||||
import {
|
||||
type LinkItemType,
|
||||
type NavOptions,
|
||||
renderTitleNav,
|
||||
resolveLinkItems,
|
||||
} from '@/layouts/shared';
|
||||
import { type LinkItemType, type NavOptions, renderTitleNav, useLinkItems } from '@/layouts/shared';
|
||||
import { LinkItem } from '@fumadocs/ui/link-item';
|
||||
import {
|
||||
NavigationMenu,
|
||||
@@ -54,26 +49,7 @@ export function Header({
|
||||
themeSwitch = {},
|
||||
searchToggle = {},
|
||||
}: HomeLayoutProps) {
|
||||
const { navItems, menuItems } = useMemo(() => {
|
||||
const navItems: LinkItemType[] = [];
|
||||
const menuItems: LinkItemType[] = [];
|
||||
|
||||
for (const item of resolveLinkItems({ links, githubUrl })) {
|
||||
switch (item.on ?? 'all') {
|
||||
case 'menu':
|
||||
menuItems.push(item);
|
||||
break;
|
||||
case 'nav':
|
||||
navItems.push(item);
|
||||
break;
|
||||
default:
|
||||
navItems.push(item);
|
||||
menuItems.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return { navItems, menuItems };
|
||||
}, [links, githubUrl]);
|
||||
const { navItems, menuItems } = useLinkItems({ links, githubUrl });
|
||||
|
||||
return (
|
||||
<HeaderNavigationMenu transparentMode={nav.transparentMode}>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type ComponentProps, type FC, type HTMLAttributes, type ReactNode, useMemo } from 'react';
|
||||
import { type BaseLayoutProps, renderTitleNav, resolveLinkItems } from '@/layouts/shared';
|
||||
import { type BaseLayoutProps, renderTitleNav, useLinkItems } from '@/layouts/shared';
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarCollapseTrigger,
|
||||
@@ -76,7 +76,7 @@ export function DocsLayout(props: DocsLayoutProps) {
|
||||
} = props;
|
||||
|
||||
const navMode = nav.mode ?? 'auto';
|
||||
const links = resolveLinkItems(props);
|
||||
const { menuItems, navItems } = useLinkItems(props);
|
||||
const tabs = useMemo(() => {
|
||||
if (Array.isArray(tabOptions)) {
|
||||
return tabOptions;
|
||||
@@ -96,7 +96,7 @@ export function DocsLayout(props: DocsLayoutProps) {
|
||||
function sidebar() {
|
||||
const { banner, footer, components, collapsible = true, ...rest } = sidebarProps;
|
||||
|
||||
const iconLinks = links.filter((item) => item.type === 'icon');
|
||||
const iconLinks = menuItems.filter((item) => item.type === 'icon');
|
||||
const Header =
|
||||
typeof banner === 'function'
|
||||
? banner
|
||||
@@ -124,7 +124,7 @@ export function DocsLayout(props: DocsLayoutProps) {
|
||||
);
|
||||
const viewport = (
|
||||
<SidebarViewport>
|
||||
{links
|
||||
{menuItems
|
||||
.filter((item) => item.type !== 'icon')
|
||||
.map((item, i, arr) => (
|
||||
<SidebarLinkItem
|
||||
@@ -254,7 +254,7 @@ export function DocsLayout(props: DocsLayoutProps) {
|
||||
<Sidebar defaultOpenLevel={defaultOpenLevel} prefetch={prefetch}>
|
||||
<LayoutBody {...props.containerProps}>
|
||||
{sidebar()}
|
||||
<DocsNavbar {...props} links={links} tabs={tabs} />
|
||||
<DocsNavbar {...props} links={navItems} tabs={tabs} />
|
||||
{props.children}
|
||||
</LayoutBody>
|
||||
</Sidebar>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ComponentProps, ReactNode } from 'react';
|
||||
import { useMemo, type ComponentProps, type ReactNode } from 'react';
|
||||
import type { I18nConfig } from 'fumadocs-core/i18n';
|
||||
import type { LinkItemType } from '@fumadocs/ui/link-item';
|
||||
import Link from 'fumadocs-core/link';
|
||||
@@ -99,4 +99,28 @@ export function renderTitleNav(
|
||||
);
|
||||
}
|
||||
|
||||
export function useLinkItems({ githubUrl, links }: Pick<BaseLayoutProps, 'links' | 'githubUrl'>) {
|
||||
return useMemo(() => {
|
||||
const all = resolveLinkItems({ links, githubUrl });
|
||||
const navItems: LinkItemType[] = [];
|
||||
const menuItems: LinkItemType[] = [];
|
||||
|
||||
for (const item of all) {
|
||||
switch (item.on) {
|
||||
case 'menu':
|
||||
menuItems.push(item);
|
||||
break;
|
||||
case 'nav':
|
||||
navItems.push(item);
|
||||
break;
|
||||
default:
|
||||
navItems.push(item);
|
||||
menuItems.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return { navItems, menuItems, all };
|
||||
}, [links, githubUrl]);
|
||||
}
|
||||
|
||||
export type * from '@fumadocs/ui/link-item';
|
||||
|
||||
Reference in New Issue
Block a user