go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/analysis/frontend/ui/src/components/top_bar/collapsed_menu/collapsed_menu.tsx (about)

     1  // Copyright 2022 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import React, { useContext } from 'react';
    16  import { Link } from 'react-router-dom';
    17  
    18  import MenuIcon from '@mui/icons-material/Menu';
    19  import Box from '@mui/material/Box';
    20  import IconButton from '@mui/material/IconButton';
    21  import ListItemIcon from '@mui/material/ListItemIcon';
    22  import ListItemText from '@mui/material/ListItemText';
    23  import Menu from '@mui/material/Menu';
    24  import MenuItem from '@mui/material/MenuItem';
    25  import Typography from '@mui/material/Typography';
    26  
    27  import Logo from '@/components/top_bar/logo/logo';
    28  import { AppBarPage } from '@/components/top_bar/top_bar';
    29  import { TopBarContext } from '@/components/top_bar/top_bar_context';
    30  import { DynamicComponentNoProps } from '@/tools/rendering_tools';
    31  
    32  interface Props {
    33    pages: AppBarPage[];
    34  }
    35  
    36  // A menu that is collapsed on mobile.
    37  const CollapsedMenu = ({ pages }: Props) => {
    38    const { anchorElNav, setAnchorElNav } = useContext(TopBarContext);
    39  
    40    const handleOpenNavMenu = (event: React.MouseEvent<HTMLElement>) => {
    41      setAnchorElNav(event.currentTarget);
    42    };
    43  
    44    const handleCloseNavMenu = () => {
    45      setAnchorElNav(null);
    46    };
    47  
    48    return (
    49      <>
    50        <Box sx={{ flexGrow: 1, display: { xs: 'flex', md: 'none' } }}>
    51          <IconButton
    52            size="large"
    53            aria-label="pages menu"
    54            aria-controls="menu-appbar"
    55            aria-haspopup="true"
    56            onClick={handleOpenNavMenu}
    57            color="inherit"
    58            data-testid="collapsed-menu-button"
    59          >
    60            <MenuIcon />
    61          </IconButton>
    62          <Menu
    63            id="menu-appbar"
    64            keepMounted
    65            anchorEl={anchorElNav}
    66            anchorOrigin={{
    67              vertical: 'bottom',
    68              horizontal: 'left',
    69            }}
    70            transformOrigin={{
    71              vertical: 'top',
    72              horizontal: 'left',
    73            }}
    74            open={Boolean(anchorElNav)}
    75            onClose={handleCloseNavMenu}
    76            sx={{
    77              display: { xs: 'block', md: 'none' },
    78            }}
    79            data-testid="collapsed-menu"
    80          >
    81            {pages.map((page) => (
    82              <MenuItem
    83                component={Link}
    84                to={page.url}
    85                key={page.title}
    86                onClick={handleCloseNavMenu}>
    87                <ListItemIcon>
    88                  <DynamicComponentNoProps component={page.icon} />
    89                </ListItemIcon>
    90                <ListItemText>{page.title}</ListItemText>
    91              </MenuItem>
    92            ))}
    93          </Menu>
    94        </Box>
    95        <Box sx={{
    96          display: {
    97            xs: 'flex',
    98            md: 'none' },
    99          mr: 1,
   100          width: '3rem',
   101        }}>
   102          <Logo />
   103        </Box>
   104        <Typography
   105          variant="h5"
   106          noWrap
   107          component="a"
   108          href=""
   109          sx={{
   110            mr: 2,
   111            display: { xs: 'flex', md: 'none' },
   112            flexGrow: 1,
   113            color: 'inherit',
   114            textDecoration: 'none',
   115          }}
   116        >
   117          LUCI Analysis
   118        </Typography>
   119      </>
   120    );
   121  };
   122  
   123  export default CollapsedMenu;