File size: 1,407 Bytes
d0c18f0
 
 
 
 
a43ac26
 
 
 
d0c18f0
a43ac26
d0c18f0
 
a43ac26
 
d0c18f0
a43ac26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9ef8a08
 
a43ac26
 
 
9ef8a08
 
 
a43ac26
 
 
 
 
 
 
d0c18f0
 
a43ac26
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
import { Outlet } from 'react-router-dom';
import { Navbar } from './Navbar';
import { Sidebar } from './Sidebar';
import { useUIStore } from '@stores/uiStore';

/**
 * 控制台布局 Shell
 * 固定侧栏、顶部导航栏、主工作区、移动端抽屉
 */
export function Layout() {
  const { sidebarOpen, setSidebarOpen } = useUIStore();

  return (
    <div className="min-h-screen bg-console-surface-base">
      {/* 顶部导航栏 */}
      <Navbar />

      <div className="flex">
        {/* 侧边栏:桌面端固定,移动端抽屉 */}
        <div
          className={`
            fixed inset-y-0 left-0 z-40 w-56 transform transition-transform duration-200 ease-out
            md:sticky md:top-12 md:h-[calc(100vh-3rem)] md:translate-x-0
            ${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
          `}
          role="navigation"
          aria-label="控制台侧边栏"
        >
          <Sidebar />
        </div>

        {/* 移动端遮罩层 */}
        {sidebarOpen && (
          <div
            className="fixed inset-0 z-30 bg-black/50 md:hidden"
            onClick={() => setSidebarOpen(false)}
            aria-hidden="true"
          />
        )}

        {/* 主内容区域 */}
        <main className="flex-1 min-w-0">
          <div className="p-6 lg:p-8">
            <Outlet />
          </div>
        </main>
      </div>
    </div>
  );
}