Merge pull request #201 from sharetribe/mobile-topbar-modal

Mobile topbar modal
This commit is contained in:
Vesa Luusua 2017-06-02 01:03:20 +03:00 committed by GitHub
commit 896500e241
12 changed files with 220 additions and 55 deletions

View file

@ -40,6 +40,14 @@
font-style: normal;
}
@font-face {
font-family: 'sofiapro';
src: url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-bold-webfont.woff2') format('woff2'),
url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-bold-webfont.woff') format('woff');
font-weight: 700;
font-style: normal;
}
</style>
<link rel="stylesheet" href="%PUBLIC_URL%/static/reactDates.css" />

View file

@ -75,7 +75,6 @@
.inlineButton {
display: inline-block;
padding: 0;
/* fill colors should be in sync with marketplace color palette */
background-color: transparent;

View file

@ -0,0 +1,5 @@
@import '../../marketplace.css';
.root {
stroke: var(--matterColor);
}

View file

@ -0,0 +1,38 @@
import React, { PropTypes } from 'react';
import classNames from 'classnames';
import css from './CloseIcon.css';
const CloseIcon = props => {
const { className, rootClassName } = props;
const classes = classNames(rootClassName || css.root, className);
return (
<svg
className={classes}
width="12"
height="12"
viewBox="0 0 12 12"
xmlns="http://www.w3.org/2000/svg"
>
<g transform="translate(-1 -1)" fillRule="evenodd">
<rect transform="rotate(45 7 7)" x="-1" y="6" width="16" height="2" rx="1" />
<rect transform="rotate(-45 7 7)" x="-1" y="6" width="16" height="2" rx="1" />
</g>
</svg>
);
};
const { string } = PropTypes;
CloseIcon.defaultProps = {
className: null,
rootClassName: null,
};
CloseIcon.propTypes = {
className: string,
rootClassName: string,
};
export default CloseIcon;

View file

@ -1,3 +1,5 @@
@import '../../marketplace.css';
/* Content is visible as modal layer */
.isOpen {
display: flex;
@ -8,7 +10,7 @@
bottom: 0;
width: 100%;
z-index: 100;
background-color: white;
background-color: var(--matterColorLight);
margin: 0 auto;
}
@ -33,31 +35,37 @@
}
.title {
margin: 1rem;
margin: 24px;
flex-grow: 1;
}
.close {
display: flex;
align-items: baseline;
width: auto;
height: 3em;
background-color: transparent;
padding: 1em;
color: #999;
padding: 24px;
color: var(--matterColor);
border: 0;
composes: tinyBoldFont from '../../marketplace.css';
&:enabled:hover {
background-color: transparent;
color: #666;
color: var(--matterColorDark);
}
&:enabled:active {
background-color: transparent;
color: #000;
color: var(--matterColorDark);
}
&:disabled {
background-color: transparent;
}
}
.closeIcon {
margin-left: 12px;
}
.content {
flex-grow: 1;
display: flex;

View file

@ -10,10 +10,9 @@
*/
import React, { Component, PropTypes } from 'react';
import classNames from 'classnames';
import { intlShape, injectIntl } from 'react-intl';
import { Button } from '../../components';
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
import { Button, CloseIcon } from '../../components';
import closeIcon from './images/closeIcon.svg';
import css from './Modal.css';
export class ModalComponent extends Component {
@ -53,8 +52,9 @@ export class ModalComponent extends Component {
const closeModalMessage = intl.formatMessage({ id: 'Modal.closeModal' });
const modalTitle = title ? <h2 className={css.title}>{title}</h2> : null;
const closeBtn = (
<Button onClick={this.handleClose} className={css.close} title={closeModalMessage}>
<img src={closeIcon} alt={closeModalMessage} />
<Button onClick={this.handleClose} rootClassName={css.close} title={closeModalMessage}>
<span><FormattedMessage id="Modal.close" /></span>
<CloseIcon rootClassName={css.closeIcon} />
</Button>
);

View file

@ -4,24 +4,24 @@
display: flex;
flex-direction: column;
height: 100vh;
padding: 1rem;
}
.user {
display: flex;
flex-direction: row;
flex-basis: 80px;
padding: 24px;
}
.content {
flex-grow: 1;
flex-shrink: 0;
display: flex;
flex-direction: column;
margin: 24px 0;
}
.footer {
flex-basis: 80px;
flex-basis: 66px;
flex-shrink: 0;
}
.avatar {
flex-shrink: 0;
width: 120px;
height: 120px;
border-radius: 50%;
@ -39,26 +39,71 @@
composes: h2Font from '../../marketplace.css';
}
.greeting {
composes: h2Font from '../../marketplace.css';
}
.logoutButton {
composes: h4Font from '../../marketplace.css';
text-align: left;
color: var(--matterColorAnti);
margin-top: 6px;
}
.inbox {
composes: h2Font from '../../marketplace.css';
color: var(--marketplaceColor);
margin-top: auto;
}
/* TODO createNewListingLink camouflages as a button. */
.createNewListingLink {
font-size: 14px;
display: block;
padding: 21px;
background-color: var(--marketplaceColor);
border-width: 0;
border-radius: var(--borderRadius);
/* Font */
composes: buttonFont from '../../marketplace.css';
color: var(--matterColorLight);
text-align: center;
/* Dimensions */
width: 100%;
/* Hovers */
&:enabled {
cursor: pointer;
}
&:enabled:hover {
background-color: var(--marketplaceColorDark);
text-decoration: none;
}
&:enabled:active {
background-color: var(--marketplaceColorLight);
}
&:disabled {
background-color: var(--matterColorAnti);
cursor: auto;
}
}
.userInfo {
display: flex;
flex-direction: column;
.authenticationGreeting {
composes: h2Font from '../../marketplace.css';
margin-bottom: 24px;
}
.authenticationLinks {
display: flex;
flex-direction: row;
margin-bottom: 1rem;
font-size: 20px;
white-space: nowrap;
}
.signupLink {
margin-right: 1rem;
text-decoration: none;
white-space: nowrap;
color: var(--marketplaceColor);
}
.loginLink {
text-decoration: none;
white-space: nowrap;
color: var(--marketplaceColor);
}

View file

@ -12,18 +12,35 @@ const TopbarMobileMenu = props => {
const { isAuthenticated, currentUserHasListings, firstName, lastName, onLogout } = props;
if (!isAuthenticated) {
const signup = (
<NamedLink name="SignupPage" className={css.signupLink}>
<FormattedMessage id="TopbarMobileMenu.signupLink" />
</NamedLink>
);
const login = (
<NamedLink name="LoginPage" className={css.loginLink}>
<FormattedMessage id="TopbarMobileMenu.loginLink" />
</NamedLink>
);
const signupOrLogin = (
<span className={css.authenticationLinks}>
<FormattedMessage id="TopbarMobileMenu.signupOrLogin" values={{ signup, login }} />
</span>
);
return (
<div className={css.root}>
<div className={css.authenticationLinks}>
<NamedLink name="SignupPage" className={css.signupLink}>
<FormattedMessage id="TopbarMobileMenu.signupLink" />
</NamedLink>
<NamedLink name="LoginPage" className={css.loginLink}>
<FormattedMessage id="TopbarMobileMenu.loginLink" />
</NamedLink>
<div className={css.content}>
<div className={css.authenticationGreeting}>
<FormattedMessage
id="TopbarMobileMenu.unauthorizedGreeting"
values={{ lineBreak: <br />, signupOrLogin }}
/>
</div>
</div>
<div className={css.createNewListingLink}>
<NamedLink name="NewListingPage">
<div className={css.footer}>
<NamedLink className={css.createNewListingLink} name="NewListingPage">
<FormattedMessage id="TopbarMobileMenu.newListingLink" />
</NamedLink>
</div>
@ -32,29 +49,31 @@ const TopbarMobileMenu = props => {
}
const inboxLink = (
<NamedLink name="InboxPage" params={{ tab: currentUserHasListings ? 'sales' : 'orders' }}>
<NamedLink
className={css.inbox}
name="InboxPage"
params={{ tab: currentUserHasListings ? 'sales' : 'orders' }}
>
<FormattedMessage id="TopbarMobileMenu.inboxLink" />
</NamedLink>
);
return (
<div className={css.root}>
<div className={css.user}>
<Avatar rootClassName={css.avatar} firstName={firstName} lastName={lastName} />
<div className={css.userInfo}>
<span>{name}</span>
<NamedLink className={css.createNewListingLink} name="NewListingPage">
<FormattedMessage id="TopbarMobileMenu.newListingLink" />
</NamedLink>
</div>
</div>
<Avatar rootClassName={css.avatar} firstName={firstName} lastName={lastName} />
<div className={css.content}>
{inboxLink}
</div>
<div className={css.footer}>
<span className={css.greeting}>
<FormattedMessage id="TopbarMobileMenu.greeting" values={{ firstName }} />
</span>
<InlineButton className={css.logoutButton} onClick={onLogout}>
<FormattedMessage id="TopbarMobileMenu.logoutLink" />
</InlineButton>
{inboxLink}
</div>
<div className={css.footer}>
<NamedLink className={css.createNewListingLink} name="NewListingPage">
<FormattedMessage id="TopbarMobileMenu.newListingLink" />
</NamedLink>
</div>
</div>
);

View file

@ -4,6 +4,7 @@ import Avatar from './Avatar/Avatar';
import BirthdayInput from './BirthdayInput/BirthdayInput';
import BookingInfo from './BookingInfo/BookingInfo';
import Button, { FlatButton, InlineButton } from './Button/Button';
import CloseIcon from './CloseIcon/CloseIcon';
import CurrencyInput from './CurrencyInput/CurrencyInput';
import DateInput from './DateInput/DateInput';
import Discussion from './Discussion/Discussion';
@ -53,6 +54,7 @@ export {
BirthdayInput,
BookingInfo,
Button,
CloseIcon,
CurrencyInput,
DateInput,
Discussion,

View file

@ -67,6 +67,12 @@ const Fonts = () => {
line-height: 18px;
padding: 2px 0 4px 0;`;
const tinyBoldFontStyling = `Styles affecting size:
font-weight: 700;
font-size: 13px;
line-height: 18px;
padding: 2px 0 4px 0;`;
const fontsContainerClasses = classNames(css.fontsContainer, css.baselines);
return (
@ -132,6 +138,15 @@ const Fonts = () => {
description="Very small print."
styling={tinyFontStyling}
/>
<Font
component={() => (
<p className={mpStyle.tinyBoldFont}>
Tiny bold mobile text (.tinyBoldFont): CLOSE
</p>
)}
description="Very small bold print used next to close icon."
styling={tinyBoldFontStyling}
/>
</div>
</div>
);

View file

@ -27,12 +27,14 @@
--boxShadowPopup: 0 8px 16px 0 rgba(0, 0, 0, 0.3);
--boxShadowPopupLight: 0 3px 6px 0 rgba(0, 0, 0, 0.3);
/* z-index base levels */
/* small popups on UI should use z-indexes above 50 */
--zIndexPopup: 50;
/* modals and UI overlays should use z-indexes above 100 */
--zIndexModal: 100;
/* Border radius */
--borderRadius: 2px;
}
/* FONTS */
@ -159,6 +161,26 @@ pre,
/* TODO Desktop styles needs to be extracted */
}
.tinyBoldFont {
font-family: "sofiapro", Helvetica, Arial, sans-serif;
font-weight: 700;
font-size: 13px;
line-height: 18px;
padding: 2px 0 4px 0; /* 2px + 4px = 6px */
letter-spacing: 1.5px;
}
.buttonFont {
font-family: "sofiapro", Helvetica, Arial, sans-serif;
font-weight: 600;
font-size: 18px;
line-height: 24px;
padding: 2.5px 0 3.5px 0; /* 2.5px + 3.5px = 6px */
letter-spacing: -0.3px;
/* TODO Desktop styles needs to be extracted */
}
/* This font is specific to Avatar component only */
.smallAvatarFont {
font-family: "sofiapro", Helvetica, Arial, sans-serif;

View file

@ -77,6 +77,7 @@
"LoginForm.logIn": "Log in",
"LoginForm.passwordLabel": "Password",
"LoginForm.passwordRequired": "required",
"Modal.close": "CLOSE",
"Modal.closeModal": "Close modal",
"OrderDetailsPanel.orderAcceptedStatus": "{providerName} accepted the booking.",
"OrderDetailsPanel.orderAcceptedTitle": "You have booked {title}.",
@ -190,9 +191,12 @@
"TopbarDesktop.logout": "Log out",
"TopbarDesktop.logo": "Logo",
"TopbarDesktop.signup": "Sign up",
"TopbarMobileMenu.greeting": "Hello {firstName}",
"TopbarMobileMenu.inboxLink": "Inbox",
"TopbarMobileMenu.loginLink": "Log in",
"TopbarMobileMenu.logoutLink": "Log out",
"TopbarMobileMenu.newListingLink": "+ Add your sauna",
"TopbarMobileMenu.signupLink": "Sign up"
"TopbarMobileMenu.signupLink": "Sign up",
"TopbarMobileMenu.signupOrLogin": "{signup} or {login}",
"TopbarMobileMenu.unauthorizedGreeting": "Hello there,{lineBreak}would you like to {signupOrLogin}?"
}