UNPKG

auth0-web-header

Version:

Auth0's website and landings header

199 lines (179 loc) 5.87 kB
import React, { Component, PropTypes } from 'react'; import Head from '../Head'; import Item from '../Item'; import defaultMenuItems from '../data/menu-items.json'; import styles from './WebHeader.styl'; import classNames from 'classnames/bind'; import cxN from 'classnames'; const cx = styles::classNames; class WebHeader extends Component { static propTypes = { className: PropTypes.string, children: PropTypes.node, menuItems: PropTypes.array, theme: PropTypes.oneOf(['light', 'dark']), featuredEnable: PropTypes.bool, featuredLink: PropTypes.string, featuredText: PropTypes.string, primaryButtonEnable: PropTypes.bool, primaryButtonLink: PropTypes.string, primaryButtonOnClick: PropTypes.func, primaryButtonText: PropTypes.string, secondaryButtonEnable: PropTypes.bool, secondaryButtonLink: PropTypes.string, secondaryButtonOnClick: PropTypes.func, secondaryButtonText: PropTypes.string, breakpoint: PropTypes.number }; static defaultProps = { className: '', children: null, menuItems: defaultMenuItems, theme: 'light', featuredEnable: true, featuredLink: 'https://auth0.com/jobs', featuredText: 'We\'re hiring!', primaryButtonEnable: true, primaryButtonLink: '', primaryButtonOnClick: () => {}, primaryButtonText: 'Log in', secondaryButtonEnable: true, secondaryButtonLink: '?contact=true', secondaryButtonOnClick: () => {}, secondaryButtonText: 'Talk to sales', breakpoint: 992 }; state = { navbarDropdownIsOpen: false, mobileState: true }; componentDidMount() { this.handleResize(); window.addEventListener('resize', this.handleResize); } componentWillUnmount() { window.removeEventListener('resize', this.handleResize); } setHeightDropdown = () => { const height = this.state.mobileState ? `${window.innerHeight - 75}px` : ''; this.refs.dropdownContent.style.height = height; } handleResize = () => { const mobileState = window.innerWidth < this.props.breakpoint; this.setState({ mobileState }, () => { this.addOverflowBody(); this.setHeightDropdown(); }); } navbarDropdownHandler = () => { this.setState({ navbarDropdownIsOpen: !this.state.navbarDropdownIsOpen }, this.addOverflowBody); } closeDropdownOnButtonClick = callback => event => { const isMobile = this.state.mobileState; const isDropdownOpen = this.state.navbarDropdownIsOpen; if (callback) callback(event); if (isMobile && isDropdownOpen) this.navbarDropdownHandler(); } addOverflowBody() { const { navbarDropdownIsOpen, mobileState } = this.state; if (navbarDropdownIsOpen && mobileState) { document.body.classList.add(cx('overflow')); } else { document.body.classList.remove(cx('overflow')); } } handleKeyDown = e => { // Only enable focusable elements on key tab pressed if (e.keyCode !== 9 || this.state.focusable) return; this.setState({ focusable: true }); } renderButton(link, onClick, text, className) { return !!link ? <a href={link} className={className} onClick={onClick}>{text}</a> : <button className={className} onClick={onClick}>{text}</button>; } render() { const { className, children, menuItems, theme, featuredEnable, featuredLink, featuredText, primaryButtonEnable, primaryButtonLink, primaryButtonOnClick, primaryButtonText, secondaryButtonEnable, secondaryButtonLink, secondaryButtonOnClick, secondaryButtonText } = this.props; const { navbarDropdownIsOpen, mobileState, focusable } = this.state; const primaryButton = this.renderButton( primaryButtonLink, this.closeDropdownOnButtonClick(primaryButtonOnClick), primaryButtonText, 'btn btn-success btn-sm' ); const secondaryButton = this.renderButton( secondaryButtonLink, this.closeDropdownOnButtonClick(secondaryButtonOnClick), secondaryButtonText, 'btn btn-transparent btn-sm' ); const renderedMenuItems = menuItems.map(item => <Item key={item.position + item.id} item={item} theme={theme} simpleList={item.simpleList} closeHeaderDropdown={this.closeDropdownOnButtonClick()} mobile={mobileState} /> ); return ( <header className={cx('header', [`theme-${theme}`], className, { 'is-dropdown-open': navbarDropdownIsOpen, focusable })} onKeyDown={this.handleKeyDown} > <div className={cx('menu', { 'is-dropdown-open': navbarDropdownIsOpen })}> <div className="container"> <Head toggleDropdownHandler={this.navbarDropdownHandler} featured={featuredEnable} featuredLink={featuredLink} featuredText={featuredText} dropdownOpen={navbarDropdownIsOpen} theme={theme} closeHeaderDropdown={this.closeDropdownOnButtonClick()} /> <nav className={cx('collapse', { 'is-dropdown-open': navbarDropdownIsOpen })} ref="dropdownContent" > <ul className={cx('navigation')}>{!!children ? children : renderedMenuItems}</ul> </nav> <div className={cxN(cx('buttons-group', { 'is-dropdown-open': navbarDropdownIsOpen }), { 'theme-dark': theme === 'dark' })} > {secondaryButtonEnable ? secondaryButton : null} {primaryButtonEnable ? primaryButton : null} </div> </div> </div> </header> ); } } export default WebHeader;