From 2b0a57c3908643f0fef75ebec0f5b7c0b8c8902a Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 30 May 2017 15:11:00 +0300 Subject: [PATCH] TopbarDesktop as separate component --- .../TopbarDesktop/TopbarDesktop.css | 131 ++++++++++++++++++ .../TopbarDesktop/TopbarDesktop.example.js | 14 ++ src/components/TopbarDesktop/TopbarDesktop.js | 82 +++++++++++ .../TopbarDesktop/TopbarDesktop.test.js | 25 ++++ .../__snapshots__/TopbarDesktop.test.js.snap | 56 ++++++++ .../TopbarDesktop/images/saunatime-logo.png | Bin 0 -> 7569 bytes src/components/index.js | 2 + src/examples.js | 2 + src/translations/en.json | 7 +- 9 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 src/components/TopbarDesktop/TopbarDesktop.css create mode 100644 src/components/TopbarDesktop/TopbarDesktop.example.js create mode 100644 src/components/TopbarDesktop/TopbarDesktop.js create mode 100644 src/components/TopbarDesktop/TopbarDesktop.test.js create mode 100644 src/components/TopbarDesktop/__snapshots__/TopbarDesktop.test.js.snap create mode 100644 src/components/TopbarDesktop/images/saunatime-logo.png diff --git a/src/components/TopbarDesktop/TopbarDesktop.css b/src/components/TopbarDesktop/TopbarDesktop.css new file mode 100644 index 00000000..9a57b172 --- /dev/null +++ b/src/components/TopbarDesktop/TopbarDesktop.css @@ -0,0 +1,131 @@ +@import '../../marketplace.css'; + +/* Desktop */ +.root { + display: none; + + @media (min-width: 768px) { + /* 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); +} diff --git a/src/components/TopbarDesktop/TopbarDesktop.example.js b/src/components/TopbarDesktop/TopbarDesktop.example.js new file mode 100644 index 00000000..dc50f621 --- /dev/null +++ b/src/components/TopbarDesktop/TopbarDesktop.example.js @@ -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', +}; diff --git a/src/components/TopbarDesktop/TopbarDesktop.js b/src/components/TopbarDesktop/TopbarDesktop.js new file mode 100644 index 00000000..727098c9 --- /dev/null +++ b/src/components/TopbarDesktop/TopbarDesktop.js @@ -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 = ( +
+ Search should be here +
+ ); + + const inboxLink = isAuthenticated + ? + + + : null; + + // TODO This is just a placeholder + const profileMenu = isAuthenticated + ?
+ : null; + + const signupLink = isAuthenticated + ? null + : + + ; + + const loginLink = isAuthenticated + ? null + : + + ; + + return ( +
+ + {intl.formatMessage({ + + {search} +
+ + + + {inboxLink} + {profileMenu} + {signupLink} + {loginLink} +
+ ); +}; + +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); diff --git a/src/components/TopbarDesktop/TopbarDesktop.test.js b/src/components/TopbarDesktop/TopbarDesktop.test.js new file mode 100644 index 00000000..a56c64a9 --- /dev/null +++ b/src/components/TopbarDesktop/TopbarDesktop.test.js @@ -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( + + + + ); + expect(tree).toMatchSnapshot(); + }); + +}); diff --git a/src/components/TopbarDesktop/__snapshots__/TopbarDesktop.test.js.snap b/src/components/TopbarDesktop/__snapshots__/TopbarDesktop.test.js.snap new file mode 100644 index 00000000..39cbadbd --- /dev/null +++ b/src/components/TopbarDesktop/__snapshots__/TopbarDesktop.test.js.snap @@ -0,0 +1,56 @@ +exports[`TopbarDesktop data matches snapshot 1`] = ` +
+ + Logo + +
+ + Search should be here + +
+
+ + + + + Add your sauna + + + + + + + Inbox + + + +
+ + John Doe +
+
+`; diff --git a/src/components/TopbarDesktop/images/saunatime-logo.png b/src/components/TopbarDesktop/images/saunatime-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b8f5ed40dccdcdfd94d369c439c761057b42055a GIT binary patch literal 7569 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 literal 0 HcmV?d00001 diff --git a/src/components/index.js b/src/components/index.js index ff3d06b6..976575fd 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -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, }; diff --git a/src/examples.js b/src/examples.js index cb139c66..92635dbb 100644 --- a/src/examples.js +++ b/src/examples.js @@ -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, }; diff --git a/src/translations/en.json b/src/translations/en.json index 27d663f3..9069ca3a 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -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" }