init: Init React Application
This commit is contained in:
67
src/widgets/Layout/index.tsx
Normal file
67
src/widgets/Layout/index.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import * as React from "react";
|
||||
import Box from "@mui/material/Box";
|
||||
import Toolbar from "@mui/material/Toolbar";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { Menu, ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { AppBar } from "./ui/AppBar";
|
||||
import { Drawer } from "./ui/Drawer";
|
||||
import { DrawerHeader } from "./ui/DrawerHeader";
|
||||
import { NavigationList } from "@features";
|
||||
|
||||
interface LayoutProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Layout: React.FC<LayoutProps> = ({ children }) => {
|
||||
const theme = useTheme();
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
const handleDrawerOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const handleDrawerClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ display: "flex" }}>
|
||||
<AppBar position="fixed" open={open}>
|
||||
<Toolbar>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
aria-label="open drawer"
|
||||
onClick={handleDrawerOpen}
|
||||
edge="start"
|
||||
sx={[
|
||||
{
|
||||
marginRight: 5,
|
||||
},
|
||||
open && { display: "none" },
|
||||
]}
|
||||
>
|
||||
<Menu />
|
||||
</IconButton>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Drawer variant="permanent" open={open}>
|
||||
<DrawerHeader>
|
||||
<IconButton onClick={handleDrawerClose}>
|
||||
{theme.direction === "rtl" ? (
|
||||
<ChevronRightIcon />
|
||||
) : (
|
||||
<ChevronLeftIcon />
|
||||
)}
|
||||
</IconButton>
|
||||
</DrawerHeader>
|
||||
<NavigationList open={open} />
|
||||
</Drawer>
|
||||
<Box component="main" sx={{ flexGrow: 1, p: 3 }}>
|
||||
<DrawerHeader />
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
27
src/widgets/Layout/ui/AppBar.tsx
Normal file
27
src/widgets/Layout/ui/AppBar.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { styled } from "@mui/material/styles";
|
||||
import MuiAppBar, {
|
||||
type AppBarProps as MuiAppBarProps,
|
||||
} from "@mui/material/AppBar";
|
||||
import { DRAWER_WIDTH } from "@shared";
|
||||
|
||||
interface AppBarProps extends MuiAppBarProps {
|
||||
open?: boolean;
|
||||
}
|
||||
|
||||
export const AppBar = styled(MuiAppBar, {
|
||||
shouldForwardProp: (prop) => prop !== "open",
|
||||
})<AppBarProps>(({ theme, open }) => ({
|
||||
zIndex: theme.zIndex.drawer + 1,
|
||||
transition: theme.transitions.create(["width", "margin"], {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen,
|
||||
}),
|
||||
...(open && {
|
||||
marginLeft: DRAWER_WIDTH,
|
||||
width: `calc(100% - ${DRAWER_WIDTH}px)`,
|
||||
transition: theme.transitions.create(["width", "margin"], {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
}),
|
||||
}));
|
||||
42
src/widgets/Layout/ui/Drawer.tsx
Normal file
42
src/widgets/Layout/ui/Drawer.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { styled } from "@mui/material/styles";
|
||||
import MuiDrawer from "@mui/material/Drawer";
|
||||
import type { Theme, CSSObject } from "@mui/material/styles";
|
||||
import { DRAWER_WIDTH } from "@shared";
|
||||
|
||||
const openedMixin = (theme: Theme): CSSObject => ({
|
||||
width: DRAWER_WIDTH,
|
||||
transition: theme.transitions.create("width", {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
overflowX: "hidden",
|
||||
});
|
||||
|
||||
const closedMixin = (theme: Theme): CSSObject => ({
|
||||
transition: theme.transitions.create("width", {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen,
|
||||
}),
|
||||
overflowX: "hidden",
|
||||
width: `calc(${theme.spacing(7)} + 1px)`,
|
||||
[theme.breakpoints.up("sm")]: {
|
||||
width: `calc(${theme.spacing(8)} + 1px)`,
|
||||
},
|
||||
});
|
||||
|
||||
export const Drawer = styled(MuiDrawer, {
|
||||
shouldForwardProp: (prop) => prop !== "open",
|
||||
})(({ theme, open }) => ({
|
||||
width: DRAWER_WIDTH,
|
||||
flexShrink: 0,
|
||||
whiteSpace: "nowrap",
|
||||
boxSizing: "border-box",
|
||||
...(open && {
|
||||
...openedMixin(theme),
|
||||
"& .MuiDrawer-paper": openedMixin(theme),
|
||||
}),
|
||||
...(!open && {
|
||||
...closedMixin(theme),
|
||||
"& .MuiDrawer-paper": closedMixin(theme),
|
||||
}),
|
||||
}));
|
||||
10
src/widgets/Layout/ui/DrawerHeader.tsx
Normal file
10
src/widgets/Layout/ui/DrawerHeader.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import { styled } from "@mui/material/styles";
|
||||
import type { Theme } from "@mui/material/styles";
|
||||
|
||||
export const DrawerHeader = styled("div")(({ theme }: { theme: Theme }) => ({
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-end",
|
||||
padding: theme.spacing(0, 1),
|
||||
...theme.mixins.toolbar,
|
||||
}));
|
||||
Reference in New Issue
Block a user