feat: add hybrid display for small and big devices.
This commit is contained in:
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user