fix(ui): top nav menu behavior on guide

This commit is contained in:
Valeriy 2019-03-09 01:13:20 +03:00 committed by mrugesh mohapatra
parent 6bbe152f34
commit 4994cd828e
7 changed files with 99 additions and 202 deletions

View File

@ -41,7 +41,7 @@ export const wrapPageElement = ({ element, props }) => {
}
if (/^\/guide(\/.*)*/.test(pathname)) {
return (
<DefaultLayout onGuide={true}>
<DefaultLayout disableMenuButtonBehavior={true} mediaBreakpoint='991px'>
<GuideLayout>{element}</GuideLayout>
</DefaultLayout>
);

View File

@ -1,5 +1,4 @@
.signup-btn.btn,
#top-right-nav .signup-btn.btn {
.signup-btn {
background-color: #ffac33;
background-image: linear-gradient(#ffcc4d, #ffac33);
-ms-filter: 'progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffcc4d, endColorstr=#ffac33, GradientType=0)';
@ -10,18 +9,14 @@
}
.signup-btn:hover,
.signup-btn:focus,
.signup-btn:active:hover,
#top-right-nav .signup-btn:hover,
#top-right-nav .signup-btn:focus,
#top-right-nav .signup-btn:active:hover {
.signup-btn:active:hover {
background-color: #e99110;
background-image: linear-gradient(#ffcc4d, #e99110);
-ms-filter: 'progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffcc4d, endColorstr=#e99110, GradientType=0)';
border-color: #ec8b11;
color: #292f33 !important;
}
.signup-btn:active,
#top-right-nav .signup-btn:active {
.signup-btn:active {
background-color: #f2a330;
background-image: none;
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.3);

View File

@ -41,41 +41,22 @@ header {
background-color: #006400;
}
#top-right-nav a,
#top-right-nav img {
max-height: var(--header-height);
}
#top-right-nav > li > a {
padding: 8px 15px;
}
#top-right-nav li {
margin: 0;
}
#top-right-nav a {
.top-right-nav-link {
max-height: var(--header-height);
color: #fff;
font-size: 18px;
padding: 8px 15px;
}
#top-right-nav a:hover,
#top-right-nav a:focus {
.top-right-nav-link:hover,
.top-right-nav-link:focus,
.top-right-nav-link:active {
background-color: #fff;
color: #006400;
}
#top-right-nav li.user-state-link,
#top-right-nav li.user-state-link:hover,
#top-right-nav li.user-state-link:focus,
#top-right-nav li.user-state-link > a,
#top-right-nav li.user-state-link > a:hover,
#top-right-nav li.user-state-link > a:focus {
background-color: #006400;
}
#top-right-nav a:hover,
#top-right-nav a:focus {
text-decoration: none;
}
@ -175,8 +156,21 @@ header {
}
#top-nav .menu-button {
display: none;
color: white;
background-color: transparent;
margin: 0 20px 0 12px;
padding: 2px 14px;
border: 1px solid #fff;
border-radius: 3px;
}
#top-nav .menu-button-open {
background: white;
color: #006400;
}
#top-right-nav .signup-btn {
margin: 0 15px;
}
@media (max-width: 734px) {
@ -184,28 +178,9 @@ header {
padding: 0;
}
#top-nav .menu-button {
display: block;
margin: 0 20px 0 12px;
padding: 2px 14px;
border: 1px solid #fff;
border-radius: 3px;
cursor: pointer;
color: #fff;
}
.opened #top-right-nav {
top: var(--header-height);
}
.opened #top-nav .menu-button {
background: white;
color: #006400;
}
#top-right-nav {
position: absolute;
top: -300px;
top: var(--header-height);
flex-direction: column;
width: 100vw;
height: min-content;
@ -233,41 +208,3 @@ header {
top: 2.4em;
}
}
@media (min-width: 735px) and (max-width: 991px) {
.onGuide #top-nav {
padding: 0;
}
.onGuide #top-nav .menu-button {
display: block;
margin: 0 20px 0 12px;
padding: 2px 14px;
border: 1px solid #fff;
border-radius: 3px;
cursor: pointer;
}
.onGuide #top-right-nav {
top: var(--header-height);
}
.opened #top-nav .menu-button {
background: white;
color: #006400;
}
.onGuide #top-right-nav {
position: absolute;
top: -300px;
flex-direction: column;
width: 100vw;
height: min-content;
min-height: 160px;
padding: 10px 0;
}
.onGuide #top-nav img {
margin: 0 0 0 10px;
}
}

View File

