Skip to content

Commit

Permalink
Merge pull request #78 from vtex-apps/feature/future-header
Browse files Browse the repository at this point in the history
Feature/future header
  • Loading branch information
lbebber committed Mar 28, 2019
2 parents c9a4587 + e0dff5c commit 999ec23
Show file tree
Hide file tree
Showing 32 changed files with 406 additions and 144 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [2.11.0] - 2019-03-28

### Added
- Added new experimental `header-layout` blocks, under an `unstable--` flag.
- Support for new experimental `menu` block, under an `unstable--` flag.

### Changed
- All previously required blocks are now simply allowed.

## Fixed
- Fixed bug on legacy header where it would be in desktop mode on mobile devices.

## [2.10.6] - 2019-03-26

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
@@ -1,7 +1,7 @@
{
"vendor": "vtex",
"name": "store-header",
"version": "2.10.6",
"version": "2.11.0",
"title": "VTEX Store Header",
"defaultLocale": "pt-BR",
"description": "The VTEX Store Header component",
Expand Down
3 changes: 3 additions & 0 deletions react/Border.js
@@ -0,0 +1,3 @@
import Border from './components/Border'

export default Border
3 changes: 3 additions & 0 deletions react/Layout.js
@@ -0,0 +1,3 @@
import Layout from './components/Layout'

export default Layout
3 changes: 3 additions & 0 deletions react/Row.js
@@ -0,0 +1,3 @@
import Row from './components/Row'

export default Row
3 changes: 3 additions & 0 deletions react/Spacer.js
@@ -0,0 +1,3 @@
import Spacer from './components/Spacer'

export default Spacer
4 changes: 4 additions & 0 deletions react/__mocks__/vtex.render-runtime.js
Expand Up @@ -10,6 +10,10 @@ export const useRuntime = () => {
return { hints, setHints, page, getSettings }
}

export const useChildBlock__unstable = ({ id }) => {
return null
}

export const ExtensionPoint = ({ id }) => (
<div className="extension-point-mock">{id}</div>
)
Expand Down
2 changes: 1 addition & 1 deletion react/__tests__/Header.test.js
@@ -1,7 +1,7 @@
import React from 'react'
import { render } from '@vtex/test-tools/react'
import { useRuntime } from 'vtex.render-runtime'
import Header from '../index'
import Header from '../legacy/index'

describe('Header Component', () => {
beforeEach(() => {
Expand Down
3 changes: 3 additions & 0 deletions react/components/Border.js
@@ -0,0 +1,3 @@
import React from 'react'

export default () => <div />
29 changes: 29 additions & 0 deletions react/components/CustomHeader.js
@@ -0,0 +1,29 @@
import React from 'react'
import { ExtensionPoint, useRuntime } from 'vtex.render-runtime'
import Media from 'react-media'

const CustomHeader = () => {
const { hints: { mobile } } = useRuntime()

if (!window || !window.matchMedia) {
return mobile ? (
<ExtensionPoint id="unstable--header-layout.mobile" />
) : (
<ExtensionPoint id="unstable--header-layout.desktop" />
)
}

return (
<React.Fragment>
<Media query="(max-width:40rem)">
{matches => matches ? (
<ExtensionPoint id="unstable--header-layout.mobile" />
) : (
<ExtensionPoint id="unstable--header-layout.desktop" />
)}
</Media>
</React.Fragment>
)
}

export default CustomHeader
9 changes: 9 additions & 0 deletions react/components/Layout.js
@@ -0,0 +1,9 @@
import React from 'react'

const Layout = ({ children }) => (
<React.Fragment>
{children}
</React.Fragment>
)

export default Layout
28 changes: 28 additions & 0 deletions react/components/Row.js
@@ -0,0 +1,28 @@
import React from 'react'
import classNames from 'classnames'
import { Container } from 'vtex.store-components'

const Row = ({ children, fullWidth, sticky, inverted }) => {
const content = (
<div className="w-100 flex items-center">
{children}
</div>
)

return (
<div
className={classNames('w-100 top-0', inverted ? 'bg-base--inverted c-on-base--inverted' : 'bg-base c-on-base', { 'z-999': sticky })}
style={{
// TODO: use `sticky` class once it's available on render
position: sticky ? 'sticky' : 'relative',
}}>
{fullWidth ? content : (
<Container className="w-100 flex">
{content}
</Container>
)}
</div>
)
}

export default Row
5 changes: 5 additions & 0 deletions react/components/Spacer.js
@@ -0,0 +1,5 @@
import React from "react"

const Spacer = () => <div className="flex flex-grow-1" />

export default Spacer
138 changes: 11 additions & 127 deletions react/index.js
@@ -1,140 +1,24 @@
import React, { Fragment, useEffect, useLayoutEffect, useState } from 'react'
import classNames from 'classnames'
import PropTypes from 'prop-types'
import { ExtensionPoint, useRuntime } from 'vtex.render-runtime'
import TopMenu from './components/TopMenu'
import Spacer from './components/Helpers/Spacer'
import { logo, collapsible, icons, searchBar, login } from './defaults'
import React from 'react'
import { useChildBlock__unstable } from 'vtex.render-runtime'
import LegacyHeader from './legacy'
import CustomHeader from './components/CustomHeader'

import styles from './store-header.css'
import useDevice from './hooks/useDevice'
const Header = props => {
const headerDesktop = !!useChildBlock__unstable({ id: 'unstable--header-layout.desktop' })
const headerMobile = !!useChildBlock__unstable({ id: 'unstable--header-layout.mobile' })

/**
* Main header component
*/
const Header = ({
leanWhen,
linkUrl,
logoUrl,
logoTitle,
logoSize,
showSearchBar,
showLogin,
iconClasses,
labelClasses,
collapsibleAnimation,
}) => {
const { page, getSettings } = useRuntime()
const { mobile } = useDevice()
const [containerHeight, setContainerHeight] = useState(null)
const { storeName } = getSettings('vtex.store')

useEffect(() => {
if (document) {
const containerElement = document.querySelector(
'.vtex-store-header-2-x-container'
)
const elementHeight = containerElement && containerElement.offsetHeight
setContainerHeight(elementHeight)
}
})

const topMenuOptions = {
linkUrl,
logoUrl,
logoTitle: logoTitle || storeName || '',
logoSize,
showSearchBar,
showLogin,
iconClasses,
labelClasses,
collapsibleAnimation,
mobile,
}

const isLeanMode = () => {
const acceptedPaths = new RegExp(leanWhen)
return acceptedPaths.test(page)
}

const containerClasses = classNames(
styles.container,
'fixed top-0 z-4 w-100',
isLeanMode() ? styles.leanMode : ''
)
const hasCustomHeader = headerDesktop || headerMobile

return (
<Fragment>
<div className={containerClasses}>
<TopMenu
{...topMenuOptions}
leanMode={isLeanMode()}
extraHeaders={
<div
className="left-0 w-100"
style={{
transform: 'translateZ(0)', //Avoid shaking
}}
>
<ExtensionPoint id="telemarketing" />
<ExtensionPoint id="menu-link" />
</div>
}
/>
</div>
<Spacer containerHeight={containerHeight} />
</Fragment>
hasCustomHeader
? <CustomHeader {...props} />
: <LegacyHeader {...props} />
)
}

Header.propTypes = {
/** Cases in which the menu is in lean mode */
leanWhen: PropTypes.string,
...login.propTypes,
...searchBar.propTypes,
...icons.propTypes,
...logo.propTypes,
...collapsible.propTypes,
}

Header.defaultProps = {
leanWhen: 'a^',
...login.defaultProps,
...searchBar.defaultProps,
...icons.defaultProps,
...logo.defaultProps,
...collapsible.defaultProps,
}

Header.schema = {
title: 'editor.header.title',
description: 'editor.header.description',
type: 'object',
properties: {
logoUrl: {
type: 'string',
title: 'editor.header.logo.image',
widget: {
'ui:widget': 'image-uploader',
},
},
linkUrl: {
type: 'string',
title: 'editor.header.link.url',
},
showSearchBar: {
title: 'editor.header.show.searchbar.title',
type: 'boolean',
default: true,
isLayout: true,
},
showLogin: {
title: 'editor.header.show.login.title',
type: 'boolean',
default: true,
isLayout: true,
},
},
}

export default Header
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
16 changes: 14 additions & 2 deletions react/components/TopMenu.js → react/legacy/components/TopMenu.js
@@ -1,9 +1,10 @@
import React, { Fragment } from 'react'
import PropTypes from 'prop-types'
import { ExtensionPoint } from 'vtex.render-runtime'
import { ExtensionPoint, useChildBlock__unstable } from 'vtex.render-runtime'
import Collapsible from './Collapsible'
import FixedContent from './FixedContent'
import { logo, collapsible, icons, lean, searchBar, login } from '../defaults'
import styles from '../store-header.css'

/**
* Top menu that contains the fixed and collapsible parts
Expand All @@ -22,6 +23,8 @@ const TopMenu = ({
collapsibleAnimation,
mobile,
}) => {
const hasMenu = !!useChildBlock__unstable({id: 'unstable--menu'})

return (
<Fragment>
{extraHeaders}
Expand All @@ -44,7 +47,16 @@ const TopMenu = ({
leanMode={leanMode}
mobile={mobile}
>
<ExtensionPoint id="category-menu" />
{hasMenu
? (
<div className={styles.topMenuCompatibilityContainer}>
<div className="flex flex-grow-1"></div>
<ExtensionPoint id="unstable--menu" />
<div className="flex flex-grow-1"></div>
</div>
)
: <ExtensionPoint id="category-menu" />
}
</Collapsible>
</Fragment>
)
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions react/hooks/useDevice.js → react/legacy/hooks/useDevice.js
Expand Up @@ -24,8 +24,10 @@ const useDevice = (mobileBreakpoint = 640) => {
}
const debounced = debounce(handleResize, 100)
window.addEventListener('resize', debounced)
window.addEventListener('load', handleResize)
return () => {
window.removeEventListener('resize', debounced)
window.removeEventListener('load', handleResize)
}
}, [mobileBreakpoint])

Expand Down
File renamed without changes.
File renamed without changes.

0 comments on commit 999ec23

Please sign in to comment.