mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 05:00:43 +10:00
Merge pull request #140 from sharetribe/topbar-mobile-menu
Topbar mobile menu
This commit is contained in:
commit
7eb452c3ed
9 changed files with 237 additions and 33 deletions
|
|
@ -72,3 +72,30 @@
|
|||
cursor: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.inlineButton {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
|
||||
/* fill colors should be in sync with marketplace color palette */
|
||||
background-color: transparent;
|
||||
|
||||
/* border-width should be in sync with marketplace strike-widths */
|
||||
border-width: 0px;
|
||||
|
||||
/* Font configuration */
|
||||
text-decoration: underline;
|
||||
|
||||
/* Hovers */
|
||||
&:enabled {
|
||||
cursor: pointer;
|
||||
}
|
||||
&:enabled:hover,
|
||||
&:enabled:active {
|
||||
background-color: transparent;
|
||||
}
|
||||
&:disabled {
|
||||
background-color: transparent;
|
||||
cursor: auto;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ Button.propTypes = {
|
|||
export default Button;
|
||||
|
||||
export const FlatButton = props => <Button {...props} rootClassName={css.flatButton} />;
|
||||
|
||||
FlatButton.defaultProps = { className: '' };
|
||||
|
||||
FlatButton.propTypes = { className: string };
|
||||
|
||||
export const InlineButton = props => <Button {...props} rootClassName={css.inlineButton} />;
|
||||
InlineButton.defaultProps = { className: '' };
|
||||
InlineButton.propTypes = { className: string };
|
||||
|
|
|
|||
46
src/components/MobileMenu/MobileMenu.css
Normal file
46
src/components/MobileMenu/MobileMenu.css
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
.root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.user {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-basis: 80px;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.footer {
|
||||
flex-basis: 80px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.createNewListingLink {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.userInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.authenticationLinks {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.signupLink {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
69
src/components/MobileMenu/MobileMenu.js
Normal file
69
src/components/MobileMenu/MobileMenu.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* MobileMenu prints the menu content for authenticated user or
|
||||
* shows login actions for those who are not authenticated.
|
||||
*/
|
||||
import React, { PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Avatar, InlineButton, NamedLink } from '../../components';
|
||||
|
||||
import css from './MobileMenu.css';
|
||||
|
||||
const MobileMenu = props => {
|
||||
const { isAuthenticated, name, onLogout } = props;
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return (
|
||||
<div className={css.root}>
|
||||
<div className={css.authenticationLinks}>
|
||||
<NamedLink name="SignUpPage" className={css.signupLink}>
|
||||
<FormattedMessage id="MobileMenu.signupLink" />
|
||||
</NamedLink>
|
||||
<NamedLink name="LogInPage">
|
||||
<FormattedMessage id="MobileMenu.loginLink" />
|
||||
</NamedLink>
|
||||
</div>
|
||||
<div className={css.createNewListingLink}>
|
||||
<NamedLink name="NewListingPage">
|
||||
<FormattedMessage id="MobileMenu.newListingLink" />
|
||||
</NamedLink>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={css.root}>
|
||||
<div className={css.user}>
|
||||
<Avatar className={css.avatar} name={name} />
|
||||
<div className={css.userInfo}>
|
||||
<span>{name}</span>
|
||||
<NamedLink className={css.createNewListingLink} name="NewListingPage">
|
||||
<FormattedMessage id="MobileMenu.newListingLink" />
|
||||
</NamedLink>
|
||||
</div>
|
||||
</div>
|
||||
<div className={css.content}>
|
||||
<NamedLink name="InboxPage" params={{ tab: 'orders' }}>
|
||||
<FormattedMessage id="MobileMenu.inboxLink" />
|
||||
</NamedLink>
|
||||
</div>
|
||||
<div className={css.footer}>
|
||||
<InlineButton className={css.logoutButton} onClick={onLogout}>
|
||||
<FormattedMessage id="MobileMenu.logoutLink" />
|
||||
</InlineButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
MobileMenu.defaultProps = { name: '' };
|
||||
|
||||
const { bool, func, string } = PropTypes;
|
||||
|
||||
MobileMenu.propTypes = {
|
||||
isAuthenticated: bool.isRequired,
|
||||
name: string,
|
||||
onLogout: func.isRequired,
|
||||
};
|
||||
|
||||
export default MobileMenu;
|
||||
|
|
@ -2,7 +2,7 @@ import AddImages from './AddImages/AddImages';
|
|||
import AuthorInfo from './AuthorInfo/AuthorInfo';
|
||||
import Avatar from './Avatar/Avatar';
|
||||
import BookingInfo from './BookingInfo/BookingInfo';
|
||||
import Button, { FlatButton } from './Button/Button';
|
||||
import Button, { FlatButton, InlineButton } from './Button/Button';
|
||||
import CurrencyInput from './CurrencyInput/CurrencyInput';
|
||||
import DateInput from './DateInput/DateInput';
|
||||
import Discussion from './Discussion/Discussion';
|
||||
|
|
@ -17,6 +17,7 @@ import Map from './Map/Map';
|
|||
import MapPanel from './MapPanel/MapPanel';
|
||||
import Menu from './Menu/Menu';
|
||||
import MobileFrame from './MobileFrame/MobileFrame';
|
||||
import MobileMenu from './MobileMenu/MobileMenu';
|
||||
import Modal from './Modal/Modal';
|
||||
import ModalInMobile from './ModalInMobile/ModalInMobile';
|
||||
import NamedLink from './NamedLink/NamedLink';
|
||||
|
|
@ -43,6 +44,7 @@ export {
|
|||
FilterPanel,
|
||||
FlatButton,
|
||||
HeroSection,
|
||||
InlineButton,
|
||||
Input,
|
||||
LabeledField,
|
||||
ListingCard,
|
||||
|
|
@ -52,6 +54,7 @@ export {
|
|||
MapPanel,
|
||||
Menu,
|
||||
MobileFrame,
|
||||
MobileMenu,
|
||||
Modal,
|
||||
ModalInMobile,
|
||||
NamedLink,
|
||||
|
|
|
|||
|
|
@ -44,15 +44,39 @@ exports[`InboxPage matches snapshot 1`] = `
|
|||
className="">
|
||||
<div
|
||||
className={undefined}>
|
||||
<a
|
||||
className=""
|
||||
href="/inbox"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span>
|
||||
Inbox
|
||||
</span>
|
||||
</a>
|
||||
<div
|
||||
className={undefined}>
|
||||
<a
|
||||
className=""
|
||||
href="/signup"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span>
|
||||
Sign up
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
className=""
|
||||
href="/login"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span>
|
||||
Log in
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
className={undefined}>
|
||||
<a
|
||||
className=""
|
||||
href="/l/new"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span>
|
||||
+ Add your sauna
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -204,15 +228,39 @@ exports[`InboxPage matches snapshot 2`] = `
|
|||
className="">
|
||||
<div
|
||||
className={undefined}>
|
||||
<a
|
||||
className=""
|
||||
href="/inbox"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span>
|
||||
Inbox
|
||||
</span>
|
||||
</a>
|
||||
<div
|
||||
className={undefined}>
|
||||
<a
|
||||
className=""
|
||||
href="/signup"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span>
|
||||
Sign up
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
className=""
|
||||
href="/login"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span>
|
||||
Log in
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
className={undefined}>
|
||||
<a
|
||||
className=""
|
||||
href="/l/new"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span>
|
||||
+ Add your sauna
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,3 @@
|
|||
.hamburgerMenu {
|
||||
width: 44px;
|
||||
}
|
||||
|
||||
.mobileMenuContent {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import React, { Component, PropTypes } from 'react';
|
||||
import { compose } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { logout, authenticationInProgress } from '../../ducks/Auth.duck';
|
||||
import { Button, FlatButton, Modal, NamedLink } from '../../components';
|
||||
import { Button, FlatButton, MobileMenu, Modal, NamedLink } from '../../components';
|
||||
import { withFlattenedRoutes } from '../../util/contextHelpers';
|
||||
import { parse, stringify } from '../../util/urlHelpers';
|
||||
import { ensureUser } from '../../util/data';
|
||||
import { pathByRouteName } from '../../util/routes';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
|
||||
|
|
@ -53,7 +53,16 @@ class TopbarComponent extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { isAuthenticated, authInProgress, location, togglePageClassNames } = this.props;
|
||||
const {
|
||||
isAuthenticated,
|
||||
authInProgress,
|
||||
currentUser,
|
||||
location,
|
||||
togglePageClassNames,
|
||||
} = this.props;
|
||||
const me = ensureUser(currentUser);
|
||||
const profile = me.attributes.profile;
|
||||
const name = me.id ? `${profile.firstName} ${profile.lastName}` : '';
|
||||
const { mobilemenu } = parse(location.search);
|
||||
const isMobileMenuOpen = mobilemenu === 'open';
|
||||
|
||||
|
|
@ -81,11 +90,7 @@ class TopbarComponent extends Component {
|
|||
onClose={this.handleMobileMenuClose}
|
||||
togglePageClassNames={togglePageClassNames}
|
||||
>
|
||||
<div className={css.mobileMenuContent}>
|
||||
<NamedLink name="InboxBasePage">
|
||||
<FormattedMessage id="Topbar.inboxLink" defaultMessage="Inbox" />
|
||||
</NamedLink>
|
||||
</div>
|
||||
<MobileMenu isAuthenticated={isAuthenticated} name={name} onLogout={this.handleLogout} />
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -97,6 +102,7 @@ const { arrayOf, bool, func, shape, string } = PropTypes;
|
|||
TopbarComponent.propTypes = {
|
||||
isAuthenticated: bool.isRequired,
|
||||
authInProgress: bool.isRequired,
|
||||
currentUser: propTypes.currentUser,
|
||||
onLogout: func.isRequired,
|
||||
togglePageClassNames: func.isRequired,
|
||||
|
||||
|
|
@ -114,9 +120,11 @@ TopbarComponent.propTypes = {
|
|||
|
||||
const mapStateToProps = state => {
|
||||
const { isAuthenticated } = state.Auth;
|
||||
const { currentUser } = state.user;
|
||||
return {
|
||||
isAuthenticated,
|
||||
authInProgress: authenticationInProgress(state),
|
||||
currentUser,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,11 @@
|
|||
"LoginForm.emailLabel": "Email",
|
||||
"LoginForm.logIn": "Log in",
|
||||
"LoginForm.passwordLabel": "Password",
|
||||
"MobileMenu.inboxLink": "Inbox",
|
||||
"MobileMenu.loginLink": "Log in",
|
||||
"MobileMenu.logoutLink": "Log out",
|
||||
"MobileMenu.newListingLink": "+ Add your sauna",
|
||||
"MobileMenu.signupLink": "Sign up",
|
||||
"Modal.closeModal": "Close modal",
|
||||
"OrderDetailsPanel.orderAcceptedStatus": "{providerName} accepted the booking.",
|
||||
"OrderDetailsPanel.orderAcceptedTitle": "You have booked {title}.",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue