@@ -266,8 +266,8 @@ export function Header(props) {
266266 } , [ props . notification ?. error ] ) ;
267267
268268 const toggle = ( ) => {
269- setIsOpen ( prevIsOpen => ! prevIsOpen ) ;
270- } ;
269+ setIsOpen ( prevIsOpen => ! prevIsOpen ) ;
270+ } ;
271271
272272 const openModal = ( ) => {
273273 setLogoutPopup ( true ) ;
@@ -380,25 +380,25 @@ export function Header(props) {
380380 setShowProjectDropdown ( location . pathname . startsWith ( '/bmdashboard/projects/' ) ) ;
381381 } , [ location . pathname ] ) ;
382382
383- useEffect ( ( ) => {
384- const handleClickOutside = ( event ) => {
385- if (
386- collapseRef . current &&
387- ! collapseRef . current . contains ( event . target ) &&
388- ! toggleRef . current ?. contains ( event . target )
389- ) {
390- setIsOpen ( false ) ;
391- }
392- } ;
383+ useEffect ( ( ) => {
384+ if ( ! isOpen ) return ;
393385
394- if ( isOpen ) {
395- document . addEventListener ( 'mousedown' , handleClickOutside ) ;
396- }
386+ const handleClickOutside = ( event ) => {
387+ if ( collapseRef . current ?. contains ( event . target ) ) return ;
388+ if ( toggleRef . current ?. contains ( event . target ) ) return ;
389+ setIsOpen ( false ) ;
390+ } ;
397391
398- return ( ) => {
399- document . removeEventListener ( 'mousedown' , handleClickOutside ) ;
400- } ;
401- } , [ isOpen ] ) ;
392+ // Defer adding listener until after current click event finishes
393+ const timer = setTimeout ( ( ) => {
394+ document . addEventListener ( 'click' , handleClickOutside ) ;
395+ } , 0 ) ;
396+
397+ return ( ) => {
398+ clearTimeout ( timer ) ;
399+ document . removeEventListener ( 'click' , handleClickOutside ) ;
400+ } ;
401+ } , [ isOpen ] ) ;
402402
403403 const fontColor = darkMode ? `${ styles . darkDropdownText } ${ styles . darkDropdownItem } ` : `${ styles . mobileDropdownText } ${ styles . mobileDropdownItem } ` ;
404404
@@ -407,7 +407,7 @@ export function Header(props) {
407407 const viewingUser = JSON . parse ( window . sessionStorage . getItem ( 'viewingUser' ) ) ;
408408 return (
409409 < div className = { `${ styles . headerWrapper } ` } data-testid = "header" >
410- < Navbar className = { `py-3 ${ styles . navbar } ` } color = "dark" dark expand = { true } >
410+ < Navbar className = { `py-3 ${ styles . navbar } ` } color = "dark" dark expand = "xl" >
411411 { logoutPopup && < Logout open = { logoutPopup } setLogoutPopup = { setLogoutPopup } /> }
412412 { showPromotionsPopup && < DisplayBox onClose = { ( ) => setShowPromotionsPopup ( false ) } /> }
413413
@@ -420,8 +420,17 @@ export function Header(props) {
420420 { isAuthenticated && < OwnerMessage /> }
421421 </ div >
422422 < div className = { styles . rightSection } >
423- < Collapse isOpen = { isOpen } navbar ref = { collapseRef } >
424- < Nav className = { `ml-auto ${ styles . menuContainer } mr-3` } navbar >
423+ < NavbarToggler onClick = { toggle } ref = { toggleRef } className = { styles . navbarToggler } />
424+ < div
425+ ref = { collapseRef }
426+ className = { `${ styles . navCollapse } ${ isOpen ? styles . navCollapseOpen : styles . navCollapseHidden } ` }
427+ role = "menu"
428+ tabIndex = { - 1 }
429+ onKeyDown = { ( e ) => {
430+ if ( e . key === 'Escape' ) setIsOpen ( false ) ;
431+ } }
432+ >
433+ < Nav className = { `${ styles . menuContainer } mr-3` } navbar >
425434 < NavItem className = { styles . showInMobile } >
426435 < NavLink tag = { Link } to = { `/userprofile/${ displayUserId } ` } >
427436 < img
@@ -905,7 +914,7 @@ export function Header(props) {
905914 </ DropdownMenu >
906915 </ UncontrolledDropdown >
907916 </ Nav >
908- </ Collapse >
917+ </ div >
909918 </ div >
910919 </ div >
911920 </ Navbar >
0 commit comments