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 00000000..b8f5ed40 Binary files /dev/null and b/src/components/TopbarDesktop/images/saunatime-logo.png differ 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" }