mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 03:43:28 +10:00
Merge pull request #194 from sharetribe/desktop-topbar-draft
Desktop topbar draft
This commit is contained in:
commit
fbc61acd65
12 changed files with 347 additions and 2 deletions
127
src/components/TopbarDesktop/TopbarDesktop.css
Normal file
127
src/components/TopbarDesktop/TopbarDesktop.css
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
/* Desktop */
|
||||
.root {
|
||||
/* Size */
|
||||
width: 100%;
|
||||
height: 72px;
|
||||
|
||||
/* Layout for child components */
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
padding: 0 36px;
|
||||
|
||||
/* fill */
|
||||
background-color: var(--matterColorLight);
|
||||
|
||||
/* shadows */
|
||||
box-shadow: var(--boxShadowLight);
|
||||
}
|
||||
|
||||
/* Compose text label items on top of this */
|
||||
/* This stretches inline element (link) to take available vertical space (big hover area),
|
||||
* and align baselines, and passes text-decoration hover effect
|
||||
*/
|
||||
.topbarDesktopLabel {
|
||||
display: inline-block;
|
||||
margin: 24px 0 16px 0;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
/* logo */
|
||||
.logoLink {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 155px;
|
||||
height: 27px;
|
||||
}
|
||||
|
||||
/* Search */
|
||||
/* TODO This is placeholder, it needs Search component */
|
||||
.searchLink {
|
||||
min-width: 220px;
|
||||
align-self: flex-start;
|
||||
height: 100%;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.search {
|
||||
composes: topbarDesktopLabel;
|
||||
composes: bodyFont from '../../marketplace.css';
|
||||
color: var(--matterColor);
|
||||
}
|
||||
|
||||
/* Spacer */
|
||||
/* Extra space is gathered between search and createListingLink */
|
||||
.spacer {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/* Create listing (CTA for providers) */
|
||||
.createListingLink {
|
||||
align-self: flex-start;
|
||||
height: 100%;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.createListing {
|
||||
composes: topbarDesktopLabel;
|
||||
composes: bodyFont from '../../marketplace.css';
|
||||
color: var(--marketplaceColor);
|
||||
}
|
||||
|
||||
/* Inbox */
|
||||
.inboxLink {
|
||||
align-self: flex-start;
|
||||
height: 100%;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.inbox {
|
||||
composes: topbarDesktopLabel;
|
||||
composes: bodyFont from '../../marketplace.css';
|
||||
color: var(--matterColor);
|
||||
}
|
||||
|
||||
/* Profile menu */
|
||||
/* TODO This is placeholder, it needs Menu component */
|
||||
.avatarLink {
|
||||
align-self: flex-start;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 41px;
|
||||
height: 41px;
|
||||
}
|
||||
|
||||
/* Authentication */
|
||||
.signupLink {
|
||||
align-self: flex-start;
|
||||
height: 100%;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.loginLink {
|
||||
align-self: flex-start;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.signup,
|
||||
.login {
|
||||
composes: topbarDesktopLabel;
|
||||
composes: bodyFont from '../../marketplace.css';
|
||||
color: var(--matterColor);
|
||||
}
|
||||
14
src/components/TopbarDesktop/TopbarDesktop.example.js
Normal file
14
src/components/TopbarDesktop/TopbarDesktop.example.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { fakeIntl } from '../../util/test-data';
|
||||
import TopbarDesktop from './TopbarDesktop';
|
||||
|
||||
|
||||
export const AuthenticatedDesktopTopbar = {
|
||||
component: TopbarDesktop,
|
||||
props: {
|
||||
isAuthenticated: true,
|
||||
currentUserHasListings: true,
|
||||
name: 'John Doe',
|
||||
intl: fakeIntl,
|
||||
},
|
||||
group: 'navigation',
|
||||
};
|
||||
82
src/components/TopbarDesktop/TopbarDesktop.js
Normal file
82
src/components/TopbarDesktop/TopbarDesktop.js
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import React, { PropTypes } from 'react';
|
||||
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { Avatar, NamedLink } from '../../components';
|
||||
|
||||
import logo from './images/saunatime-logo.png';
|
||||
import css from './TopbarDesktop.css';
|
||||
|
||||
const TopbarDesktop = props => {
|
||||
const { className, rootClassName, currentUserHasListings, intl, isAuthenticated, name } = props;
|
||||
|
||||
const rootClass = rootClassName || css.root;
|
||||
const classes = classNames(rootClass, className);
|
||||
|
||||
// TODO This is just a placeholder
|
||||
const search = (
|
||||
<div className={css.searchLink}>
|
||||
<span className={css.search}>Search should be here</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
const inboxLink = isAuthenticated
|
||||
? <NamedLink
|
||||
className={css.inboxLink}
|
||||
name="InboxPage"
|
||||
params={{ tab: currentUserHasListings ? 'sales' : 'orders' }}
|
||||
>
|
||||
<span className={css.inbox}><FormattedMessage id="TopbarDesktop.inbox" /></span>
|
||||
</NamedLink>
|
||||
: null;
|
||||
|
||||
// TODO This is just a placeholder
|
||||
const profileMenu = isAuthenticated
|
||||
? <div className={css.avatarLink}> <Avatar className={css.avatar} name={name} /></div>
|
||||
: null;
|
||||
|
||||
const signupLink = isAuthenticated
|
||||
? null
|
||||
: <NamedLink name="SignupPage" className={css.signupLink}>
|
||||
<span className={css.signup}><FormattedMessage id="TopbarDesktop.signup" /></span>
|
||||
</NamedLink>;
|
||||
|
||||
const loginLink = isAuthenticated
|
||||
? null
|
||||
: <NamedLink name="LoginPage" className={css.loginLink}>
|
||||
<span className={css.login}><FormattedMessage id="TopbarDesktop.login" /></span>
|
||||
</NamedLink>;
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<NamedLink className={css.logoLink} name="LandingPage">
|
||||
<img className={css.logo} src={logo} alt={intl.formatMessage({ id: 'TopbarDesktop.logo' })} />
|
||||
</NamedLink>
|
||||
{search}
|
||||
<div className={css.spacer} />
|
||||
<NamedLink className={css.createListingLink} name="NewListingPage">
|
||||
<span className={css.createListing}><FormattedMessage id="TopbarDesktop.createListing" /></span>
|
||||
</NamedLink>
|
||||
{inboxLink}
|
||||
{profileMenu}
|
||||
{signupLink}
|
||||
{loginLink}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
TopbarDesktop.defaultProps = { name: '', className: null, rootClassName: '' };
|
||||
|
||||
const { bool, string } = PropTypes;
|
||||
|
||||
TopbarDesktop.propTypes = {
|
||||
className: string,
|
||||
currentUserHasListings: bool.isRequired,
|
||||
isAuthenticated: bool.isRequired,
|
||||
name: string,
|
||||
rootClassName: string,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(TopbarDesktop);
|
||||
25
src/components/TopbarDesktop/TopbarDesktop.test.js
Normal file
25
src/components/TopbarDesktop/TopbarDesktop.test.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import React from 'react';
|
||||
import { fakeIntl } from '../../util/test-data';
|
||||
import { renderDeep } from '../../util/test-helpers';
|
||||
import { RoutesProvider } from '../../components';
|
||||
import routesConfiguration from '../../routesConfiguration';
|
||||
import { flattenRoutes } from '../../util/routes';
|
||||
import TopbarDesktop from './TopbarDesktop';
|
||||
|
||||
describe('TopbarDesktop', () => {
|
||||
it('data matches snapshot', () => {
|
||||
const flattenedRoutes = flattenRoutes(routesConfiguration);
|
||||
const tree = renderDeep(
|
||||
<RoutesProvider flattenedRoutes={flattenedRoutes}>
|
||||
<TopbarDesktop
|
||||
isAuthenticated
|
||||
currentUserHasListings
|
||||
name="John Doe"
|
||||
intl={fakeIntl}
|
||||
/>
|
||||
</RoutesProvider>
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
exports[`TopbarDesktop data matches snapshot 1`] = `
|
||||
<div
|
||||
className="">
|
||||
<a
|
||||
className="NamedLink_active"
|
||||
href="/"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<img
|
||||
alt="Logo"
|
||||
className={undefined}
|
||||
src="saunatime-logo.png" />
|
||||
</a>
|
||||
<div
|
||||
className={undefined}>
|
||||
<span
|
||||
className={undefined}>
|
||||
Search should be here
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className={undefined} />
|
||||
<a
|
||||
className=""
|
||||
href="/l/new"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span
|
||||
className={undefined}>
|
||||
<span>
|
||||
+ Add your sauna
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
className=""
|
||||
href="/inbox/sales"
|
||||
onClick={[Function]}
|
||||
style={Object {}}>
|
||||
<span
|
||||
className={undefined}>
|
||||
<span>
|
||||
Inbox
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
<div
|
||||
className={undefined}>
|
||||
|
||||
<img
|
||||
alt="John Doe"
|
||||
className=""
|
||||
src="wireframeAvatar.svg" />
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
BIN
src/components/TopbarDesktop/images/saunatime-logo.png
Normal file
BIN
src/components/TopbarDesktop/images/saunatime-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
|
|
@ -40,6 +40,7 @@ import Select from './Select/Select';
|
|||
import StripeBankAccountToken from './StripeBankAccountToken/StripeBankAccountToken';
|
||||
import TabNav from './TabNav/TabNav';
|
||||
import Tabs from './Tabs/Tabs';
|
||||
import TopbarDesktop from './TopbarDesktop/TopbarDesktop';
|
||||
import ValidationError from './ValidationError/ValidationError';
|
||||
|
||||
export {
|
||||
|
|
@ -87,5 +88,6 @@ export {
|
|||
StripeBankAccountToken,
|
||||
TabNav,
|
||||
Tabs,
|
||||
TopbarDesktop,
|
||||
ValidationError,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -20,6 +22,10 @@
|
|||
|
||||
/* shadows */
|
||||
box-shadow: 0 1px 1px 0 #dcdcdc;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.home {
|
||||
|
|
@ -55,3 +61,11 @@
|
|||
.searchForm {
|
||||
margin: 2rem;
|
||||
}
|
||||
|
||||
.desktop {
|
||||
display: none;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { connect } from 'react-redux';
|
|||
import { intlShape, injectIntl } from 'react-intl';
|
||||
import { pickBy } from 'lodash';
|
||||
import { logout, authenticationInProgress } from '../../ducks/Auth.duck';
|
||||
import { FlatButton, MobileMenu, Modal, NamedLink } from '../../components';
|
||||
import { FlatButton, MobileMenu, Modal, NamedLink, TopbarDesktop } from '../../components';
|
||||
import { SearchForm } from '../../containers';
|
||||
import { withFlattenedRoutes } from '../../util/contextHelpers';
|
||||
import { parse, stringify } from '../../util/urlHelpers';
|
||||
|
|
@ -135,6 +135,14 @@ class TopbarComponent extends Component {
|
|||
<img src={searchIcon} alt={intl.formatMessage({ id: 'Topbar.searchIcon' })} />
|
||||
</FlatButton>
|
||||
</div>
|
||||
<div className={css.desktop}>
|
||||
<TopbarDesktop
|
||||
currentUserHasListings={currentUserHasListings}
|
||||
intl={intl}
|
||||
isAuthenticated={isAuthenticated}
|
||||
name={name}
|
||||
/>
|
||||
</div>
|
||||
<Modal
|
||||
isOpen={isMobileMenuOpen}
|
||||
onClose={this.handleMobileMenuClose}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import * as StripeBankAccountToken
|
|||
from './components/StripeBankAccountToken/StripeBankAccountToken.example';
|
||||
import * as TabNav from './components/TabNav/TabNav.example';
|
||||
import * as Tabs from './components/Tabs/Tabs.example';
|
||||
import * as TopbarDesktop from './components/TopbarDesktop/TopbarDesktop.example';
|
||||
|
||||
// containers
|
||||
import * as BookingDatesForm from './containers/BookingDatesForm/BookingDatesForm.example';
|
||||
|
|
@ -72,5 +73,6 @@ export {
|
|||
StripePaymentForm,
|
||||
TabNav,
|
||||
Tabs,
|
||||
TopbarDesktop,
|
||||
Typography,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -133,6 +133,12 @@ pre,
|
|||
letter-spacing: -0.1px;
|
||||
|
||||
/* TODO Desktop styles needs to be extracted */
|
||||
@media (min-width: 768px) {
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
padding: 2px 0 6px 0; /* 2px + 6px = 8px */
|
||||
}
|
||||
}
|
||||
|
||||
.tinyFont {
|
||||
|
|
@ -155,6 +161,10 @@ html,
|
|||
/* NORMALIZATIONS for other elements */
|
||||
/* TODO */
|
||||
|
||||
html {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
|
|
|
|||
|
|
@ -188,5 +188,10 @@
|
|||
"StripePaymentForm.stripe.validation_error.processing_error": "An error occurred while processing the card.",
|
||||
"StripePaymentForm.submitPaymentInfo": "Send request",
|
||||
"Topbar.menuIcon": "Open menu",
|
||||
"Topbar.searchIcon": "Open search"
|
||||
"Topbar.searchIcon": "Open search",
|
||||
"TopbarDesktop.createListing": "+ Add your sauna",
|
||||
"TopbarDesktop.inbox": "Inbox",
|
||||
"TopbarDesktop.login": "Log in",
|
||||
"TopbarDesktop.logo": "Logo",
|
||||
"TopbarDesktop.signup": "Sign up"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue