diff --git a/.eslintrc b/.eslintrc
index bb0c4e1..eb80a2e 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -99,6 +99,11 @@
"**/.eslintrc.[j|t]s"
],
"optionalDependencies": false
+ }],
+ "react/function-component-definition": [
+ "error", {
+ "namedComponents": "arrow-function",
+ "unnamedComponents": "arrow-function"
}]
}
}
diff --git a/offline_node_modules/@react-spring-animated-npm-9.7.3-4aff527e22-5151da4fa7.zip b/offline_node_modules/@react-spring-animated-npm-9.7.3-4aff527e22-5151da4fa7.zip
new file mode 100644
index 0000000..6373e32
Binary files /dev/null and b/offline_node_modules/@react-spring-animated-npm-9.7.3-4aff527e22-5151da4fa7.zip differ
diff --git a/offline_node_modules/@react-spring-core-npm-9.7.3-00b8dd52b3-e28c05de84.zip b/offline_node_modules/@react-spring-core-npm-9.7.3-00b8dd52b3-e28c05de84.zip
new file mode 100644
index 0000000..9b8cacc
Binary files /dev/null and b/offline_node_modules/@react-spring-core-npm-9.7.3-00b8dd52b3-e28c05de84.zip differ
diff --git a/offline_node_modules/@react-spring-shared-npm-9.7.3-cefcfdc40d-afb03ed28c.zip b/offline_node_modules/@react-spring-shared-npm-9.7.3-cefcfdc40d-afb03ed28c.zip
new file mode 100644
index 0000000..98b9eaa
Binary files /dev/null and b/offline_node_modules/@react-spring-shared-npm-9.7.3-cefcfdc40d-afb03ed28c.zip differ
diff --git a/offline_node_modules/@react-spring-types-npm-9.7.3-f9de91ab6e-d645044f3c.zip b/offline_node_modules/@react-spring-types-npm-9.7.3-f9de91ab6e-d645044f3c.zip
new file mode 100644
index 0000000..99c00b5
Binary files /dev/null and b/offline_node_modules/@react-spring-types-npm-9.7.3-f9de91ab6e-d645044f3c.zip differ
diff --git a/offline_node_modules/@react-spring-web-npm-9.7.3-95390d075a-a5b4847a29.zip b/offline_node_modules/@react-spring-web-npm-9.7.3-95390d075a-a5b4847a29.zip
new file mode 100644
index 0000000..17eb392
Binary files /dev/null and b/offline_node_modules/@react-spring-web-npm-9.7.3-95390d075a-a5b4847a29.zip differ
diff --git a/package.json b/package.json
index f88e1a2..7df13d9 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"@emotion/styled": "11.11.5",
"@mui/icons-material": "^5.15.19",
"@mui/material": "5.15.19",
+ "@react-spring/web": "9.7.3",
"classnames": "2.5.1",
"notistack": "3.0.1",
"prop-types": "15.8.1",
diff --git a/src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx b/src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx
index fe5b5aa..5798b35 100644
--- a/src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx
+++ b/src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx
@@ -1,11 +1,10 @@
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
import FormatListBulletedIcon from '@mui/icons-material/FormatListBulleted';
import PieChartIcon from '@mui/icons-material/PieChart';
-import { CircularProgress } from '@mui/material';
+import CircularProgress from '@mui/material/CircularProgress';
import { Suspense } from 'react';
import { createBrowserRouter, Navigate, RouterProvider as RRDRouterProvider } from 'react-router-dom';
-// todo lazy & access
import { AnalyzePage, AnalyzePageToolbar } from 'pages/AnalyzePage';
import { ErrorPage, ErrorPageToolbar } from 'pages/ErrorPage';
import { PaymentsPage, PaymentsPageToolbar } from 'pages/PaymentsPage';
diff --git a/src/pages/SchedulePage/ui/SchedulePage.spec.tsx b/src/pages/SchedulePage/ui/SchedulePage.spec.tsx
index dfb306d..9219e8d 100644
--- a/src/pages/SchedulePage/ui/SchedulePage.spec.tsx
+++ b/src/pages/SchedulePage/ui/SchedulePage.spec.tsx
@@ -1,4 +1,4 @@
-import { render, screen } from '@testing-library/react';
+import { render, screen, waitFor } from '@testing-library/react';
import { SchedulePage, SchedulePageToolbar } from 'pages/SchedulePage';
@@ -7,12 +7,15 @@ describe('Test SchedulePage', () => {
,
);
- test('should render correctly', () => {
+ test('should render correctly', async () => {
setup();
- const pageElem = screen.getByTestId('schedule-page');
- expect(pageElem).toBeVisible();
- expect(pageElem).toHaveTextContent('Schedule Page');
+ await waitFor(() => {
+ const pageElem = screen.getByTestId('schedule-page');
+ expect(pageElem).toBeVisible();
+ // eslint-disable-next-line testing-library/no-wait-for-multiple-assertions
+ expect(pageElem).toHaveTextContent('Schedule Page');
+ });
});
});
diff --git a/src/shared/hoc/withProvider/ui/withProvider.ui.tsx b/src/shared/hoc/withProvider/ui/withProvider.ui.tsx
index d4385c7..c7c14de 100644
--- a/src/shared/hoc/withProvider/ui/withProvider.ui.tsx
+++ b/src/shared/hoc/withProvider/ui/withProvider.ui.tsx
@@ -1,8 +1,5 @@
-// todo fix eslint
-
import type { FC, PropsWithChildren } from 'react';
-// eslint-disable-next-line react/function-component-definition
const withProvider = (Provider: FC) => (Component: FC) => (...params: T[]) => (
{/* @ts-ignore */}
diff --git a/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.spec.tsx b/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.spec.tsx
index f349181..59868c9 100644
--- a/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.spec.tsx
+++ b/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.spec.tsx
@@ -1,7 +1,7 @@
import { renderWithProvider } from '__spec__/custon-renders';
import PieChartIcon from '@mui/icons-material/PieChart';
-import { fireEvent, screen } from '@testing-library/react';
+import { fireEvent, screen, waitFor } from '@testing-library/react';
import AsideMenuLayout from './AsideMenuLayout.ui';
@@ -41,10 +41,6 @@ describe('Test AsideMenuLayout', () => {
}
data-testid="aside-menu-layout"
- DrawerSwitcherProps={{
- // @ts-ignore
- 'data-testid': 'drawer-switcher',
- }}
pages={pages}
Toolbar={}
/>,
@@ -58,18 +54,22 @@ describe('Test AsideMenuLayout', () => {
expect(layoutElem).toBeVisible();
});
- test('should render toolbar', () => {
+ test('should render toolbar', async () => {
setup();
- const toolbarElem = screen.getByText('Test Toolbar');
- expect(toolbarElem).toBeVisible();
+ await waitFor(() => {
+ const toolbarElem = screen.getByText('Test Toolbar');
+ expect(toolbarElem).toBeVisible();
+ });
});
- test('should render content', () => {
+ test('should render content', async () => {
setup();
- const toolbarElem = screen.getByText('Test Content');
- expect(toolbarElem).toBeVisible();
+ await waitFor(() => {
+ const toolbarElem = screen.getByText('Test Content');
+ expect(toolbarElem).toBeVisible();
+ });
});
test('should render navigation routes', () => {
diff --git a/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.ui.tsx b/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.ui.tsx
index e94bc10..f2fdb6a 100644
--- a/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.ui.tsx
+++ b/src/widgets/AsideMenuLayout/ui/AsideMenuLayout.ui.tsx
@@ -1,104 +1,137 @@
-import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
-import MenuIcon from '@mui/icons-material/Menu';
+import { useMediaQuery } from '@mui/material';
import Box from '@mui/material/Box';
-import CssBaseline from '@mui/material/CssBaseline';
-import Divider from '@mui/material/Divider';
import List from '@mui/material/List';
-import { useState } from 'react';
+import { useTheme } from '@mui/material/styles';
+import Tooltip from '@mui/material/Tooltip';
+import { animated, useTransition } from '@react-spring/web';
+import { useContext } from 'react';
+import { useLocation } from 'react-router-dom';
-import AppBar from './components/AppBar';
-import Drawer from './components/Drawer';
-import DrawerHeader from './components/DrawerMenu';
-import DrawerSwitcher from './components/DrawerSwitcher';
-import MenuItem from './components/MenuItem/MenuItem.ui';
+import { DesktopAppBar, MobileAppBar } from './components/AppBar';
+import { AsideMenuContext, AsideMenuProvider } from './components/AsideMenuProvider';
+import { DesktopDrawer } from './components/DesktopDrawer';
+import { MenuItem } from './components/MenuItem';
+import { MobileDrawer } from './components/MobileDrawer';
-import type { MenuItemProps } from './components/MenuItem/MenuItem.ui';
+import type { MenuItemProps } from './components/MenuItem/ui/MenuItem.ui';
import type { BoxProps } from '@mui/material/Box/Box';
-import type {
- FC,
- ReactNode,
- DetailedHTMLProps,
- HTMLAttributes,
-} from 'react';
+import type { FC, ReactNode } from 'react';
-const drawerWidth = 250;
+export const DESKTOP_DRAWER_WIDTH = 250;
+export const MOBILE_DRAWER_WIDTH = 250;
-type AsideMenuLayoutProps = BoxProps & {
+export type AsideMenuLayoutProps = BoxProps & {
pages: MenuItemProps['page'][];
Content: ReactNode;
Toolbar?: ReactNode;
- DrawerSwitcherProps?: DetailedHTMLProps, HTMLDivElement>;
};
const AsideMenuLayout: FC = (props) => {
const {
pages,
Content,
Toolbar,
- DrawerSwitcherProps,
...restProps
} = props;
- const [isOpen, setIsOpen] = useState(true);
+ const { desktopDrawerOpen, setMobileDrawerOpen } = useContext(AsideMenuContext);
+ const theme = useTheme();
+ const isMobileView = useMediaQuery(theme.breakpoints.down('sm'));
- const handleDrawerOpen = () => {
- setIsOpen(true);
- };
- const handleDrawerClose = () => {
- setIsOpen(false);
- };
+ const location = useLocation();
+ const transitions = useTransition(location, {
+ from: { opacity: 0 },
+ enter: { opacity: 1 },
+ leave: { opacity: 0 },
+ unique: true,
+ reset: true,
+ });
+
+ const AnimatedContent = (
+ <>
+ {transitions((styles) => (
+
+ {Content}
+
+ ))}
+ >
+ );
+
+ const AnimatedToolBar = (
+ <>
+ {transitions((styles) => (
+
+ {Toolbar}
+
+ ))}
+ >
+ );
+
+ if (isMobileView) {
+ return (
+
+ {
+ Boolean(Toolbar) && (
+
+
+
+ {pages.map((page) => (
+
+
+
+ {AnimatedToolBar}
+
+ )
+ }
+
+
+ {AnimatedContent}
+
+
+ );
+ }
return (
-
-
-
-
-
- { isOpen ? : }
-
-
-
-
-
+
{pages.map((page) => (
-
- ))}
+ desktopDrawerOpen
+ ? (
+
+ )
+ : (
+
+
+
+ )))}
-
+
-
- {
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
- Toolbar
- ? (
- <>
-
- {Toolbar}
-
+
+ { Boolean(Toolbar) && (
+
+ {AnimatedToolBar}
+
+ )}
-
- >
- )
- : null
- }
-
- {Content}
+
+ {AnimatedContent}
+
);
};
-export default AsideMenuLayout;
+const withProvider = (Component: FC) => (props: AsideMenuLayoutProps) => (
+
+
+
+);
+
+export default withProvider(AsideMenuLayout);
diff --git a/src/widgets/AsideMenuLayout/ui/components/AppBar/index.tsx b/src/widgets/AsideMenuLayout/ui/components/AppBar/index.tsx
index 582417b..318a896 100644
--- a/src/widgets/AsideMenuLayout/ui/components/AppBar/index.tsx
+++ b/src/widgets/AsideMenuLayout/ui/components/AppBar/index.tsx
@@ -1,30 +1,21 @@
import MuiAppBar from '@mui/material/AppBar';
import { styled } from '@mui/material/styles';
-import type { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar/AppBar';
-
-type AppBarProps = MuiAppBarProps & {
- open?: boolean;
- drawerWidth: number;
-};
-
-const AppBar = styled(MuiAppBar, { shouldForwardProp: (prop) => !['open', 'drawerWidth'].includes(prop as string) })(
- ({ theme, open, drawerWidth }) => ({
+export const DesktopAppBar = styled(MuiAppBar)(
+ ({ theme }) => ({
transition: theme.transitions.create(['width', 'margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
- marginLeft: `calc(${theme.spacing(7)} + 1px)`,
- width: `calc(100% - calc(${theme.spacing(7)} + 1px))`,
- ...Boolean(open) && {
- marginLeft: drawerWidth,
- width: `calc(100% - ${drawerWidth}px)`,
- transition: theme.transitions.create(['width', 'margin'], {
- easing: theme.transitions.easing.sharp,
- duration: theme.transitions.duration.enteringScreen,
- }),
- },
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
}),
);
-export default AppBar;
+export const MobileAppBar = styled(MuiAppBar)(() => ({
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+ padding: '0 24px',
+}));
diff --git a/src/widgets/AsideMenuLayout/ui/components/AsideMenuProvider/index.ts b/src/widgets/AsideMenuLayout/ui/components/AsideMenuProvider/index.ts
new file mode 100644
index 0000000..0cfea09
--- /dev/null
+++ b/src/widgets/AsideMenuLayout/ui/components/AsideMenuProvider/index.ts
@@ -0,0 +1,2 @@
+export { default as AsideMenuProvider } from './ui/AsideMenuProvider.ui';
+export { AsideMenuContext } from './model/context';
diff --git a/src/widgets/AsideMenuLayout/ui/components/AsideMenuProvider/model/context.ts b/src/widgets/AsideMenuLayout/ui/components/AsideMenuProvider/model/context.ts
new file mode 100644
index 0000000..3856b8d
--- /dev/null
+++ b/src/widgets/AsideMenuLayout/ui/components/AsideMenuProvider/model/context.ts
@@ -0,0 +1,10 @@
+import { createContext } from 'react';
+
+export type AsideMenuContextType = {
+ desktopDrawerOpen: boolean;
+ setDesktopDrawerOpen: (isOpen: boolean) => void;
+ mobileDrawerOpen: boolean;
+ setMobileDrawerOpen: (isOpen: boolean) => void;
+};
+
+export const AsideMenuContext = createContext({} as AsideMenuContextType);
diff --git a/src/widgets/AsideMenuLayout/ui/components/AsideMenuProvider/ui/AsideMenuProvider.ui.tsx b/src/widgets/AsideMenuLayout/ui/components/AsideMenuProvider/ui/AsideMenuProvider.ui.tsx
new file mode 100644
index 0000000..01e59ae
--- /dev/null
+++ b/src/widgets/AsideMenuLayout/ui/components/AsideMenuProvider/ui/AsideMenuProvider.ui.tsx
@@ -0,0 +1,31 @@
+import { useMemo, useState } from 'react';
+
+import { AsideMenuContext, type AsideMenuContextType } from '../model/context';
+
+import type { FC, ReactNode } from 'react';
+
+type AsideMenuProviderProps = {
+ children: ReactNode;
+};
+const AsideMenuProvider: FC = (props) => {
+ const { children } = props;
+
+ // todo desktop from default value localstorage
+ const [desktopDrawerOpen, setDesktopDrawerOpen] = useState(true);
+ const [mobileDrawerOpen, setMobileDrawerOpen] = useState(false);
+
+ const value = useMemo(() => ({
+ desktopDrawerOpen,
+ setDesktopDrawerOpen,
+ mobileDrawerOpen,
+ setMobileDrawerOpen,
+ }), [desktopDrawerOpen, mobileDrawerOpen]);
+
+ return (
+
+ {children}
+
+ );
+};
+
+export default AsideMenuProvider;
diff --git a/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/index.ts b/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/index.ts
new file mode 100644
index 0000000..37f7bda
--- /dev/null
+++ b/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/index.ts
@@ -0,0 +1,2 @@
+export type { DesktopDrawerProps } from './ui/DesktopDrawer.ui';
+export { default as DesktopDrawer } from './ui/DesktopDrawer.ui';
diff --git a/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/DesktopDrawer.ui.tsx b/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/DesktopDrawer.ui.tsx
new file mode 100644
index 0000000..01883b0
--- /dev/null
+++ b/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/DesktopDrawer.ui.tsx
@@ -0,0 +1,53 @@
+import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
+import MenuIcon from '@mui/icons-material/Menu';
+import Divider from '@mui/material/Divider';
+import { useContext } from 'react';
+
+import { AsideMenuContext } from '../../AsideMenuProvider';
+
+import Drawer from './components/Drawer';
+import DrawerHeader from './components/DrawerMenu';
+import DrawerSwitcher from './components/DrawerSwitcher';
+
+import type { FC, ReactNode } from 'react';
+
+export type DesktopDrawerProps = {
+ width: number;
+ children: ReactNode;
+};
+
+const DesktopDrawer: FC = (props) => {
+ const {
+ width,
+ children,
+ } = props;
+
+ const { desktopDrawerOpen, setDesktopDrawerOpen } = useContext(AsideMenuContext);
+
+ const handleDrawerOpen = () => {
+ setDesktopDrawerOpen(true);
+ };
+ const handleDrawerClose = () => {
+ setDesktopDrawerOpen(false);
+ };
+
+ return (
+
+
+
+ { desktopDrawerOpen ? : }
+
+
+
+
+
+ {children}
+
+ );
+};
+
+export default DesktopDrawer;
diff --git a/src/widgets/AsideMenuLayout/ui/components/Drawer/index.tsx b/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/components/Drawer/index.tsx
similarity index 70%
rename from src/widgets/AsideMenuLayout/ui/components/Drawer/index.tsx
rename to src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/components/Drawer/index.tsx
index f09dbcd..e8b0ad1 100644
--- a/src/widgets/AsideMenuLayout/ui/components/Drawer/index.tsx
+++ b/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/components/Drawer/index.tsx
@@ -3,11 +3,11 @@ import { type CSSObject, styled, type Theme } from '@mui/material/styles';
type DrawerProps = {
open: boolean;
- drawerWidth: number;
+ width: number;
};
-const openedMixin = (theme: Theme, { drawerWidth }: Pick): CSSObject => ({
- width: drawerWidth,
+const openedMixin = (theme: Theme, { width }: Pick): CSSObject => ({
+ width,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
@@ -24,15 +24,15 @@ const closedMixin = (theme: Theme): CSSObject => ({
width: `calc(${theme.spacing(8)} + 1px)`,
});
-const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => !['open', 'drawerWidth'].includes(prop as string) })(
- ({ theme, open, drawerWidth }) => ({
- width: drawerWidth,
+const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => !['open', 'width'].includes(prop as string) })(
+ ({ theme, open, width }) => ({
+ width,
flexShrink: 0,
whiteSpace: 'nowrap',
boxSizing: 'border-box',
...open && {
- ...openedMixin(theme, { drawerWidth }),
- '& .MuiDrawer-paper': openedMixin(theme, { drawerWidth }),
+ ...openedMixin(theme, { width }),
+ '& .MuiDrawer-paper': openedMixin(theme, { width }),
},
...!open && {
...closedMixin(theme),
diff --git a/src/widgets/AsideMenuLayout/ui/components/DrawerMenu/index.tsx b/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/components/DrawerMenu/index.tsx
similarity index 100%
rename from src/widgets/AsideMenuLayout/ui/components/DrawerMenu/index.tsx
rename to src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/components/DrawerMenu/index.tsx
diff --git a/src/widgets/AsideMenuLayout/ui/components/DrawerSwitcher/index.tsx b/src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/components/DrawerSwitcher/index.tsx
similarity index 100%
rename from src/widgets/AsideMenuLayout/ui/components/DrawerSwitcher/index.tsx
rename to src/widgets/AsideMenuLayout/ui/components/DesktopDrawer/ui/components/DrawerSwitcher/index.tsx
diff --git a/src/widgets/AsideMenuLayout/ui/components/MenuItem/index.ts b/src/widgets/AsideMenuLayout/ui/components/MenuItem/index.ts
new file mode 100644
index 0000000..4a6ccb6
--- /dev/null
+++ b/src/widgets/AsideMenuLayout/ui/components/MenuItem/index.ts
@@ -0,0 +1 @@
+export { default as MenuItem } from './ui/MenuItem.ui';
diff --git a/src/widgets/AsideMenuLayout/ui/components/MenuItem/MenuItem.spec.tsx b/src/widgets/AsideMenuLayout/ui/components/MenuItem/ui/MenuItem.spec.tsx
similarity index 100%
rename from src/widgets/AsideMenuLayout/ui/components/MenuItem/MenuItem.spec.tsx
rename to src/widgets/AsideMenuLayout/ui/components/MenuItem/ui/MenuItem.spec.tsx
diff --git a/src/widgets/AsideMenuLayout/ui/components/MenuItem/MenuItem.ui.tsx b/src/widgets/AsideMenuLayout/ui/components/MenuItem/ui/MenuItem.ui.tsx
similarity index 90%
rename from src/widgets/AsideMenuLayout/ui/components/MenuItem/MenuItem.ui.tsx
rename to src/widgets/AsideMenuLayout/ui/components/MenuItem/ui/MenuItem.ui.tsx
index b46e5db..bfc057a 100644
--- a/src/widgets/AsideMenuLayout/ui/components/MenuItem/MenuItem.ui.tsx
+++ b/src/widgets/AsideMenuLayout/ui/components/MenuItem/ui/MenuItem.ui.tsx
@@ -4,10 +4,11 @@ import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import { styled, useTheme } from '@mui/material/styles';
import Typography from '@mui/material/Typography';
+import { forwardRef } from 'react';
import { NavLink as RRDNavLink } from 'react-router-dom';
import type { ListItemProps } from '@mui/material/ListItem/ListItem';
-import type { FC, ReactNode } from 'react';
+import type { ReactNode } from 'react';
import type { NavLinkProps } from 'react-router-dom';
const NavLink = styled(RRDNavLink)(({ theme }) => ({
@@ -26,7 +27,7 @@ export type MenuItemProps = ListItemProps & {
NavLinkProps?: NavLinkProps;
};
-const MenuItem: FC = (props) => {
+const MenuItem = forwardRef((props, ref) => {
const {
page,
isOpen = true,
@@ -36,7 +37,7 @@ const MenuItem: FC = (props) => {
const theme = useTheme();
return (
-
+
{({ isActive }) => (
= (props) => {
);
-};
+});
export default MenuItem;
diff --git a/src/widgets/AsideMenuLayout/ui/components/MobileDrawer/index.ts b/src/widgets/AsideMenuLayout/ui/components/MobileDrawer/index.ts
new file mode 100644
index 0000000..d8563e5
--- /dev/null
+++ b/src/widgets/AsideMenuLayout/ui/components/MobileDrawer/index.ts
@@ -0,0 +1 @@
+export { default as MobileDrawer } from './ui/MobileDrawer.ui';
diff --git a/src/widgets/AsideMenuLayout/ui/components/MobileDrawer/ui/MobileDrawer.ui.tsx b/src/widgets/AsideMenuLayout/ui/components/MobileDrawer/ui/MobileDrawer.ui.tsx
new file mode 100644
index 0000000..abdaad8
--- /dev/null
+++ b/src/widgets/AsideMenuLayout/ui/components/MobileDrawer/ui/MobileDrawer.ui.tsx
@@ -0,0 +1,56 @@
+import MenuIcon from '@mui/icons-material/Menu';
+import MuiDrawer from '@mui/material/Drawer';
+import IconButton from '@mui/material/IconButton';
+import { useContext } from 'react';
+
+import { AsideMenuContext } from '../../AsideMenuProvider';
+
+import type { FC, ReactNode } from 'react';
+
+type MobileDrawerProps = {
+ children: ReactNode;
+ width: number;
+
+ onOpen?: () => void;
+ onClose?: () => void;
+};
+
+const MobileDrawer: FC = (props) => {
+ const {
+ children,
+ width,
+ onOpen,
+ onClose,
+ } = props;
+
+ const { mobileDrawerOpen, setMobileDrawerOpen } = useContext(AsideMenuContext);
+
+ const handleDrawerOpen = () => {
+ setMobileDrawerOpen(true);
+ onOpen?.();
+ };
+
+ const handleDrawerClose = () => {
+ setMobileDrawerOpen(false);
+ onClose?.();
+ };
+
+ return (
+ <>
+
+
+
+
+
+ {children}
+
+ >
+
+ );
+};
+
+export default MobileDrawer;
diff --git a/yarn.lock b/yarn.lock
index 1da2e33..6a8414d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4496,6 +4496,64 @@ __metadata:
languageName: node
linkType: hard
+"@react-spring/animated@npm:~9.7.3":
+ version: 9.7.3
+ resolution: "@react-spring/animated@npm:9.7.3"
+ dependencies:
+ "@react-spring/shared": "npm:~9.7.3"
+ "@react-spring/types": "npm:~9.7.3"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ checksum: 10c0/5151da4fa7da010bb2edbee05871aa7a4aea8763fe617389d17605810aa0dd817374205e5fb3930b650f4a7f25fcdf23205fdfb7365686ff75888bdfd0b39839
+ languageName: node
+ linkType: hard
+
+"@react-spring/core@npm:~9.7.3":
+ version: 9.7.3
+ resolution: "@react-spring/core@npm:9.7.3"
+ dependencies:
+ "@react-spring/animated": "npm:~9.7.3"
+ "@react-spring/shared": "npm:~9.7.3"
+ "@react-spring/types": "npm:~9.7.3"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ checksum: 10c0/e28c05de8435bf2eaf8481f8acdf093909d4be9881a9a854c51dfac7c2d5562088d0fb2ce04e2f07e1b3bf621d8da3ab57bf6fedb4fdc954e3aa263bc1e393af
+ languageName: node
+ linkType: hard
+
+"@react-spring/shared@npm:~9.7.3":
+ version: 9.7.3
+ resolution: "@react-spring/shared@npm:9.7.3"
+ dependencies:
+ "@react-spring/types": "npm:~9.7.3"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ checksum: 10c0/afb03ed28ccf62efa4012e531c3659999bb364d1e0eb0fb729b962f9bd21a0b772a2d98e862062c9c32c06edf72327afcc45984d9eb22fdd961706b6ddf6950d
+ languageName: node
+ linkType: hard
+
+"@react-spring/types@npm:~9.7.3":
+ version: 9.7.3
+ resolution: "@react-spring/types@npm:9.7.3"
+ checksum: 10c0/d645044f3cc9ceb7c4f6c4d061aaf6660018568a1553d05638f56b3328c5f91597ee4118334abe22fc8f07f5ee02f054340170c1d52e11b3faea22888b5170d4
+ languageName: node
+ linkType: hard
+
+"@react-spring/web@npm:9.7.3":
+ version: 9.7.3
+ resolution: "@react-spring/web@npm:9.7.3"
+ dependencies:
+ "@react-spring/animated": "npm:~9.7.3"
+ "@react-spring/core": "npm:~9.7.3"
+ "@react-spring/shared": "npm:~9.7.3"
+ "@react-spring/types": "npm:~9.7.3"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
+ checksum: 10c0/a5b4847a2921a29a3e8ce569f4951abeb268b6e8eb230f8c49d98709216b2b3a23ba1e58628c51c9eaa0bd20d83f9d7b8f8f03df98215e933de4c66c39e17fe1
+ languageName: node
+ linkType: hard
+
"@remix-run/router@npm:1.16.1":
version: 1.16.1
resolution: "@remix-run/router@npm:1.16.1"
@@ -12874,6 +12932,7 @@ __metadata:
"@emotion/styled": "npm:11.11.5"
"@mui/icons-material": "npm:^5.15.19"
"@mui/material": "npm:5.15.19"
+ "@react-spring/web": "npm:9.7.3"
"@testing-library/jest-dom": "npm:6.4.2"
"@testing-library/react": "npm:14.3.1"
"@testing-library/user-event": "npm:^14.5.2"