init: initial commit
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import { useState } from 'react'
|
||||
import { Link, NavLink } from 'react-router-dom'
|
||||
import { Menu, Moon, Sun, X } from 'lucide-react'
|
||||
import { useTheme } from '@/components/theme-provider'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const NAV_ITEMS = [
|
||||
{ label: '产品', to: '/', end: true },
|
||||
{ label: '功能', to: '/#features' },
|
||||
{ label: '架构', to: '/#architecture' },
|
||||
{ label: '博客', to: '/blog' },
|
||||
]
|
||||
|
||||
function ThemeToggle() {
|
||||
const { resolved, setTheme } = useTheme()
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
aria-label={resolved === 'dark' ? '切换到浅色主题' : '切换到深色主题'}
|
||||
onClick={() => setTheme(resolved === 'dark' ? 'light' : 'dark')}
|
||||
className="flex size-8 items-center justify-center rounded-full border border-hairline-strong text-ink-2 transition-colors hover:border-accent hover:text-accent-ink"
|
||||
>
|
||||
{resolved === 'dark' ? (
|
||||
<Sun className="size-4" />
|
||||
) : (
|
||||
<Moon className="size-4" />
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
export function SiteHeader() {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
const links = NAV_ITEMS.map((item) =>
|
||||
item.to.includes('#') ? (
|
||||
<a
|
||||
key={item.to}
|
||||
href={item.to}
|
||||
onClick={() => setOpen(false)}
|
||||
className="text-sm text-ink-2 transition-colors hover:text-ink"
|
||||
>
|
||||
{item.label}
|
||||
</a>
|
||||
) : (
|
||||
<NavLink
|
||||
key={item.to}
|
||||
to={item.to}
|
||||
end={item.end}
|
||||
onClick={() => setOpen(false)}
|
||||
className={({ isActive }) =>
|
||||
cn(
|
||||
'text-sm transition-colors hover:text-ink',
|
||||
isActive ? 'text-ink' : 'text-ink-2',
|
||||
)
|
||||
}
|
||||
>
|
||||
{item.label}
|
||||
</NavLink>
|
||||
),
|
||||
)
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-40 border-b border-hairline bg-ground/85 backdrop-blur">
|
||||
<div className="mx-auto flex h-16 max-w-6xl items-center justify-between px-6 lg:px-10">
|
||||
<Link to="/" className="font-mono text-[15px] font-semibold">
|
||||
sundynix <em className="not-italic text-accent">agentix</em>
|
||||
</Link>
|
||||
|
||||
<nav className="hidden items-center gap-7 md:flex">
|
||||
{links}
|
||||
<ThemeToggle />
|
||||
<Link
|
||||
to="/download"
|
||||
className="rounded-[7px] bg-accent px-4 py-1.5 text-[13px] font-medium text-ground transition-opacity hover:opacity-90"
|
||||
>
|
||||
下载桌面版
|
||||
</Link>
|
||||
</nav>
|
||||
|
||||
<div className="flex items-center gap-3 md:hidden">
|
||||
<ThemeToggle />
|
||||
<button
|
||||
type="button"
|
||||
aria-label={open ? '关闭菜单' : '打开菜单'}
|
||||
onClick={() => setOpen((v) => !v)}
|
||||
className="flex size-8 items-center justify-center text-ink-2"
|
||||
>
|
||||
{open ? <X className="size-5" /> : <Menu className="size-5" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{open && (
|
||||
<nav className="flex flex-col gap-4 border-t border-hairline px-6 py-5 md:hidden">
|
||||
{links}
|
||||
<Link
|
||||
to="/download"
|
||||
onClick={() => setOpen(false)}
|
||||
className="w-fit rounded-[7px] bg-accent px-4 py-1.5 text-[13px] font-medium text-ground"
|
||||
>
|
||||
下载桌面版
|
||||
</Link>
|
||||
</nav>
|
||||
)}
|
||||
</header>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user