@ -13,7 +13,6 @@ import { Link } from '../helpers';
import './header.css';
import {
toggleDisplaySideNav,
toggleDisplayMenu,
displayMenuSelector
} from '../layouts/components/guide/redux';
@ -26,14 +25,14 @@ const mapStateToProps = createSelector(
);
const mapDispatchToProps = dispatch =>
bindActionCreators({ toggleDisplaySideNav, toggleDisplayMenu }, dispatch);
bindActionCreators({ toggleDisplayMenu }, dispatch);
const propTypes = {
disableMenuButtonBehavior: PropTypes.bool,
disableSettings: PropTypes.bool,
displayMenu: PropTypes.bool,
onGuide: PropTypes.bool,
toggleDisplayMenu: PropTypes.func,
toggleDisplaySideNav: PropTypes.func
mediaBreakpoint: PropTypes.string.isRequired,
toggleDisplayMenu: PropTypes.func.isRequired
};
class Header extends Component {
@ -50,97 +49,85 @@ class Header extends Component {
document.removeEventListener('click', this.handleClickOutside);
}
toggleDisplayMenuLogic = () => {
if (this.props.onGuide) {
this.props.toggleDisplaySideNav();
} else {
this.props.toggleDisplayMenu();
}
};
handleClickOutside = event => {
if (
!this.props.disableMenuButtonBehavior &&
this.props.displayMenu &&
!this.menuButtonRef.current.contains(event.target) &&
!this.props.onGuide
this.menuButtonRef.current &&
!this.menuButtonRef.current.contains(event.target)
) {
this.toggleDisplayMenuLogic();
this.props.toggleDisplayMenu();
}
};
handleMediaChange = matches => {
if (!matches && this.props.displayMenu) {
this.toggleDisplayMenuLogic();
this.props.toggleDisplayMenu();
}
};
renderClassNames = (displayMenu, onGuide) => {
if (displayMenu && onGuide) {
return 'opened onGuide';
} else if (displayMenu) {
return 'opened';
} else if (onGuide) {
return 'onGuide';
}
return '';
};
render() {
const {
disableMenuButtonBehavior,
disableSettings,
onGuide,
displayMenu,
mediaBreakpoint,
toggleDisplayMenu
} = this.props;
return (
<header className={this.renderClassNames(displayMenu, onGuide)}>
<header>
<nav id='top-nav'>
<Link className='home-link' to='/'>
<NavLogo />
</Link>
{disableSettings ? null : <FCCSearch />}
<Media query='(max-width: 991px)'>
{matches =>
matches && onGuide && displayMenu ? null : (
<ul id='top-right-nav'>
<li onClick={toggleDisplayMenu}>
<Link to='/learn'>Learn</Link>
<Media maxWidth={mediaBreakpoint} onChange={this.handleMediaChange}>
{matches => [
matches && (
<button
aria-expanded={displayMenu}
className={
'menu-button' + (displayMenu ? ' menu-button-open' : '')
}
key='menu-button'
onClick={toggleDisplayMenu}
ref={this.menuButtonRef}
>
Menu
</button>
),
(!matches || (displayMenu && !disableMenuButtonBehavior)) && (
<ul id='top-right-nav' key='top-right-nav'>
<li>
<Link className='top-right-nav-link' to='/learn'>
Learn
</Link>
</li>
<li onClick={toggleDisplayMenu}>
<Link external={true} to='/forum'>
<li>
<Link
className='top-right-nav-link'
external={true}
to='/forum'
>
Forum
</Link>
</li>
<li onClick={toggleDisplayMenu}>
<Link external={true} to='/news'>
<li>
<Link
className='top-right-nav-link'
external={true}
to='/news'
>
News
</Link>
</li>
<li className='user-state-link' onClick={toggleDisplayMenu}>
<li>
<UserState disableSettings={disableSettings} />
</li>
</ul>
)
}
]}
</Media>
<span
className='menu-button'
onClick={this.toggleDisplayMenuLogic}
ref={this.menuButtonRef}
>
Menu
</span>
{onGuide ? (
<Media
onChange={this.handleMediaChange}
query='(max-width: 991px)'
/>
) : (
<Media
onChange={this.handleMediaChange}
query='(max-width: 734px)'
/>
)}
</nav>
</header>
);
@ -148,6 +135,9 @@ class Header extends Component {
}
Header.propTypes = propTypes;
Header.defaultProps = {
mediaBreakpoint: '734px'
};
export default connect(
mapStateToProps,

View File

@ -56,6 +56,7 @@ const metaKeywords = [
const propTypes = {
children: PropTypes.node.isRequired,
disableMenuButtonBehavior: PropTypes.bool,
disableSettings: PropTypes.bool,
fetchUser: PropTypes.func.isRequired,
flashMessages: PropTypes.arrayOf(
@ -69,7 +70,7 @@ const propTypes = {
isOnline: PropTypes.bool.isRequired,
isSignedIn: PropTypes.bool,
landingPage: PropTypes.bool,
onGuide: PropTypes.bool,
mediaBreakpoint: PropTypes.string,
onlineStatusChange: PropTypes.func.isRequired,
removeFlashMessage: PropTypes.func.isRequired,
showFooter: PropTypes.bool
@ -141,7 +142,8 @@ class DefaultLayout extends Component {
removeFlashMessage,
landingPage,
showFooter = true,
onGuide = false,
mediaBreakpoint,
disableMenuButtonBehavior,
isOnline,
isSignedIn
} = this.props;
@ -160,7 +162,11 @@ class DefaultLayout extends Component {
>
<style>{fontawesome.dom.css()}</style>
</Helmet>
<Header disableSettings={disableSettings} onGuide={onGuide} />
<Header
disableMenuButtonBehavior={disableMenuButtonBehavior}
disableSettings={disableSettings}
mediaBreakpoint={mediaBreakpoint}
/>
<div className={`default-layout ${landingPage ? 'landing-page' : ''}`}>
<OfflineWarning isOnline={isOnline} isSignedIn={isSignedIn} />
{hasMessages ? (

View File

@ -14,8 +14,7 @@ import './guide.css';
import {
toggleExpandedState,
toggleDisplaySideNav,
displaySideNavSelector,
toggleDisplayMenu,
displayMenuSelector,
expandedStateSelector
} from './components/guide/redux';
@ -37,48 +36,37 @@ const propTypes = {
})
}),
displayMenu: PropTypes.bool,
displaySideNav: PropTypes.bool,
expandedState: PropTypes.object,
location: PropTypes.object,
toggleDisplaySideNav: PropTypes.func,
toggleDisplayMenu: PropTypes.func,
toggleExpandedState: PropTypes.func
};
const mapStateToProps = createSelector(
displaySideNavSelector,
displayMenuSelector,
expandedStateSelector,
(displaySideNav, displayMenu, expandedState) => ({
displaySideNav,
(displayMenu, expandedState) => ({
displayMenu,
expandedState
})
);
const mapDispatchToProps = dispatch =>
bindActionCreators({ toggleExpandedState, toggleDisplaySideNav }, dispatch);
bindActionCreators({ toggleExpandedState, toggleDisplayMenu }, dispatch);
class GuideLayout extends React.Component {
getContentRef = ref => (this.contentRef = ref);
handleNavigation = () => {
this.contentRef.scrollTop = 0;
this.contentRef.focus();
handleNavigation = () => {};
hideSideNav = () => {
if (this.props.displayMenu) {
this.props.toggleDisplayMenu();
}
};
componentWillUnmount() {
if (this.props.displayMenu) {
this.props.toggleDisplaySideNav();
}
}
render() {
let {
displaySideNav,
expandedState,
toggleExpandedState,
toggleDisplaySideNav
} = this.props;
const { expandedState, toggleExpandedState, displayMenu } = this.props;
return (
<StaticQuery
query={graphql`
@ -105,24 +93,16 @@ class GuideLayout extends React.Component {
<Spacer size={1} />
<Grid className='guide-container'>
<Row>
<Col
md={4}
smHidden={!displaySideNav}
xsHidden={!displaySideNav}
>
<Col md={4} smHidden={!displayMenu} xsHidden={!displayMenu}>
<SideNav
expandedState={expandedState}
onNavigate={this.handleNavigation}
pages={pages}
toggleDisplaySideNav={toggleDisplaySideNav}
toggleDisplaySideNav={this.hideSideNav}
toggleExpandedState={toggleExpandedState}
/>
</Col>
<Col
md={8}
smHidden={displaySideNav}
xsHidden={displaySideNav}
>
<Col md={8} smHidden={displayMenu} xsHidden={displayMenu}>
<main
className='content'
id='main'

View File

@ -6,23 +6,17 @@ import { createSideNavigationSaga } from './side-navigation-saga';
export const ns = 'guideNav';
const initialState = {
displaySideNav: false,
displayMenu: false,
expandedState: {}
};
const types = createTypes(
['toggleExpandedState', 'toggleDisplaySideNav', 'toggleDisplayMenu'],
ns
);
const types = createTypes(['toggleExpandedState', 'toggleDisplayMenu'], ns);
export const sagas = [...createSideNavigationSaga(types)];
export const toggleExpandedState = createAction(types.toggleExpandedState);
export const toggleDisplaySideNav = createAction(types.toggleDisplaySideNav);
export const toggleDisplayMenu = createAction(types.toggleDisplayMenu);
export const displaySideNavSelector = state => state[ns].displaySideNav;
export const displayMenuSelector = state => state[ns].displayMenu;
export const expandedStateSelector = state => state[ns].expandedState;
@ -35,11 +29,6 @@ export const reducer = handleActions(
[payload]: !state.expandedState[payload]
}
}),
[types.toggleDisplaySideNav]: state => ({
...state,
displayMenu: !state.displayMenu,
displaySideNav: !state.displaySideNav
}),
[types.toggleDisplayMenu]: state => ({
...state,
displayMenu: !state.displayMenu