UNPKG

irisrad-ui

Version:

UI elements developered for IRIS R&D Group Inc

278 lines (258 loc) 8.47 kB
/** * IRIS R&D Group Inc. All rights reserved. * * Author: Lucien Chu * Create Date: Apr 07, 2021 * * Description: This is a wrapper of header * A header should has the following components * 1. the company logo * provided as regular html img component * * 2. some some navigation links * these component are optional, if they are given, they are positioned on the right hand side * of the header * * 3. user name: * logged in user's name, position next to the user icon buton * * 4. hidden links: * some navigation links about the user, ie: profile, logout btn etc, the are not display until * user click on the predefined user icon button * * 5. fade in element: * elemets that would position below the header, a button would be posisiton on the header component * which is used to toggle its fade in and fade out animation. */ import React, { useEffect } from "react"; import PropTypes from "prop-types"; import { IrisMenuIcon } from "../irisIconButtons"; import "../../style/styles.css"; import { IrisDropDownMenu } from "../irisDropDownMenu/IrisDropDownMenu"; import { IrisButton } from "../irisButton/IrisButton"; const HEADER_VARIANTS = ["primary", "secondary"]; let timeoutFunction; const toggleFadeInWrapper = (event) => { // find header by its id const toggleBtn = event.target; const header = document.getElementById("iris-header"); if (header) { // find the slide wrapper within the header const slideDownOverlay = header.querySelector(".slide-down-overlay"); const slidDownContent = header.querySelector(".slide-down-wrapper"); if (slideDownOverlay && slidDownContent) { const { classList: overlayClassList } = slideDownOverlay; const { classList: contentClassList } = slidDownContent; // const height = slidDownContent.scrollHeight; if (timeoutFunction) { clearTimeout(timeoutFunction); timeoutFunction = null; } // content is currently shown if (overlayClassList.contains("show")) { // fade out content contentClassList.toggle("fade-in"); header.classList.toggle("hide-shadow"); // document.body.style.overflow = ""; document.body.classList.remove("prevent-scroll"); // mark wrapper as display none timeoutFunction = setTimeout(() => { overlayClassList.toggle("show"); toggleBtn.classList.toggle( "active", overlayClassList.contains("show") ); }, 300); } // content is not shown else { // display wrapper overlayClassList.toggle("show"); // delay to fade in content timeoutFunction = setTimeout(() => { contentClassList.toggle("fade-in"); header.classList.toggle("hide-shadow"); // document.body.style.overflow = "hidden"; document.body.classList.add("prevent-scroll"); }, 100); } // highlight the toggle btn toggleBtn.classList.toggle("active", overlayClassList.contains("show")); } } }; export function IrisHeader({ className = "", variant, links, logoComponent, headerTitle, actionButtons, fadeInContent, hiddenLinks, menuBtnSize = "small", userName = "", ...props }) { let headerStyle = ""; if (HEADER_VARIANTS.indexOf(variant) >= 0) { headerStyle = `iris-header--${variant}`; } if (typeof className === "string" && className !== "") { headerStyle += " " + className; } let hideenItems; if (hiddenLinks) { hideenItems = hiddenLinks.map((link) => ( <a href="#" onClick={link.onClick}> {link.label} </a> )); } useEffect(() => { const ele = document.getElementById("iris-header"); const as = ele.querySelectorAll("a"); as.forEach((a) => { a.onclick = () => { as.forEach((a) => a.classList.remove("active")); if (!a.classList.contains("active")) { a.classList.add("active"); } }; }); }, []); // fade in content is provided if (fadeInContent?.toggleBtnProps) { const { btnTitle, size, iconProps } = fadeInContent.toggleBtnProps; const toggleBtn = ( <IrisButton onClick={toggleFadeInWrapper} size={size} iconProps={iconProps} data-type="data-type" > {btnTitle} </IrisButton> ); // action buttons would be display on the header // make the toggle button as the first element of // the list so that it would be arranged on the // left most position if (actionButtons && Array.isArray(actionButtons)) { actionButtons.unshift(toggleBtn); } else { actionButtons = [toggleBtn]; } } return ( <header id="iris-header" className={headerStyle} {...props}> <nav className="iris-header-nav"> <div className="logo">{logoComponent}</div> {/* header title */} {headerTitle && <h2 className="header-title">{headerTitle}</h2>} {/* action buttons */} {actionButtons && ( <div className="action-btn-wrapper"> {actionButtons.map((Button, index) => ( <div key={index}>{Button}</div> ))} </div> )} {links && ( <> <label htmlFor="iris-header-menu-toggle" className="iris-header-menu-toggle-button" > <IrisMenuIcon size={menuBtnSize} /> </label> <input type="checkbox" id="iris-header-menu-toggle" /> <ul className="nav-list"> {links.map((link) => ( <li key={link.label}>{link.node}</li> ))} </ul> </> )} <span className="iris-header__user-name-wrapper" style={{ marginLeft: "auto", marginRight: "0.725rem", fontSize: "1.375rem", }} > {userName} </span> {hiddenLinks && ( <div className="hidden-content-wrapper"> <IrisDropDownMenu menuItems={hideenItems} style={{ color: "#737373" }} menuProps={{ alignment: "right", }} /> </div> )} </nav> {/* element to be faded in and out */} {fadeInContent?.element && ( <div className="slide-down-overlay" onClick={(event) => { if (event.target === event.currentTarget) { const header = document.getElementById("iris-header"); if (header) { const toggleBtn = header.querySelector( `[data-type="data-type"]` ); if (toggleBtn) { toggleBtn.click(); } } } }} > <div className="slide-down-wrapper"> <div className="slide-down-content">{fadeInContent.element}</div> </div> </div> )} </header> ); } IrisHeader.propTypes = { className: PropTypes.string, variant: PropTypes.oneOf(HEADER_VARIANTS), logoComponent: PropTypes.node, // html node that could represent company logo headerTitle: PropTypes.string, // header title actionButtons: PropTypes.arrayOf(PropTypes.node), useName: PropTypes.string, // logged in user name // navigation links links: PropTypes.arrayOf( PropTypes.shape({ label: PropTypes.string.isRequired, onClick: PropTypes.func, }) ), // links hidden by defeault, togglable by clicking the user icon hiddenLinks: PropTypes.arrayOf( PropTypes.shape({ label: PropTypes.string.isRequired, onClick: PropTypes.func, }) ), fadeInContent: PropTypes.shape({ toggleBtnProps: PropTypes.shape({ btnTitle: PropTypes.string.isRequired, size: PropTypes.oneOf(["small", "medium", "large"]), iconProps: PropTypes.shape({ variant: PropTypes.string, size: PropTypes.string, iconTitle: PropTypes.string.isRequired, }), }).isRequired, element: PropTypes.node.isRequired, }), };