Files
games-frontend-js/src/components/MobileBar.tsx
T
john-okeefe 45dd783964 refactor(nav): migrate header, dashboard chrome and discovery UI to v3
- Header/MobileBar: MenuRoot/Positioner/Content + Portal + Tooltip
  shims, ghost icon buttons, 2rem padded user/settings menus, hover
  token gray.700; MobileBar drawer API (open/onOpenChange/finalFocusEl)
- FilterBar/ActiveFilters: DrawerRoot/CloseTrigger, Divider -> Separator,
  Tag shim, FixedSelect with typed handlers and width-preserving
  chakraStyles, blue active-filter pills untouched
- Pagination: NumberInputRoot/Field + NativeSelect shims, first/last
  arrows back to double chevrons (LuChevronsLeft/Right), single chevrons
  kept for prev/next
- Search/SearchModal, Home, NoGames, LoadingModal, DashboardLoadingModal:
  Dialog/Toaster-era props, gap/align/textAlign renames; App.test target
  content updated accordingly
2026-09-06 10:30:21 -04:00

123 lines
3.7 KiB
TypeScript

import React, { MutableRefObject } from 'react'
import {
Button, Center,
Separator,
Drawer,
Icon,
Image, Link,
Stack, Text,
} from '@chakra-ui/react'
import {DrawerBody, DrawerCloseTrigger, DrawerContent, DrawerFooter, DrawerHeader, DrawerRoot} from './ui/drawer'
import {Avatar} from './ui/avatar'
import AdminMode from './authComponents/AdminMode'
import { NavLink } from 'react-router-dom'
import Search from './Search'
import { LuPlus } from 'react-icons/lu'
import { logout } from '../stateManagement/userState'
import User from '../models/user'
import { AiOutlineLogout } from 'react-icons/ai'
import {useHookstate} from "@hookstate/core";
import {searchCompletedState} from "../stateManagement/loadingState";
import {gameDashboardState} from "../stateManagement/gameState";
import ResetFilterButton from "./helperComponents/ResetFilterButton";
import type { ColorMode } from './ui/color-mode'
interface Props {
mobileIsOpen: boolean
mobileOnClose: () => void
btnRef: MutableRefObject<null>
bgLink: string
user: User
colorMode: ColorMode
toggleColorMode: () => void
}
function MobileBar({ mobileIsOpen, mobileOnClose, btnRef, bgLink, user }: Props) {
const searchCompleted = useHookstate(searchCompletedState)
const gamesState = useHookstate(gameDashboardState)
const games = gamesState.get()
return (
<DrawerRoot
open={mobileIsOpen}
placement="end"
onOpenChange={(e) => { if (!e.open) mobileOnClose() }}
finalFocusEl={() => btnRef.current as unknown as HTMLElement}
>
<DrawerContent>
<DrawerCloseTrigger/>
<DrawerHeader>
<Image maxW="15rem" src="/assets/Logo.svg" alt="Games Database Logo"/>
</DrawerHeader>
<DrawerBody>
<AdminMode />
<Stack
as={'nav'}
gap={4}
>
<Link
px={2}
py={1}
rounded={'md'}
_hover={{
textDecoration: 'none',
bg: bgLink,
}}
asChild>
<NavLink to="/games"><Text textAlign={'right'}>Games</Text></NavLink>
</Link>
<Link
px={2}
py={1}
rounded={'md'}
_hover={{
textDecoration: 'none',
bg: bgLink,
}}
asChild>
<NavLink to="/games/create"><Text textAlign={'right'}>Create Game</Text></NavLink>
</Link>
<Separator/>
<Search/>
{searchCompleted.get() && <Text>Games Found: {games.count.totalGames}</Text>}
<Separator/>
<Center><Avatar mr={'2'} size={'sm'} src={user.avatar} name={user.displayName}/><Text mt={1}>{user.displayName}</Text></Center>
<Link
px={2}
py={1}
rounded={'md'}
_hover={{
textDecoration: 'none',
bg: bgLink,
}}
asChild>
<NavLink to="/profile"><Text textAlign={'right'}>Preferences</Text></NavLink>
</Link>
<Separator/>
<ResetFilterButton />
</Stack>
</DrawerBody>
<DrawerFooter>
<Button
variant={'solid'}
colorPalette={'blue'}
size={'md'}
asChild
mr={3}
>
<NavLink to="/games/create"><LuPlus/> <Text mt="1">Create Game</Text></NavLink>
</Button>
<Button onMouseDown={() => logout()}><Icon as={AiOutlineLogout} mr={'2'}/> <Text
mt={'1'}>Logout</Text></Button>
</DrawerFooter>
</DrawerContent>
</DrawerRoot>
)
}
export default MobileBar