Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use JS to trigger hover and reposition the flyout #47238

Merged
merged 10 commits into from
Nov 10, 2020
46 changes: 43 additions & 3 deletions client/layout/sidebar/expandable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import React, { useState, useRef, useEffect } from 'react';
import { get, uniqueId } from 'lodash';

/**
Expand All @@ -12,6 +12,10 @@ import { get, uniqueId } from 'lodash';
import TranslatableString from 'calypso/components/translatable/proptype';
import ExpandableSidebarHeading from './expandable-heading';
import SidebarMenu from 'calypso/layout/sidebar/menu';
import { hasTouch } from 'calypso/lib/touch-detect';
import config from 'calypso/config';

const isTouch = hasTouch();

function containsSelectedSidebarItem( children ) {
let selectedItemFound = false;
Expand All @@ -35,6 +39,11 @@ function containsSelectedSidebarItem( children ) {
return selectedItemFound;
}

const offScreen = ( submenu ) => {
const rect = submenu.getBoundingClientRect();
return rect.y + rect.height > window.innerHeight;
};

export const ExpandableSidebarMenu = ( {
className,
title,
Expand All @@ -48,6 +57,9 @@ export const ExpandableSidebarMenu = ( {
...props
} ) => {
let { expanded } = props;
const submenu = useRef();
const [ submenuHovered, setSubmenuHovered ] = useState( false );
const [ submenuStyles, setSubmenuStyles ] = useState( { top: 0 } );

if ( null === expanded ) {
expanded = containsSelectedSidebarItem( children );
Expand All @@ -56,12 +68,33 @@ export const ExpandableSidebarMenu = ( {
const classes = classNames( className, {
'is-toggle-open': !! expanded,
'is-togglable': true,
hovered: submenuHovered,
} );

const onEnter = () => {
if ( expanded || isTouch ) return;
cpapazoglou marked this conversation as resolved.
Show resolved Hide resolved
setSubmenuHovered( true );
};

const onLeave = () => {
if ( expanded || isTouch ) return;
cpapazoglou marked this conversation as resolved.
Show resolved Hide resolved
setSubmenuHovered( false );
cpapazoglou marked this conversation as resolved.
Show resolved Hide resolved
};

const menuId = uniqueId( 'menu' );

useEffect( () => {
cpapazoglou marked this conversation as resolved.
Show resolved Hide resolved
if ( offScreen( submenu.current ) ) {
setSubmenuStyles( { bottom: 0 } );
}
}, [ submenuHovered ] );

return (
<SidebarMenu className={ classes }>
<SidebarMenu
className={ classes }
onMouseEnter={ config.isEnabled( 'nav-unification' ) ? () => onEnter() : null }
onMouseLeave={ config.isEnabled( 'nav-unification' ) ? () => onLeave() : null }
cpapazoglou marked this conversation as resolved.
Show resolved Hide resolved
>
<ExpandableSidebarHeading
title={ title }
count={ count }
Expand All @@ -74,7 +107,14 @@ export const ExpandableSidebarMenu = ( {
menuId={ menuId }
{ ...props }
/>
<li role="region" id={ menuId } className="sidebar__expandable-content" hidden={ ! expanded }>
<li
role="region"
ref={ submenu }
id={ menuId }
className="sidebar__expandable-content"
hidden={ ! expanded }
style={ submenuStyles }
>
<ul>{ children }</ul>
</li>
</SidebarMenu>
Expand Down
6 changes: 4 additions & 2 deletions client/layout/sidebar/menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import React from 'react';
import classNames from 'classnames';

const SidebarMenu = ( { children, className } ) => (
<ul className={ classNames( 'sidebar__menu', className ) }>{ children }</ul>
const SidebarMenu = ( { children, className, ...props } ) => (
<ul className={ classNames( 'sidebar__menu', className ) } { ...props }>
{ children }
</ul>
);

export default SidebarMenu;
64 changes: 33 additions & 31 deletions client/my-sites/sidebar-unified/menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,38 +60,40 @@ export const MySitesSidebarUnifiedMenu = ( {
}, [ selected, childIsSelected, reduxDispatch, sectionId, sidebarCollapsed ] );

return (
<ExpandableSidebarMenu
onClick={ () => {
if ( link ) {
if ( isExternal( link ) ) {
// If the URL is external, page() will fail to replace state between different domains
externalRedirect( link );
return;
<li>
cpapazoglou marked this conversation as resolved.
Show resolved Hide resolved
<ExpandableSidebarMenu
onClick={ () => {
if ( link ) {
if ( isExternal( link ) ) {
// If the URL is external, page() will fail to replace state between different domains
cpapazoglou marked this conversation as resolved.
Show resolved Hide resolved
externalRedirect( link );
return;
}
page( link );
}
page( link );
}
if ( ! sidebarCollapsed ) {
reduxDispatch( collapseAllMySitesSidebarSections() );
reduxDispatch( toggleSection( sectionId ) );
}
} }
expanded={ ! sidebarCollapsed && isExpanded }
title={ title }
customIcon={ <SidebarCustomIcon icon={ icon } /> }
className={ ( selected || childIsSelected ) && 'sidebar__menu--selected' }
>
{ children.map( ( item ) => {
const isSelected = selectedMenuItem?.url === item.url;
return (
<MySitesSidebarUnifiedItem
key={ item.slug }
{ ...item }
selected={ isSelected }
isSubItem={ true }
/>
);
} ) }
</ExpandableSidebarMenu>
if ( ! sidebarCollapsed ) {
reduxDispatch( collapseAllMySitesSidebarSections() );
reduxDispatch( toggleSection( sectionId ) );
}
} }
expanded={ ! sidebarCollapsed && isExpanded }
title={ title }
customIcon={ <SidebarCustomIcon icon={ icon } /> }
className={ ( selected || childIsSelected ) && 'sidebar__menu--selected' }
>
{ children.map( ( item ) => {
const isSelected = selectedMenuItem?.url === item.url;
return (
<MySitesSidebarUnifiedItem
key={ item.slug }
{ ...item }
selected={ isSelected }
isSubItem={ true }
/>
);
} ) }
</ExpandableSidebarMenu>
</li>
);
};

Expand Down
3 changes: 1 addition & 2 deletions client/my-sites/sidebar-unified/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ $font-size: rem( 14px );
}
}

.sidebar__menu.is-togglable:not( .is-toggle-open ):hover {
.sidebar__menu.is-togglable:not( .is-toggle-open ).hovered {
cpapazoglou marked this conversation as resolved.
Show resolved Hide resolved
position: relative;

.sidebar__heading {
Expand All @@ -501,7 +501,6 @@ $font-size: rem( 14px );
.sidebar__expandable-content {
display: block;
position: absolute;
top: 0;
cpapazoglou marked this conversation as resolved.
Show resolved Hide resolved
left: var( --sidebar-width-max );
width: 160px;

Expand Down