88 lines
2.4 KiB
TypeScript
88 lines
2.4 KiB
TypeScript
import { makeStyles, tokens, FluentProvider, webLightTheme, webDarkTheme, Toaster, useId } from '@fluentui/react-components';
|
|
import type { ReactNode } from 'react';
|
|
import { Outlet } from 'react-router-dom';
|
|
import Header from './components/Header';
|
|
import Sidebar from './components/Sidebar';
|
|
import Footer from './components/Footer';
|
|
import StatusDisplay from '../components/StatusDisplay';
|
|
import { LayoutProvider, useLayout } from '../context/LayoutContext';
|
|
|
|
const useStyles = makeStyles({
|
|
root: {
|
|
position: 'fixed',
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
backgroundColor: tokens.colorNeutralBackground2,
|
|
overflow: 'hidden',
|
|
height: '100vh',
|
|
},
|
|
container: {
|
|
display: 'flex',
|
|
flex: '1 1 auto',
|
|
overflow: 'hidden',
|
|
height: 'calc(100vh - 64px)', // 减去 Header 的高度
|
|
position: 'relative',
|
|
},
|
|
content: {
|
|
flex: '1 1 auto',
|
|
padding: '20px',
|
|
overflowY: 'auto',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'center',
|
|
height: '100%',
|
|
width: '100%',
|
|
minHeight: 0,
|
|
boxSizing: 'border-box',
|
|
},
|
|
rightPanel: {
|
|
width: '240px',
|
|
flexShrink: 0,
|
|
borderLeft: `1px solid ${tokens.colorNeutralStroke1}`,
|
|
padding: '20px',
|
|
backgroundColor: tokens.colorNeutralBackground1,
|
|
overflowY: 'auto',
|
|
'@media (max-width: 768px)': {
|
|
display: 'none',
|
|
},
|
|
}
|
|
});
|
|
|
|
const LayoutContent = ({ toasterId, imageViewer }: { toasterId: string; imageViewer?: ReactNode }) => {
|
|
const styles = useStyles();
|
|
const { isDarkMode } = useLayout();
|
|
|
|
return (
|
|
<FluentProvider theme={isDarkMode ? webDarkTheme : webLightTheme}>
|
|
<div className={styles.root}>
|
|
<Header />
|
|
<div className={styles.container}>
|
|
<Sidebar />
|
|
<main className={styles.content}>
|
|
<Outlet />
|
|
</main>
|
|
<aside className={styles.rightPanel}>
|
|
<StatusDisplay />
|
|
</aside>
|
|
</div>
|
|
<Footer />
|
|
<Toaster toasterId={toasterId} position="top-end" />
|
|
{imageViewer}
|
|
</div>
|
|
</FluentProvider>
|
|
);
|
|
};
|
|
|
|
export const MainLayout = ({ imageViewer }: { imageViewer?: ReactNode }) => {
|
|
const toasterId = useId('toaster');
|
|
return (
|
|
<LayoutProvider toasterId={toasterId}>
|
|
<LayoutContent toasterId={toasterId} imageViewer={imageViewer} />
|
|
</LayoutProvider>
|
|
);
|
|
};
|