aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/components/AppLayout.tsx
blob: 9c93302a61d3fde11404fd14075c5ce7ef2f3d6f (plain)
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
import { useLayoutEffect, useState } from 'react'
import { Outlet, useLocation } from 'react-router-dom'
import { AppShell } from '@astryxdesign/core/AppShell'
import { Icon } from '@astryxdesign/core/Icon'
import { IconButton } from '@astryxdesign/core/IconButton'
import { NavIcon } from '@astryxdesign/core/NavIcon'
import { SideNav, SideNavItem, SideNavSection } from '@astryxdesign/core/SideNav'
import { TopNav, TopNavHeading } from '@astryxdesign/core/TopNav'
import { Moon, Sparkles, Sun } from 'lucide-react'
import { isRouteActive, navRoutes } from '../app-routes'
import { useThemeMode } from '../theme/useThemeMode'

export function AppLayout() {
  const { pathname } = useLocation()
  const { mode, toggleMode } = useThemeMode()
  const [isMobileNavOpen, setIsMobileNavOpen] = useState(false)

  useLayoutEffect(() => {
    const main = document.getElementById('astryx-app-shell-main')
    if (main) main.scrollTop = 0
    window.scrollTo(0, 0)
  }, [pathname])

  const nextMode = mode === 'light' ? 'dark' : 'light'

  return (
    <AppShell
      height="fill"
      contentPadding={0}
      mobileNav={{
        isOpen: isMobileNavOpen,
        onOpenChange: setIsMobileNavOpen,
      }}
      topNav={
        <TopNav
          label="主导航"
          heading={
            <TopNavHeading
              heading="Astryx 起始模板"
              headingHref="/"
              logo={
                <NavIcon
                  icon={<Icon icon={Sparkles} size="sm" color="inherit" />}
                />
              }
            />
          }
          endContent={
            <IconButton
              label={`切换到${nextMode === 'dark' ? '深色' : '浅色'}主题`}
              tooltip={`切换到${nextMode === 'dark' ? '深色' : '浅色'}主题`}
              variant="ghost"
              icon={<Icon icon={mode === 'light' ? Moon : Sun} />}
              onClick={toggleMode}
            />
          }
        />
      }
      sideNav={
        <SideNav collapsible>
          <SideNavSection title="探索">
            {navRoutes.map(({ label, path, icon }) => (
              <SideNavItem
                key={path}
                label={label}
                href={path}
                icon={icon}
                selectedIcon={icon}
                isSelected={isRouteActive(path, pathname)}
                onClick={() => setIsMobileNavOpen(false)}
              />
            ))}
          </SideNavSection>
        </SideNav>
      }>
      <Outlet />
    </AppShell>
  )
}