UNPKG

vcc-ui

Version:

VCC UI is a collection of React UI Components that can be used for developing front-end applications at Volvo Car Corporation.

119 lines (103 loc) 2.55 kB
import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { useFela } from 'react-fela'; import { Block } from '../block'; import { getThemeStyle } from '../../get-theme-style'; const hideOnScrollOffsetTop = 80; const navStyle = ({ theme, sticky, hideOnScroll, isVisible }) => ({ position: 'relative', zIndex: 10, width: '100%', background: theme.color.background.primary, boxSizing: 'border-box', ':before': { content: "''", display: 'block', background: theme.color.ornament.divider, height: 1, outline: 'none', position: 'absolute', left: 0, right: 0, zIndex: -1, bottom: 0, }, extend: [ { condition: sticky, style: { position: 'fixed', top: 0, left: 0, }, }, { condition: hideOnScroll, style: { transition: 'transform 200ms ease-out', }, }, { condition: !isVisible, style: { transform: 'translateY(-100%)', }, }, ], }); // using an external variable for performance reasons let previousScrollY = 0; export const Nav = React.forwardRef( ({ hideOnScroll, sticky, children }, ref) => { const [isVisible, setVisible] = useState(true); const { theme } = useFela(); useEffect(() => { const toggleVisibility = () => { if (window.scrollY > previousScrollY) { if (isVisible && window.scrollY > hideOnScrollOffsetTop) { setVisible(false); } } else { if (!isVisible) { setVisible(true); } } previousScrollY = window.scrollY; }; if (hideOnScroll) { window.addEventListener('scroll', toggleVisibility); } return () => { window.removeEventListener('scroll', toggleVisibility); }; }, [hideOnScroll, isVisible]); const styleProps = { sticky, hideOnScroll, isVisible, theme, }; return ( <Block as="nav" ref={ref} extend={[navStyle(styleProps), getThemeStyle('nav', theme, styleProps)]} > {children} </Block> ); } ); Nav.displayName = 'Nav'; Nav.propTypes = { /** Automatically hide the sticky navigation if the user starts scrolling */ hideOnScroll: PropTypes.bool, /** Make the navigation stick to the top of the viewport */ sticky: PropTypes.bool, /** A JSX node */ children: PropTypes.node, }; Nav.defaultProps = { hideOnScroll: false, sticky: false, };