From 5b7ccf0b671e2999b62befc729a3e517a0433728 Mon Sep 17 00:00:00 2001 From: Bertrand Yuan Date: Mon, 15 Dec 2025 23:48:10 +0800 Subject: initial commit -- the front-end prototype The initial code is base on Anirudh's work. More to see at: https://github.com/techwithanirudh/shadcn-blog Therefore, the code in this commit is under MIT license. --- src/components/sections/header/index.tsx | 174 +++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 src/components/sections/header/index.tsx (limited to 'src/components/sections/header/index.tsx') diff --git a/src/components/sections/header/index.tsx b/src/components/sections/header/index.tsx new file mode 100644 index 0000000..4280e01 --- /dev/null +++ b/src/components/sections/header/index.tsx @@ -0,0 +1,174 @@ +import Link from 'fumadocs-core/link'; +import { + LanguageToggle, + LanguageToggleText, +} from 'fumadocs-ui/components/layout/language-toggle'; +import { + LargeSearchToggle, + SearchToggle, +} from 'fumadocs-ui/components/layout/search-toggle'; +import { NavigationMenuList } from 'fumadocs-ui/components/ui/navigation-menu'; +import type { HomeLayoutProps } from 'fumadocs-ui/layouts/home'; +import { + NavbarLink, + NavbarMenu, + NavbarMenuContent, + NavbarMenuTrigger, +} from 'fumadocs-ui/layouts/home/navbar'; +import type { LinkItemType } from 'fumadocs-ui/layouts/links'; +import { SearchOnly } from 'fumadocs-ui/provider'; +import { ChevronDown, Languages } from 'lucide-react'; +import { ThemeToggle } from '../../theme-toggle'; +import { Menu, MenuContent, MenuLinkItem, MenuTrigger } from './menu'; +import { Navbar, NavbarMenuLink } from './navbar'; + +export const Header = ({ + nav: { enableSearch = true, ...nav } = {}, + i18n = false, + finalLinks, +}: HomeLayoutProps & { + finalLinks: LinkItemType[]; +}) => { + const navItems = finalLinks.filter((item) => + ['nav', 'all'].includes(item.on ?? 'all'), + ); + const menuItems = finalLinks.filter((item) => + ['menu', 'all'].includes(item.on ?? 'all'), + ); + + return ( + + + {nav.title} + + {nav.children} + + {navItems + .filter((item) => !isSecondary(item)) + .map((item, i) => ( + + ))} + +
+ {enableSearch ? ( + + + + + ) : null} + + {navItems.filter(isSecondary).map((item, i) => ( + + ))} + + + + + + {menuItems + .filter((item) => !isSecondary(item)) + .map((item, i) => ( + + ))} +
+ {menuItems.filter(isSecondary).map((item, i) => ( + + ))} +
+ {i18n ? ( + + + + + + ) : null} + +
+ +
+
+
+ ); +}; + +const NavbarLinkItem = ({ + item, + ...props +}: { + item: LinkItemType; + className?: string; +}) => { + if (item.type === 'custom') return
{item.children}
; + + if (item.type === 'menu') { + const children = item.items.map((child, j) => { + if (child.type === 'custom') + return
{child.children}
; + + const { banner, footer, ...rest } = child.menu ?? {}; + + return ( + + {banner ?? + (child.icon ? ( +
+ {child.icon} +
+ ) : null)} +

{child.text}

+ {child.description ? ( +

+ {child.description} +

+ ) : null} + {footer} +
+ ); + }); + + return ( + + + {item.url ? {item.text} : item.text} + + {children} + + ); + } + + return ( + + {item.type === 'icon' ? item.icon : item.text} + + ); +}; + +const isSecondary = (item: LinkItemType): boolean => { + return ( + ('secondary' in item && item.secondary === true) || item.type === 'icon' + ); +}; -- cgit v1.2.3