go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/common/layouts/side_bar/sidebar.tsx (about) 1 // Copyright 2023 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 LaunchIcon from '@mui/icons-material/Launch'; 16 import MenuIcon from '@mui/icons-material/Menu'; 17 import { Typography } from '@mui/material'; 18 import Drawer from '@mui/material/Drawer'; 19 import MaterialLink from '@mui/material/Link'; 20 import List from '@mui/material/List'; 21 import ListItem from '@mui/material/ListItem'; 22 import ListItemButton from '@mui/material/ListItemButton'; 23 import ListItemIcon from '@mui/material/ListItemIcon'; 24 import ListItemText from '@mui/material/ListItemText'; 25 import ListSubheader from '@mui/material/ListSubheader'; 26 import Toolbar from '@mui/material/Toolbar'; 27 import { Fragment, useMemo } from 'react'; 28 import { Link } from 'react-router-dom'; 29 30 import { 31 useSelectedPage, 32 useProject, 33 } from '@/common/components/page_meta/page_meta_provider'; 34 import { UiPage, CommonColors } from '@/common/constants/view'; 35 36 import { PAGE_LABEL_MAP, drawerWidth } from '../constants'; 37 38 import { generateSidebarSections } from './pages'; 39 40 interface Props { 41 open: boolean; 42 } 43 44 export const Sidebar = ({ open }: Props) => { 45 const project = useProject(); 46 const selectedPage = useSelectedPage(); 47 48 const sidebarSections = useMemo(() => { 49 return generateSidebarSections(project); 50 }, [project]); 51 52 return ( 53 <Drawer 54 sx={{ 55 width: drawerWidth, 56 flexShrink: 0, 57 '& .MuiDrawer-paper': { 58 width: drawerWidth, 59 boxSizing: 'border-box', 60 }, 61 }} 62 variant="persistent" 63 anchor="left" 64 open={open} 65 role="complementary" 66 > 67 <Toolbar variant="dense" /> 68 <List sx={{ mb: '40px', pt: 0 }}> 69 {sidebarSections.map((sidebarSection) => ( 70 <Fragment key={sidebarSection.title}> 71 <ListSubheader>{sidebarSection.title}</ListSubheader> 72 {sidebarSection.pages.map((sidebarPage) => ( 73 <ListItem 74 dense 75 key={sidebarPage.page} 76 disablePadding 77 sx={{ display: 'block' }} 78 > 79 <ListItemButton 80 sx={{ 81 justifyContent: 'center', 82 px: 2.5, 83 }} 84 selected={sidebarPage.page === selectedPage} 85 component={sidebarPage.external ? MaterialLink : Link} 86 to={sidebarPage.url} 87 target={sidebarPage.external ? '_blank' : ''} 88 > 89 <ListItemIcon 90 sx={{ 91 minWidth: 0, 92 mr: 1, 93 justifyContent: 'center', 94 }} 95 > 96 {sidebarPage.icon} 97 </ListItemIcon> 98 <ListItemText 99 primary={ 100 // Add "(Consoles)" to "Builder groups" to let help users 101 // find the link if they are looking for "Consoles" page, 102 // which is the old name of the builder groups page. 103 // 104 // TODO: remove this once most users are aware of the name 105 // change. 106 sidebarPage.page === UiPage.BuilderGroups 107 ? 'Builder groups (Consoles)' 108 : PAGE_LABEL_MAP[sidebarPage.page] 109 } 110 /> 111 112 {sidebarPage.external && ( 113 <ListItemIcon 114 sx={{ 115 minWidth: 0, 116 mr: 1, 117 justifyContent: 'center', 118 }} 119 > 120 <LaunchIcon color="inherit" /> 121 </ListItemIcon> 122 )} 123 </ListItemButton> 124 </ListItem> 125 ))} 126 </Fragment> 127 ))} 128 <div style={{ margin: '40px 20px', color: CommonColors.FADED_TEXT }}> 129 {!project && ( 130 <div style={{ margin: '10px 0', color: CommonColors.FADED_TEXT }}> 131 <Typography variant="caption"> 132 To see more options, <Link to="/ui/">choose a project</Link>. 133 </Typography> 134 </div> 135 )} 136 <Typography variant="caption"> 137 Click{' '} 138 <MenuIcon 139 fontSize="small" 140 style={{ position: 'relative', top: '5px' }} 141 />{' '} 142 above to hide this menu. 143 </Typography> 144 </div> 145 </List> 146 </Drawer> 147 ); 148 };