estim_control/src/Layout.tsx
2025-03-20 11:20:14 +08:00

71 lines
2.3 KiB
TypeScript

import { Icon } from '@iconify/react/dist/iconify.js';
import { platform } from '@tauri-apps/plugin-os';
import cx from 'clsx';
import { FC, ReactNode } from 'react';
import { createPortal } from 'react-dom';
import { NavLink, Outlet } from 'react-router-dom';
import styles from './Layout.module.css';
import { defaultIconProps } from './icons/shared-props';
import StateBar from './page-components/state-bar/StateBar';
type FunctionLinkProps = {
name: string;
url: string;
end?: boolean;
children?: ReactNode;
};
const FunctionLink: FC<FunctionLinkProps> = ({ name, url, end, children }) => {
return (
<NavLink
to={url}
className={({ isActive }) =>
cx(styles.route_link, isActive ? styles.active : styles.inactive)
}
end={end}>
<div className={styles.filled}>{children}</div>
<div className={styles.name}>{name}</div>
</NavLink>
);
};
const Layout: FC = () => {
const os = platform();
return (
<main className={styles.layout}>
<header className={cx({ [styles.mac_titlebar]: os === 'macos' })}>
<h1>ESTIM Remote</h1>
<StateBar />
</header>
<section>
<menu>
<FunctionLink name="Device" url="/" end>
<Icon icon="material-symbols-light:device-unknown" {...defaultIconProps} />
</FunctionLink>
<FunctionLink name="Play" url="/play">
<Icon icon="material-symbols-light:motion-play" {...defaultIconProps} />
</FunctionLink>
<FunctionLink name="Pattern Library" url="/library">
<Icon icon="material-symbols-light:menu-book" {...defaultIconProps} />
</FunctionLink>
<FunctionLink name="Pattern Editor" url="/pattern-editor">
<Icon icon="material-symbols-light:movie-edit" {...defaultIconProps} />
</FunctionLink>
<FunctionLink name="Settings" url="/settings">
<Icon icon="material-symbols-light:settings" {...defaultIconProps} />
</FunctionLink>
</menu>
<div className={styles.main_content}>
<Outlet />
</div>
</section>
{createPortal(
<div data-tauri-drag-region className={styles.window_move_handler} />,
document.body,
)}
</main>
);
};
export default Layout;