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>
);
}
|