Merge pull request #205 from sharetribe/topbar-mobile-fixes

Mobile topbar fixes
This commit is contained in:
Vesa Luusua 2017-06-06 22:54:25 +03:00 committed by GitHub
commit d7794a7bc8
12 changed files with 166 additions and 108 deletions

View file

@ -27,27 +27,26 @@
overflow: hidden;
}
/* Header section for Modal */
.header {
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.title {
margin: 24px;
flex-grow: 1;
}
.close {
/* Position inside modal */
position: absolute;
top: 0;
right: 0;
/* Safari didn't know how to baseline-align svg icon and text */
display: flex;
align-items: baseline;
align-items: flex-start;
width: auto;
background-color: transparent;
/* Sizing (touch area) */
padding: 24px;
color: var(--matterColor);
border: 0;
composes: h6Font from '../../marketplace.css';
/* Colors */
background-color: transparent;
color: var(--matterColor);
cursor: pointer;
&:enabled:hover {
background-color: transparent;
@ -62,8 +61,16 @@
}
}
.closeText {
/* Font */
composes: h6Font from '../../marketplace.css';
}
.closeIcon {
display: inline-block;
margin-left: 12px;
padding: 6px 0 6px;
box-sizing: content-box;
}
.content {

View file

@ -46,24 +46,14 @@ export class ModalComponent extends Component {
intl,
isClosedClassName,
isOpen,
title,
} = this.props;
const closeModalMessage = intl.formatMessage({ id: 'Modal.closeModal' });
const modalTitle = title ? <h2 className={css.title}>{title}</h2> : null;
const closeBtn = (
<Button onClick={this.handleClose} rootClassName={css.close} title={closeModalMessage}>
<span><FormattedMessage id="Modal.close" /></span>
<CloseIcon rootClassName={css.closeIcon} />
</Button>
);
// Header
const header = isOpen
? <div className={css.header}>
{modalTitle}
{closeBtn}
</div>
const closeBtn = isOpen
? <Button onClick={this.handleClose} rootClassName={css.close} title={closeModalMessage}>
<span className={css.closeText}><FormattedMessage id="Modal.close" /></span>
<CloseIcon rootClassName={css.closeIcon} />
</Button>
: null;
// Modal uses given styles to wrap child components.
@ -74,7 +64,7 @@ export class ModalComponent extends Component {
const classes = classNames(modalClass, className);
return (
<div className={classes}>
{header}
{closeBtn}
<div className={css.content}>
{children}
</div>
@ -89,7 +79,6 @@ ModalComponent.defaultProps = {
isClosedClassName: css.isClosed,
isOpen: false,
onClose: null,
title: null,
};
const { bool, func, node, string } = PropTypes;
@ -101,7 +90,6 @@ ModalComponent.propTypes = {
isClosedClassName: string,
isOpen: bool,
onClose: func.isRequired,
title: string,
// eslint-disable-next-line react/no-unused-prop-types
togglePageClassNames: func.isRequired,

View file

@ -26,15 +26,14 @@
*/
.topbarDesktopLabel {
display: inline-block;
margin: 24px 0 16px 0;
margin: 20px 0;
text-decoration: inherit;
}
/* logo */
.logoLink {
flex-shrink: 0;
display: flex;
align-items: center;
padding: 16px 0 23px 0;
height: 100%;
margin-right: 24px;
}

View file

@ -4,7 +4,7 @@
display: flex;
flex-direction: column;
height: 100vh;
padding: 24px;
padding: 0 24px;
}
.content {
@ -12,16 +12,21 @@
flex-shrink: 0;
display: flex;
flex-direction: column;
margin: 24px 0;
align-items: flex-start;
/* Position content */
margin-top: 24px;
}
.footer {
flex-basis: 66px;
flex-shrink: 0;
margin-bottom: 24px;
}
.avatar {
flex-shrink: 0;
margin-top: 72px;
width: 120px;
height: 120px;
border-radius: 50%;
@ -44,16 +49,21 @@
}
.logoutButton {
/* Position component */
margin: 6px 0;
/* Logout font is smaller and gray since the action is not recommended. */
composes: h3Font from '../../marketplace.css';
text-align: left;
color: var(--matterColorAnti);
margin-top: 6px;
}
.inbox {
margin-top: auto;
margin-bottom: 24px;
/* Font */
composes: h1Font from '../../marketplace.css';
color: var(--marketplaceColor);
margin-top: auto;
}
/* TODO createNewListingLink camouflages as a button. */

View file

@ -38,10 +38,18 @@
composes: withPadding;
@media (--desktopViewport) {
padding: 56px 0 0 16px;
padding: 48px 0 0 16px;
}
}
.examplesList {
margin: 24px 0;
}
.example {
padding: 0;
}
.link {
color: var(--marketplaceColor);
}
@ -63,23 +71,31 @@
.typographyContent {}
.baselines {
background-image: url('data:image/svg+xml;utf8,<svg width="10" height="24" viewBox="0 0 10 24" xmlns="http://www.w3.org/2000/svg"><path d="M0 5h10M0 11h10M0 17h10" stroke="#ccc"/><path d="M0 23h10" stroke="#ddd" stroke-width="1"/></svg>');
background-image: url('data:image/svg+xml;utf8,<svg width="10" height="24" viewBox="0 0 10 24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h10M0 06h10M0 12h10" stroke="#ccc" shape-rendering="crispEdges" /><path d="M0 18h10" stroke="#ddd" stroke-width="1" shape-rendering="crispEdges" /></svg>');
background-repeat: repeat;
@media (--desktopViewport) {
background-image: url('data:image/svg+xml;utf8,<svg width="10" height="24" viewBox="0 0 10 24" xmlns="http://www.w3.org/2000/svg"><path d="M0 7h10M0 15h10M0" stroke="#ccc"/><path d="M0 23h10" stroke="#ddd" stroke-width="1"/></svg>');
background-image: url('data:image/svg+xml;utf8,<svg width="10" height="24" viewBox="0 0 10 24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h10" stroke="#ddd" stroke-width="1" shape-rendering="crispEdges" /><path d="M0 08h10M0 16h10M0" stroke="#ccc" shape-rendering="crispEdges" /></svg>');
background-repeat: repeat;
}
}
.spacing2x {
margin: calc(2 * var(--spacingUnit)) 0;
@media (--desktopViewport) {
margin: calc(2 * var(--spacingUnitDesktop)) 0;
}
}
.fontsContainer {
display: flex;
flex-wrap: wrap;
margin-top: calc(4 * var(--spacingUnit));
@media (--desktopViewport) {
margin-top: calc(3 * var(--spacingUnitDesktop));
}
}
.fontCard {
@ -87,13 +103,14 @@
display: flex;
flex-direction: column;
/**
* FontCard contains 4px worth of borders, which needs to be factored in since we use
* box-sizing: border-box;
* In this case, we'll adjust margin-bottoms (24px - 4px = 20px)
*/
margin-bottom: calc(4 * var(--spacingUnit) - 4px);
margin-right: calc(2 * var(--spacingUnit));
margin-bottom: calc(2 * var(--spacingUnit) + 2px);
@media (--desktopViewport) {
margin-right: calc(2 * var(--spacingUnitDesktop));
margin-bottom: calc(2 * var(--spacingUnitDesktop) + 2px);
}
}
.element {
@ -106,12 +123,16 @@
flex-grow: 1;
width: 100%;
background-color: #f1f1f1;
padding: calc(2 * var(--spacingUnit));
padding: calc(2 * var(--spacingUnit) - 3px) calc(2 * var(--spacingUnit));
border-style: solid;
border-color: #aaa;
border-width: 1px;
border-top-color: transparent;
@media (--desktopViewport) {
padding: calc(2 * var(--spacingUnitDesktop) - 3px) calc(2 * var(--spacingUnitDesktop));
}
}
/* Colors.example */
@ -150,6 +171,10 @@
width: 100%;
background-color: #fff;
padding: calc(2 * var(--spacingUnit));
@media (--desktopViewport) {
padding: calc(2 * var(--spacingUnitDesktop) - 2px) calc(2 * var(--spacingUnitDesktop));
}
}
.marketplaceColorBackground {

View file

@ -23,7 +23,7 @@ const Example = props => {
const exampleWrapperClassName = useDefaultWrapperStyles ? css.defaultWrapperStyles : '';
const desc = description ? <p className={css.withMargin}>Description: {description}</p> : null;
return (
<li>
<li className={css.example}>
<h3 className={css.withMargin}>
<NamedLink
name="StyleguideComponent"
@ -192,7 +192,7 @@ const StyleguidePage = props => {
}
const html = examples.length > 0
? <ul>
? <ul className={css.examplesList}>
{examples.map(ex => <Example key={`${ex.componentName}/${ex.exampleName}`} {...ex} />)}
</ul>
: <p>No examples with filter: {componentName}/{exampleName}</p>;

View file

@ -30,72 +30,70 @@ const Fonts = () => {
const heroTitleFontStyling = `Mobile styles:
font-size: 48px;
line-height: 54px;
padding: 5px 0 1px;
padding: 1px 0 5px;
Desktop styles:
font-size: 90px;
line-height: 96px;
padding: 0;`;
padding: 1px 0 7px;`;
const h1FontStyling = `Mobile styles:
font-size: 30px;
line-height: 36px;
padding: 3.5px 0 2.5px;
Desktop styles:
font-size: 48px;
line-height: 56px;
padding: 6px 0 2px;`;
line-height: 56px;`;
const h2FontStyling = `Mobile styles:
font-size: 24px;
line-height: 30px;
padding: 3px 0 3px;
padding: 5px 0 1px;
Desktop styles:
font-size: 24px;
line-height: 32px;
padding: 4px 0 4px;`;
padding: 5px 0 3px;`;
const h3FontStyling = `Mobile styles:
font-size: 20px;
line-height: 24px;
padding: 2px 0 4px;
padding: 4px 0 2px;
Desktop styles:
font-size: 20px;
line-height: 24px;
padding: 2px 0 6px;`;
padding: 4px 0 4px;`;
const h4FontStyling = `Mobile styles:
font-size: 16px;
line-height: 24px;
padding: 3.5px 0 2.5px;
padding: 0;
Desktop styles:
font-size: 16px;
line-height: 24px;
padding: 4px 0 4px;`;
padding: 5px 0 3px;`;
const h5FontStyling = `Mobile styles:
font-size: 14px;
line-height: 18px;
padding: 1.5px 0 4.5px;
padding: 4px 0 2px;
Desktop styles:
font-size: 14px;
line-height: 18px;
padding: 7px 0 1px;`;
line-height: 16px;
padding: 2px 0 6px;`;
const h6FontStyling = `Mobile styles:
font-size: 12px;
line-height: 18px;
padding: 2px 0 4px;
padding: 4px 0 2px;
Desktop styles:
font-size: 12px;
line-height: 18px;
padding: 6px 0 2px;`;
line-height: 16px;
padding: 2px 0 6px;`;
const bodyFontStyling = `Mobile styles:
font-size: 18px;

View file

@ -11,14 +11,14 @@ const MenuIcon = props => {
<svg
className={classes}
width="18"
height="12"
viewBox="0 0 18 12"
height="18"
viewBox="0 0 18 18"
xmlns="http://www.w3.org/2000/svg"
>
<g fillRule="evenodd">
<rect width="18" height="2" rx="1" />
<rect y="5" width="18" height="2" rx="1" />
<rect y="10" width="18" height="2" rx="1" />
<rect y="2" width="18" height="2" rx="1" />
<rect y="7" width="18" height="2" rx="1" />
<rect y="12" width="18" height="2" rx="1" />
</g>
</svg>
);

View file

@ -1,5 +1,10 @@
@import '../../marketplace.css';
:root {
--topbarHeight: 60px;
--logoHeight: 25px;
}
.root {
width: 100%;
}
@ -8,14 +13,13 @@
/* Size */
width: 100%;
height: 60px;
height: var(--topbarHeight);
/* Layout for child components */
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 0 12px;
/* fill */
background-color: var(--matterColorLight);
@ -29,7 +33,8 @@
}
.home {
padding: 18px;
display: flex;
padding: calc((var(--topbarHeight) - var(--logoHeight)) / 2) 24px;
}
.logoutButton {
@ -37,11 +42,35 @@
}
/* Child component's size (and positioning) should be given here */
.hamburgerMenu,
.menu,
.searchMenu {
display: flex;
align-items: center;
width: 44px;
width: 66px;
padding: 12px 24px;
border-width: 0px;
background-color: transparent;
/* Font */
composes: h5Font from '../../marketplace.css';
color: var(--matterColor);
/* Hovers */
&:enabled {
cursor: pointer;
}
&:enabled:hover,
&:enabled:active {
background-color: transparent;
}
&:disabled {
background-color: transparent;
cursor: auto;
}
}
.menuIcon,
.searchMenuIcon {
margin: 9px 0;
}
.desktop {
@ -61,6 +90,7 @@
.searchContainer {
position: relative;
height: 100%;
margin-top: 72px;
}
.mobileHelp {
@ -70,7 +100,7 @@
/* Absolute position to avoid affecting the layout of the autocomplete
predictions list */
position: absolute;
top: 115px;
top: 114px;
/* Pull text behind search suggestions */
z-index: -1;

View file

@ -4,7 +4,7 @@ import { connect } from 'react-redux';
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
import { pickBy } from 'lodash';
import { logout, authenticationInProgress } from '../../ducks/Auth.duck';
import { FlatButton, Modal, NamedLink, TopbarDesktop, TopbarMobileMenu } from '../../components';
import { Button, Modal, NamedLink, TopbarDesktop, TopbarMobileMenu } from '../../components';
import { TopbarSearchForm } from '../../containers';
import { withFlattenedRoutes } from '../../util/contextHelpers';
import { parse, stringify } from '../../util/urlHelpers';
@ -124,15 +124,15 @@ class TopbarComponent extends Component {
return (
<div className={css.root}>
<div className={css.container}>
<FlatButton className={css.hamburgerMenu} onClick={this.handleMobileMenuOpen}>
<MenuIcon title={intl.formatMessage({ id: 'Topbar.menuIcon' })} />
</FlatButton>
<Button rootClassName={css.menu} onClick={this.handleMobileMenuOpen}>
<MenuIcon className={css.menuIcon} title={intl.formatMessage({ id: 'Topbar.menuIcon' })} />
</Button>
<NamedLink className={css.home} name="LandingPage">
<LogoIcon title={intl.formatMessage({ id: 'Topbar.logoIcon' })} />
</NamedLink>
<FlatButton className={css.searchMenu} onClick={this.handleMobileSearchOpen}>
<SearchIcon title={intl.formatMessage({ id: 'Topbar.searchIcon' })} />
</FlatButton>
<Button rootClassName={css.searchMenu} onClick={this.handleMobileSearchOpen}>
<SearchIcon className={css.searchMenuIcon} title={intl.formatMessage({ id: 'Topbar.searchIcon' })} />
</Button>
</div>
<div className={css.desktop}>
<TopbarDesktop
@ -147,6 +147,7 @@ class TopbarComponent extends Component {
/>
</div>
<Modal
id="TopbarMobileMenu"
isOpen={isMobileMenuOpen}
onClose={this.handleMobileMenuClose}
togglePageClassNames={togglePageClassNames}
@ -154,6 +155,7 @@ class TopbarComponent extends Component {
{authInProgress ? null : mobileMenu}
</Modal>
<Modal
id="TopbarMobileSearch"
isOpen={isMobileSearchOpen}
onClose={this.handleMobileSearchClose}
togglePageClassNames={togglePageClassNames}

View file

@ -22,7 +22,7 @@
height: var(--topbarHeight);
border: none;
padding-top: 0;
padding-bottom: 0;
padding-bottom: 3px;
}
.mobilePredictions {

View file

@ -61,13 +61,13 @@ h1, h2, h3, h4, h5, h6, p, pre {
font-weight: 700; /* Bold */
font-size: 48px;
line-height: 54px;
padding: 5px 0 1px; /* 5px + 1px = 6px */;
padding: 1px 0 5px; /* 1px + 5px = 6px */;
letter-spacing: -1px;
@media (--desktopViewport) {
font-size: 90px;
line-height: 96px;
padding: 0;
padding: 1px 0 7px; /* 1px + 7px = 8px */
letter-spacing: -2px;
}
}
@ -79,7 +79,7 @@ h1,
font-weight: 600; /* SemiBold */
font-size: 30px;
line-height: 36px;
padding: 3.5px 0 2.5px; /* 3.5px + 2.5px = 6px */
padding: 0;
letter-spacing: -0.5px;
@media (--desktopViewport) {
@ -96,12 +96,12 @@ h2,
font-weight: 600; /* SemiBold */
font-size: 24px;
line-height: 30px;
padding: 3px 0 3px; /* 3px + 3px = 6px */
padding: 5px 0 1px; /* 5px + 1px = 6px */
letter-spacing: -0.3px;
@media (--desktopViewport) {
line-height: 32px;
padding: 4px 0 4px; /* 4px + 4px = 8px */
padding: 5px 0 3px;; /* 5px + 3px = 8px */
}
}
@ -111,11 +111,11 @@ h3,
font-weight: 600; /* SemiBold */
font-size: 20px;
line-height: 24px;
padding: 2px 0 4px; /* 2px + 4px = 6px */
padding: 4px 0 2px; /* 4px + 2px = 6px */
letter-spacing: -0.2px;
@media (--desktopViewport) {
padding: 2px 0 6px; /* 2px + 6px = 8px */
padding: 4px 0 4px; /* 4px + 4px = 8px */
}
}
@ -125,11 +125,11 @@ h4,
font-weight: 500; /* Medium */
font-size: 16px;
line-height: 24px;
padding: 3.5px 0 2.5px; /* 3.5px + 2.5px = 6px */
padding: 0;
letter-spacing: 0;
@media (--desktopViewport) {
padding: 4px 0 4px; /* 4px + 4px = 8px */
padding: 5px 0 3px; /* 5px + 3px = 8px */
}
}
@ -139,12 +139,12 @@ h5,
font-weight: 400; /* Regular */
font-size: 14px;
line-height: 18px;
padding: 1.5px 0 4.5px; /* 1.5px + 4.5px = 6px */
padding: 4px 0 2px; /* 4px + 2px = 6px */
letter-spacing: 0;
@media (--desktopViewport) {
line-height: 16px;
padding: 1px 0 7px; /* 1px + 7px = 8px */
padding: 2px 0 6px; /* 2px + 6px = 8px */
}
}
@ -154,7 +154,7 @@ h6,
font-weight: 700; /* Bold */
font-size: 12px;
line-height: 18px;
padding: 2px 0 4px; /* 2px + 4px = 6px */
padding: 4px 0 2px; /* 4px + 2px = 6px */
letter-spacing: 1.5px;
text-transform: uppercase;
@ -175,13 +175,13 @@ li,
font-weight: 500; /* Medium */
font-size: 18px;
line-height: 24px;
padding: 2.5px 0 3.5px; /* 2.5px + 3.5px = 6px */
padding: 0;
letter-spacing: -0.1px;
@media (--desktopViewport) {
font-size: 20px;
line-height: 32px;
padding: 6px 0 2px; /* 6px + 2px = 8px */
padding: 0;
}
}
@ -190,12 +190,12 @@ li,
font-weight: 400; /* Regular */
font-size: 13px;
line-height: 18px;
padding: 2px 0 4px; /* 2px + 4px = 6px */
padding: 3.5px 0 2.5px; /* 3.5px + 2.5px = 6px */
letter-spacing: -0.1px;
@media (--desktopViewport) {
line-height: 16px;
padding: 1.5px 0 6.5px; /* 1.5px + 6.5px; = 8px */
padding: 2.5px 0 5.5px; /* 1.5px + 6.5px; = 8px */
}
}
@ -218,7 +218,6 @@ li,
font-weight: 700; /* Bold */
font-size: 14px;
line-height: 18px;
padding: 7.5px 0 4.5px;
letter-spacing: 0.1px;
}