@@ -17,6 +17,7 @@ import {
1717 Menu ,
1818 MenuItem ,
1919 Select ,
20+ type SxProps ,
2021} from '@mui/material' ;
2122import MenuIcon from '@mui/icons-material/Menu' ;
2223import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown' ;
@@ -29,7 +30,7 @@ import {
2930 buildNavigationItems ,
3031} from '../constants/Navigation' ;
3132import type NavigationItem from '../interface/Navigation' ;
32- import { useNavigate } from 'react-router-dom' ;
33+ import { useLocation , useNavigate } from 'react-router-dom' ;
3334import { useSelector } from 'react-redux' ;
3435import { selectIsAuthenticated , selectUserEmail } from '../store/selectors' ;
3536import LogoutConfirmModal from './LogoutConfirmModal' ;
@@ -43,7 +44,7 @@ import { useRemoteConfig } from '../context/RemoteConfigProvider';
4344import i18n from '../../i18n' ;
4445import { NestedMenuItem } from 'mui-nested-menu' ;
4546import DirectionsBusIcon from '@mui/icons-material/DirectionsBus' ;
46- import { theme } from '../Theme' ;
47+ import { fontFamily , theme } from '../Theme' ;
4748
4849const drawerWidth = 240 ;
4950const websiteTile = 'Mobility Database' ;
@@ -71,7 +72,7 @@ const DrawerContent: React.FC<{
7172 < Avatar src = '/assets/MOBILTYDATA_logo_purple_M.png' > </ Avatar >
7273 < Typography
7374 variant = 'h6'
74- sx = { { my : 2 , cursor : 'pointer' } }
75+ sx = { { my : 2 , cursor : 'pointer' , color : theme . palette . primary . main } }
7576 data-testid = 'websiteTile'
7677 >
7778 { websiteTile }
@@ -94,7 +95,11 @@ const DrawerContent: React.FC<{
9495 pl : '16px' ,
9596 } }
9697 >
97- < ListItemText >
98+ < ListItemText
99+ sx = { {
100+ '.MuiTypography-root' : { fontFamily : fontFamily . secondary } ,
101+ } }
102+ >
98103 { item . title } { ' ' }
99104 { item . external === true ? (
100105 < OpenInNew sx = { { verticalAlign : 'middle' } } />
@@ -113,7 +118,10 @@ const DrawerContent: React.FC<{
113118 < TreeItem
114119 nodeId = '1'
115120 label = 'GTFS Metrics'
116- sx = { { color : theme . palette . primary . main } }
121+ sx = { {
122+ color : theme . palette . primary . main ,
123+ '.MuiTreeItem-label' : { fontFamily : fontFamily . secondary } ,
124+ } }
117125 >
118126 < TreeItem
119127 nodeId = '2'
@@ -182,7 +190,10 @@ const DrawerContent: React.FC<{
182190 < TreeItem
183191 nodeId = '1'
184192 label = 'Account'
185- sx = { { color : theme . palette . primary . main } }
193+ sx = { {
194+ color : theme . palette . primary . main ,
195+ '.MuiTreeItem-label' : { fontFamily : fontFamily . secondary } ,
196+ } }
186197 data-cy = 'accountHeader'
187198 >
188199 < TreeItem
@@ -229,8 +240,10 @@ const DrawerContent: React.FC<{
229240} ;
230241
231242export default function DrawerAppBar ( ) : React . ReactElement {
243+ const location = useLocation ( ) ;
232244 const [ mobileOpen , setMobileOpen ] = React . useState ( false ) ;
233245 const [ openDialog , setOpenDialog ] = React . useState ( false ) ;
246+ const [ activeTab , setActiveTab ] = React . useState ( '' ) ;
234247 const [ navigationItems , setNavigationItems ] = React . useState <
235248 NavigationItem [ ]
236249 > ( [ ] ) ;
@@ -243,6 +256,10 @@ export default function DrawerAppBar(): React.ReactElement {
243256 setCurrentLanguage ( i18n . language ) ;
244257 } ) ;
245258
259+ React . useEffect ( ( ) => {
260+ setActiveTab ( location . pathname ) ;
261+ } , [ location . pathname ] ) ;
262+
246263 React . useEffect ( ( ) => {
247264 setNavigationItems ( buildNavigationItems ( config ) ) ;
248265 } , [ config ] ) ;
@@ -290,14 +307,61 @@ export default function DrawerAppBar(): React.ReactElement {
290307
291308 const metricsOptionsEnabled =
292309 config . enableMetrics || userEmail ?. endsWith ( 'mobilitydata.org' ) === true ;
310+ const AnimatedButtonStyling : SxProps = {
311+ minWidth : 'fit-content' ,
312+ px : 0 ,
313+ mx : {
314+ md : 1 ,
315+ lg : 2 ,
316+ } ,
317+ fontFamily : fontFamily . secondary ,
318+ '&:hover, &.active' : {
319+ backgroundColor : 'transparent' ,
320+ '&::after' : {
321+ transform : 'scaleX(1)' ,
322+ left : 0 ,
323+ right : 0 ,
324+ transformOrigin : 'left' ,
325+ } ,
326+ } ,
327+ '&.active.short' : {
328+ '&::after' : {
329+ right : '20px' ,
330+ } ,
331+ } ,
332+ '&::after' : {
333+ content : '""' ,
334+ height : '2px' ,
335+ position : 'absolute' ,
336+ left : 0 ,
337+ right : 0 ,
338+ bottom : 0 ,
339+ backgroundColor : theme . palette . primary . main ,
340+ opacity : 0.7 ,
341+ transition : 'transform 0.9s cubic-bezier(0.19, 1, 0.22, 1)' ,
342+ transform : 'scaleX(0)' ,
343+ transformOrigin : 'right' ,
344+ pointerEvents : 'none' ,
345+ } ,
346+ } ;
293347
294348 return (
295- < Box sx = { { display : 'flex' } } >
349+ < Box
350+ sx = { {
351+ display : 'flex' ,
352+ height : '64px' ,
353+ mb : { xs : 2 , md : 4 } ,
354+ } }
355+ >
296356 < AppBar
297357 component = 'nav'
298358 color = 'inherit'
299359 elevation = { 0 }
300- sx = { { background : 'white' } }
360+ sx = { {
361+ background : 'white' ,
362+ fontFamily : fontFamily . secondary ,
363+ borderBottom : '1px solid rgba(0,0,0,0.2)' ,
364+ } }
301365 >
302366 < Toolbar sx = { { display : 'flex' , justifyContent : 'space-between' } } >
303367 < Box sx = { { display : 'flex' , alignItems : 'center' } } >
@@ -325,6 +389,7 @@ export default function DrawerAppBar(): React.ReactElement {
325389 component = 'div'
326390 className = 'website-title'
327391 sx = { {
392+ ml : 1 ,
328393 display : { xs : 'none' , md : 'block' } ,
329394 } }
330395 >
@@ -336,13 +401,19 @@ export default function DrawerAppBar(): React.ReactElement {
336401 < Box sx = { { display : { xs : 'none' , md : 'block' } } } >
337402 { navigationItems . map ( ( item ) => (
338403 < Button
404+ sx = { {
405+ ...AnimatedButtonStyling ,
406+ color : theme . palette . text . primary ,
407+ } }
339408 href = { item . external === true ? item . target : '/' + item . target }
340409 key = { item . title }
341- sx = { { color : item . color , minWidth : 'fit-content' , mx : 1 } }
342410 target = { item . external === true ? '_blank' : '_self' }
343411 rel = { item . external === true ? 'noopener noreferrer' : '' }
344412 variant = { 'text' }
345413 endIcon = { item . external === true ? < OpenInNew /> : null }
414+ className = {
415+ activeTab . includes ( '/' + item . target ) ? 'active' : ''
416+ }
346417 >
347418 { item . title }
348419 </ Button >
@@ -355,8 +426,14 @@ export default function DrawerAppBar(): React.ReactElement {
355426 aria-haspopup = 'true'
356427 endIcon = { < ArrowDropDownIcon /> }
357428 onClick = { handleMenuOpen }
358- sx = { { color : 'black' } }
429+ sx = { {
430+ ...AnimatedButtonStyling ,
431+ color : theme . palette . text . primary ,
432+ } }
359433 id = 'analytics-button-menu'
434+ className = {
435+ activeTab . includes ( 'metrics' ) ? 'active short' : ''
436+ }
360437 >
361438 Metrics
362439 </ Button >
@@ -434,6 +511,8 @@ export default function DrawerAppBar(): React.ReactElement {
434511 onClick = { handleMenuOpen }
435512 endIcon = { < ArrowDropDownIcon /> }
436513 id = 'account-button-menu'
514+ sx = { AnimatedButtonStyling }
515+ className = { activeTab === '/account' ? 'active short' : '' }
437516 >
438517 Account
439518 </ Button >
@@ -464,7 +543,12 @@ export default function DrawerAppBar(): React.ReactElement {
464543 </ Menu >
465544 </ >
466545 ) : (
467- < Button href = { SIGN_IN_TARGET } > Login</ Button >
546+ < Button
547+ sx = { { fontFamily : fontFamily . secondary } }
548+ href = { SIGN_IN_TARGET }
549+ >
550+ Login
551+ </ Button >
468552 ) }
469553 { /* Testing language tool */ }
470554 { config . enableLanguageToggle && currentLanguage !== undefined && (
0 commit comments