feat: add hybrid display for small and big devices.

This commit is contained in:
2026-04-20 16:57:44 +02:00
parent 8079162117
commit 3984b8684f

View File

@@ -1,41 +1,122 @@
import { useMemo, useState } from "react";
import type { MouseEvent } from "react";
import {
AppBar,
Box,
Button,
Drawer,
List,
ListItem,
ListItemButton,
ListItemText,
Menu,
MenuItem,
Toolbar,
Typography
} from "@mui/material";
import { TOOLS } from "./tools/toolRegistry";
const App = () => {
const [activeToolId, setActiveToolId] = useState<string>(TOOLS[0]?.id ?? "");
const [toolsAnchorEl, setToolsAnchorEl] = useState<null | HTMLElement>(null);
const [helpOpen, setHelpOpen] = useState(false);
const activeTool = useMemo(
() => TOOLS.find((tool) => tool.id === activeToolId) ?? TOOLS[0],
[activeToolId]
);
const toolsMenuOpen = Boolean(toolsAnchorEl);
const openToolsMenu = (event: MouseEvent<HTMLButtonElement>) => {
setToolsAnchorEl(event.currentTarget);
};
const closeToolsMenu = () => {
setToolsAnchorEl(null);
};
const selectTool = (toolId: string) => {
setActiveToolId(toolId);
closeToolsMenu();
};
return (
<Box sx={{ minHeight: "100vh", bgcolor: "background.default" }}>
<AppBar
position="sticky"
color="default"
elevation={0}
sx={{ borderBottom: 1, borderColor: "divider", display: { xs: "block", md: "none" } }}
>
<Toolbar sx={{ gap: 1 }}>
<Button
variant="text"
color="inherit"
onClick={openToolsMenu}
aria-controls={toolsMenuOpen ? "tools-menu" : undefined}
aria-haspopup="true"
aria-expanded={toolsMenuOpen ? "true" : undefined}
>
Tools
</Button>
<Typography sx={{ flexGrow: 1, fontWeight: 500 }} noWrap>
{activeTool?.name ?? "Tool"}
</Typography>
<Button variant="text" color="inherit" onClick={() => setHelpOpen(true)}>
Help
</Button>
</Toolbar>
</AppBar>
<Menu id="tools-menu" anchorEl={toolsAnchorEl} open={toolsMenuOpen} onClose={closeToolsMenu}>
{TOOLS.map((tool) => (
<MenuItem key={tool.id} selected={tool.id === activeTool?.id} onClick={() => selectTool(tool.id)}>
{tool.name}
</MenuItem>
))}
</Menu>
<Drawer anchor="right" open={helpOpen} onClose={() => setHelpOpen(false)}>
<Box sx={{ width: { xs: "85vw", sm: 360 }, p: 3 }}>
<Typography variant="h6" sx={{ mb: 1 }}>
Help
</Typography>
{activeTool?.helpContent ? (
<Box sx={{ color: "text.secondary", whiteSpace: "pre-wrap" }}>{activeTool.helpContent}</Box>
) : (
<Typography color="text.secondary">No help available for this tool.</Typography>
)}
<List sx={{ mt: 2 }}>
<ListItemButton onClick={() => setHelpOpen(false)}>
<ListItemText primary="Close" />
</ListItemButton>
</List>
</Box>
</Drawer>
<Box sx={{ display: { xs: "block", md: "none" }, p: 2 }}>{activeTool ? activeTool.render() : null}</Box>
<Box
sx={{
display: { xs: "none", md: "grid" },
minHeight: "100vh",
display: "grid",
gridTemplateColumns: {
xs: "1fr",
md: "240px minmax(0, 1fr)",
lg: "240px minmax(0, 1fr) 360px"
},
gap: { xs: 2, md: 0 },
p: { xs: 2, md: 0 }
gap: 0,
p: 0
}}
>
<Box
component="aside"
sx={{
py: { xs: 0, md: 3 },
pl: { xs: 0, md: 3 },
pr: { xs: 0, md: 1 }
py: 3,
pl: 3,
pr: 1
}}
>
<Typography variant="h6" sx={{ mb: 1 }}>
@@ -86,13 +167,13 @@ const App = () => {
</List>
</Box>
<Box sx={{ minWidth: 0, p: { xs: 0, md: 3 } }}>{activeTool ? activeTool.render() : null}</Box>
<Box sx={{ minWidth: 0, p: 3 }}>{activeTool ? activeTool.render() : null}</Box>
<Box
component="aside"
sx={{
gridColumn: { xs: "1", md: "2", lg: "auto" },
p: { xs: 2, md: 3 }
gridColumn: { md: "2", lg: "auto" },
p: 3
}}
>
<Typography variant="h6" sx={{ mb: 1 }}>
@@ -105,6 +186,7 @@ const App = () => {
)}
</Box>
</Box>
</Box>
);
};