diff --git a/src/features/navigation-bar/components/DesktopSideBar.tsx b/src/features/navigation-bar/components/DesktopSideBar.tsx index 65b87f5b..204310b5 100644 --- a/src/features/navigation-bar/components/DesktopSideBar.tsx +++ b/src/features/navigation-bar/components/DesktopSideBar.tsx @@ -8,27 +8,18 @@ import Drawer from '@mui/material/Drawer'; import List from '@mui/material/List'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import { useLocation } from 'react-router-dom'; import IconButton from '@mui/material/IconButton'; import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import Divider from '@mui/material/Divider'; -import { styled, useTheme } from '@mui/material/styles'; -import { useCallback, useMemo, useRef } from 'react'; +import { styled } from '@mui/material/styles'; +import { useCallback, useRef } from 'react'; import Box from '@mui/material/Box'; -import ListItem from '@mui/material/ListItem'; -import Badge from '@mui/material/Badge'; -import Typography from '@mui/material/Typography'; -import { useLingui } from '@lingui/react/macro'; -import { CustomTooltip } from '@/base/components/CustomTooltip.tsx'; -import { ListItemLink } from '@/base/components/lists/ListItemLink.tsx'; import { useGetOptionForDirection } from '@/features/theme/services/ThemeCreator.ts'; import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx'; import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx'; import type { NavbarItem } from '@/features/navigation-bar/NavigationBar.types.ts'; -import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx'; +import { NavigationBarItem } from '@/features/navigation-bar/components/NavigationBarItem.tsx'; const DrawerHeader = styled('div')(({ theme }) => ({ display: 'flex', @@ -39,80 +30,6 @@ const DrawerHeader = styled('div')(({ theme }) => ({ ...theme.mixins.toolbar, })); -const NavigationBarItem = ({ path, title, IconComponent, SelectedIconComponent, useBadge }: NavbarItem) => { - const { t } = useLingui(); - const location = useLocation(); - const { isCollapsed } = useNavBarContext(); - const theme = useTheme(); - const badgeInfo = useBadge?.(); - - const isActive = location.pathname.startsWith(path); - const Icon = isActive ? SelectedIconComponent : IconComponent; - - const { listItemProps, listItemIconProps } = useMemo( - () => ({ - listItemProps: isCollapsed ? { p: 0.5, display: 'flex', flexDirection: 'column' } : {}, - listItemIconProps: isCollapsed ? { justifyContent: 'center' } : {}, - }), - [isCollapsed], - ); - - return ( - - - {t(title)} -
- {badgeInfo?.title} - - } - placement="right" - > - - - - - - - - - {t(title)} - - } - secondary={ - !isCollapsed && ( - - {badgeInfo?.title} - - ) - } - sx={{ maxWidth: '100%', m: 0, display: 'flex', flexDirection: 'column' }} - /> - -
-
- ); -}; - const MIN_WIDTH_COLLAPSED = undefined; const MAX_WIDTH_COLLAPSED = 120; const MIN_WIDTH_EXTENDED = 240; diff --git a/src/features/navigation-bar/components/MobileBottomBar.tsx b/src/features/navigation-bar/components/MobileBottomBar.tsx index a3f7ff25..f01702eb 100644 --- a/src/features/navigation-bar/components/MobileBottomBar.tsx +++ b/src/features/navigation-bar/components/MobileBottomBar.tsx @@ -6,54 +6,20 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import BottomNavigation from '@mui/material/BottomNavigation'; -import type { BottomNavigationActionProps } from '@mui/material/BottomNavigationAction'; -import BottomNavigationAction from '@mui/material/BottomNavigationAction'; import Paper from '@mui/material/Paper'; import type { CSSProperties } from 'react'; -import { useCallback, useLayoutEffect, useRef, useState } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; +import { useCallback, useLayoutEffect, useRef } from 'react'; +import {} from 'react-router-dom'; import { useTheme } from '@mui/material/styles'; -import Badge from '@mui/material/Badge'; -import { useLingui } from '@lingui/react/macro'; import { useResizeObserver } from '@/base/hooks/useResizeObserver.tsx'; import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx'; import type { NavbarItem } from '@/features/navigation-bar/NavigationBar.types.ts'; -import type { StaticAppRoute } from '@/base/AppRoute.constants.ts'; - -const BottomNavigationItem = ({ - path, - title, - useBadge, - SelectedIconComponent, - IconComponent, - isActive, - ...bottomNavigationActionProps -}: NavbarItem & { - isActive: boolean; -} & Omit) => { - const { t } = useLingui(); - const count = useBadge?.()?.count; - - return ( - - {isActive ? : } - - } - /> - ); -}; +import { NavigationBarItem } from '@/features/navigation-bar/components/NavigationBarItem.tsx'; +import Stack from '@mui/material/Stack'; export const MobileBottomBar = ({ navBarItems }: { navBarItems: NavbarItem[] }) => { const theme = useTheme(); const { setBottomBarHeight } = useNavBarContext(); - const location = useLocation(); - const navigate = useNavigate(); const ref = useRef(null); useResizeObserver( @@ -62,10 +28,6 @@ export const MobileBottomBar = ({ navBarItems }: { navBarItems: NavbarItem[] }) ); useLayoutEffect(() => () => setBottomBarHeight(0), []); - const [selectedNavBarItem, setSelectedNavBarItem] = useState( - navBarItems.find((navBarItem) => navBarItem.path === location.pathname)?.path, - ); - return ( - { - setSelectedNavBarItem(newValue); - navigate(newValue); - }} - > - {navBarItems.map((navbarItem) => ( - + {navBarItems.map((item) => ( + ))} - + ); }; diff --git a/src/features/navigation-bar/components/NavigationBarItem.tsx b/src/features/navigation-bar/components/NavigationBarItem.tsx new file mode 100644 index 00000000..19aeac42 --- /dev/null +++ b/src/features/navigation-bar/components/NavigationBarItem.tsx @@ -0,0 +1,113 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import type { NavbarItem } from '@/features/navigation-bar/NavigationBar.types.ts'; +import { ListItemLink } from '@/base/components/lists/ListItemLink.tsx'; +import { CustomTooltip } from '@/base/components/CustomTooltip.tsx'; +import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { useLocation } from 'react-router-dom'; +import { useTheme } from '@mui/material/styles'; +import type { ComponentProps } from 'react'; +import { useMemo } from 'react'; +import ListItem from '@mui/material/ListItem'; +import Badge from '@mui/material/Badge'; +import Typography from '@mui/material/Typography'; +import { useLingui } from '@lingui/react/macro'; +import { useNavBarContext } from '@/features/navigation-bar/NavbarContext.tsx'; + +export const NavigationBarItem = ({ + path, + title, + IconComponent, + SelectedIconComponent, + useBadge, + slots, +}: NavbarItem & { + slots?: { + listItemLink?: Partial>; + }; +}) => { + const { t } = useLingui(); + const location = useLocation(); + const { isCollapsed } = useNavBarContext(); + const theme = useTheme(); + const badgeInfo = useBadge?.(); + + const isActive = location.pathname.startsWith(path); + const Icon = isActive ? SelectedIconComponent : IconComponent; + + const { listItemProps, listItemIconProps } = useMemo( + () => ({ + listItemProps: isCollapsed ? { p: 0.5, display: 'flex', flexDirection: 'column' } : {}, + listItemIconProps: isCollapsed ? { justifyContent: 'center' } : {}, + }), + [isCollapsed], + ); + + return ( + + + {t(title)} +
+ {badgeInfo?.title} + + } + placement="right" + > + + + + + + + + + {t(title)} + + } + secondary={ + !isCollapsed && ( + + {badgeInfo?.title} + + ) + } + sx={{ maxWidth: '100%', m: 0, display: 'flex', flexDirection: 'column' }} + /> + +
+
+ ); +};