UNPKG

@mongodb-js/mongodb-ui-components

Version:

A collection of frequently used functional UI components found on mongodb properties

241 lines (218 loc) 7.54 kB
import {h, Component} from 'preact' import {loginIcon, mongodbLogo} from './icons' import {Panel} from './panel' import {Dropdown} from './dropdown' import {Search} from './search' export class DesktopNav extends Component { constructor (props) { super(props) this.state = { isPanOpen: false, isDdOpen: false, panelIndex: -1, ddIndex: -1, searching: false, compressed: false } this.topRightEls = [] } componentDidMount () { document.addEventListener('scroll', () => { const {compressed} = this.state const shouldCompress = window.pageYOffset > 100 if (compressed && !shouldCompress) { this.setState({compressed: false}) } else if (!compressed && shouldCompress) { this.setState({compressed: true}) } }) } togglePanSection (i) { this.setState({panelIndex: i, isDdOpen: false}) setTimeout(() => this.setState({isPanOpen: true})) } toggleDdSection (i) { if (this.state.searching) return this.setState({ddIndex: i, isPanOpen: false}) setTimeout(() => this.setState({isDdOpen: true})) } renderItem (item, i, left, active, activeIndex) { if (item.href) { return ( <a class='reset p-0 m-r-35' onMouseEnter={(e) => { this.setState({isPanOpen: false, isDdOpen: false}, () => { e.currentTarget.style.color = '#13AA52' e.currentTarget.children[0].style.color = '' }) }} onMouseLeave={(e) => { e.currentTarget.style.color = '' e.currentTarget.children[0].style.color = left ? '' : '#798186' }} href={item.href}> <p style={{ color: left ? '' : '#798186', fontSize: left ? '16px' : '14px' }}>{item.text}</p> </a> ) } return ( <button ref={left === false ? (el) => { this.topRightEls.push(el) } : null} style={{outline: '0'}} class='reset p-0 m-r-35' data-opens={item.opens} onClick={() => this.setState(left ? {isPanOpen: !this.state.isPanOpen} : {isDdOpen: !this.state.isDdOpen} )} onMouseEnter={() => left ? this.togglePanSection(i) : this.toggleDdSection(i)}> <p style={{ color: active && activeIndex === i ? '#13AA52' : (left ? '' : '#798186'), fontSize: left ? '16px' : '14px' }}> {item.text} </p> </button> ) } ddTransform (el) { if (el === undefined) return '' const width = el.offsetWidth const left = el.offsetLeft return `translate(${left + (width / 2) - 110}px, 0px)` } onNavMouseLeave () { this.setState({ isPanOpen: false, isDdOpen: false }) } render ( {logoHref, top, panels, dropdowns}, {isPanOpen, isDdOpen, panelIndex, ddIndex, searching, compressed} ) { return ( <nav onMouseLeave={() => this.onNavMouseLeave()} style={{zIndex: 1000000}} class='m-nav-desktop fixed top left w-full'> <div style={{ zIndex: 1, borderBottom: '1px solid rgba(179,187,193,0.5)', transition: '200ms', height: compressed ? '50px' : '70px' }} class='relative fl fl-justify-between bg-white'> <div class='fl fl-center m-h-20'> <a href={logoHref} class='m-r-15'> {mongodbLogo} </a> {top.left.map((item, i) => this.renderItem(item, i, true, isPanOpen, panelIndex))} </div> <div class='fl fl-center m-h-20'> <div class='fl fl-center' style={{ transition: searching ? 'none' : '150ms cubic-bezier(0.230, 1.000, 0.320, 1.000)', width: searching ? '0px' : '', opacity: searching ? '0' : '1' }}> {top.right.map((item, i) => this.renderItem(item, i, false, isDdOpen, ddIndex) )} </div> <div class='relative'> <Search onSearchClick={(newVal) => this.setState({searching: newVal})} /> </div> <a href='https://cloud.mongodb.com/user' onMouseEnter={function (e) { const svg = e.target.querySelector('svg') svg.style.transition = '200ms' svg.style.transform = 'translate(-2px, 0) scale(1.4)' }} onMouseLeave={function (e) { const svg = e.target.querySelector('svg') svg.style.transform = 'translate(0, 0) scale(1)' }}> <button class='reset p-0 m-r-35'> <p class='fl fl-center' style={{fontSize: '14px', cursor: 'pointer'}}> <strong clasxss='m-l-5'>Sign In</strong> {loginIcon} </p> </button> </a> <a href='/download-center'> <button class='btn-green'> Try Free </button> </a> </div> </div> <div style={{pointerEvents: isPanOpen ? '' : 'none'}}> <div style={{ boxShadow: '0 4px 7px 0 rgba(0,0,0,0.2)', transition: 'opacity 100ms, transform 200ms cubic-bezier(0.175, 0.885, 0.320, 1.275)', transform: isPanOpen ? 'translate(0, -10px)' : 'translate(0, -30px)', opacity: isPanOpen ? '1' : '0' }} class='relative bg-white'> <div class='relative m-auto' style={{ transition: isPanOpen ? '' : 'height 1ms 210ms', height: isPanOpen ? `${panels[panelIndex].height + 10}px` : '0px' }}> {panels.map((panel, i) => <Panel width={panel.width} position={i > panelIndex ? 1 : -1} isOpen={isPanOpen} isActive={panelIndex === i} sections={panel.sections} callout={panel.callout} /> )} </div> </div> </div> <div class='absolute top left' style={{ zIndex: 10, pointerEvents: isDdOpen ? '' : 'none', transition: isDdOpen ? 'opacity 150ms, transform 250ms cubic-bezier(0.175, 0.885, 0.320, 1.275)' : '', opacity: isDdOpen ? '1' : '0', transform: this.ddTransform(this.topRightEls[ddIndex]) }}> <div style={{ border: '1px solid rgba(179,187,193,0.25)', borderRadius: '4px', boxShadow: '0 2px 4px 0 rgba(0,0,0,0.1)', transition: 'transform 250ms cubic-bezier(0.175, 0.885, 0.320, 1.275), height 100ms', transform: isDdOpen ? `translate(0, ${compressed ? '43px' : '60px'})` : `translate(0, ${compressed ? '38px' : '55px'})`, opacity: isDdOpen ? '1' : '0', height: isDdOpen ? `${dropdowns[ddIndex].height}px` : '' }} class='absolute w-220 bg-white'> {dropdowns.map((dropdown, i) => <Dropdown isOpen={isDdOpen} isActive={ddIndex === i} items={dropdown.items} /> )} </div> </div> </nav> ) } }