UNPKG

@newrelic/gatsby-theme-newrelic

Version:

[![Community Project header](https://github.com/newrelic/opensource-website/raw/master/src/images/categories/Community_Project.png)](https://opensource.newrelic.com/oss-category/#community-project)

443 lines (416 loc) 13.4 kB
import React, { useState } from 'react'; import PropTypes from 'prop-types'; import useMedia from 'use-media'; import path from 'path'; import { css } from '@emotion/react'; import { graphql, useStaticQuery } from 'gatsby'; import { useLocation } from '@reach/router'; import AnnouncementBanner from './AnnouncementBanner'; import DarkModeToggle from './DarkModeToggle'; import ExternalLink from './ExternalLink'; import Button from './Button'; import Dropdown from './Dropdown'; import NewRelicLogo from './NewRelicLogo'; import Icon from './Icon'; import GlobalNavLink from './GlobalNavLink'; import GlobalSearch from './GlobalSearch'; import { HEADER_LINKS, NR_SITES } from '../utils/constants'; import useThemeTranslation from '../hooks/useThemeTranslation'; import useInstrumentedHandler from '../hooks/useInstrumentedHandler'; // removes the site nav from the header in favor of the search bar // swaps out logo into collapsable nav const NAV_BREAKPOINT = '1070px'; const LOGO_TEXT_BREAKPOINT = '460px'; const SEARCH_BREAKPOINT = '1355px'; const SEARCH_BREAKPOINT_2 = '865px'; const NAVLIST_BREAKPOINT = '1507px'; const GlobalHeader = ({ className, activeSite }) => { const location = useLocation(); const { t } = useThemeTranslation(); const [mobileSearchOpen, setMobileSearchOpen] = useState(false); const { allLocale: { nodes: locales }, site: { layout: { mobileBreakpoint }, }, } = useStaticQuery(graphql` query GlobalHeaderQuery { allLocale(sort: { fields: [isDefault, locale], order: [DESC, ASC] }) { nodes { locale localName isDefault } } site { layout { mobileBreakpoint } } } `); const hideLogoText = useMedia({ maxWidth: LOGO_TEXT_BREAKPOINT }); const matchLocalePath = new RegExp( `^\\/(${locales.map(({ locale }) => locale).join('|')})` ); const handleLocaleClick = useInstrumentedHandler(null, ({ locale }) => ({ eventName: 'localeDropDownClick', category: 'LocaleDropDown', origin: 'gatsbyTheme', layoutElement: 'globalHeader', locale, })); return ( <> <AnnouncementBanner /> <div data-swiftype-index={false} className={className} css={css` display: grid; background-color: var(--erno-black); grid-template-columns: var(--sidebar-width) minmax(0, 1fr); grid-template-rows: 1fr auto; grid-template-areas: 'logo nav'; box-shadow: var(--shadow-2); position: sticky; top: 0; z-index: 80; height: var(--global-header-height); @media screen and (max-width: ${NAVLIST_BREAKPOINT}) { grid-template-columns: calc(150px + 1.5rem) minmax(0, 1fr); } @media screen and (max-width: ${mobileBreakpoint}) { grid-template-columns: calc(150px + 1.5rem) minmax(0, 1fr); } `} > <nav css={css` grid-area: logo; padding: 0 1.5rem; display: flex; align-items: center; height: 100%; overflow: hidden; `} > <ExternalLink href={t('header.newRelicLogoLink')} css={css` display: flex; align-items: center; @media screen and (max-width: ${NAV_BREAKPOINT}) { display: none; } `} instrumentation={{ component: 'globalHeaderLogo', layoutElement: 'globalHeader', }} > <NewRelicLogo size="150px" css={css` .text-color { fill: var(--color-white); } `} /> </ExternalLink> <Dropdown css={css` display: none; @media screen and (max-width: ${NAV_BREAKPOINT}) { display: block; } `} > <Dropdown.Toggle size={Button.SIZE.EXTRA_SMALL} variant={Button.VARIANT.LINK} chevron={false} css={css` padding-left: 0; padding-right: 0; `} > <NewRelicLogo size={hideLogoText ? '45px' : '150px'} css={css` .text-color { fill: var(--color-white); } `} omitText={hideLogoText} /> </Dropdown.Toggle> <Dropdown.Menu> <NavList listType="dropdown" activeSite={activeSite} /> </Dropdown.Menu> </Dropdown> </nav> <div css={css` grid-area: nav; display: flex; justify-content: space-between; padding: 0 1.5rem; width: 100%; max-width: var(--site-max-width); margin: auto; `} > <nav> <ul css={css` height: 100%; display: flex; list-style-type: none; white-space: nowrap; padding: 0; li { > a { font-size: 18px; } &:first-of-type { > a { padding-left: 0px; } } } @media screen and (max-width: ${NAV_BREAKPOINT}) { display: none; } `} > <NavList listType="main" activeSite={activeSite} /> </ul> </nav> <ul css={css` margin: 0; margin-left: 1rem; padding: 0; display: flex; list-style-type: none; align-items: center; justify-content: flex-end; > li { transition: all 0.2s ease-out; &:not(:first-of-type) &:not(:last-of-type) { margin-left: 0.5rem; } } @media screen and (max-width: ${NAV_BREAKPOINT}) { width: 100%; justify-content: flex-end; margin: 0; } `} > <li css={css` --search-width: 26.625rem; --search-dropdown-width: 26.625rem; display: flex; justify-content: end; margin: 0rem 0.5rem 0 1rem; position: relative; width: var(--search-width); @media screen and (max-width: 930px) { margin-right: 1rem; } @media screen and (max-width: ${NAV_BREAKPOINT}) { margin-left: 0; } @media (max-width: ${SEARCH_BREAKPOINT}) { --search-width: 13.3125rem; } @media (max-width: ${SEARCH_BREAKPOINT_2}) { --search-width: 12rem; } @media screen and (max-width: ${mobileBreakpoint}) { display: ${mobileSearchOpen ? 'block' : 'none'}; position: static; } `} > <GlobalSearch onClose={() => setMobileSearchOpen(false)} /> </li> <li css={css` display: flex; flex-direction: row; @media screen and (max-width: ${LOGO_TEXT_BREAKPOINT}) { width: 100%; justify-content: space-evenly; } `} > <Button id="mobile-search-expand" variant={Button.VARIANT.PLAIN} onClick={() => setMobileSearchOpen(true)} css={css` align-self: center; color: var(--system-text-primary-dark); display: none; margin-right: 8px; padding: 8px; transition: all 0.2s ease-out; @media screen and (max-width: ${mobileBreakpoint}) { display: block; } `} > <Icon css={css` cursor: pointer; display: block; `} name="fe-search" size="1.25rem" /> </Button> {locales.length > 1 && ( <Dropdown align="right"> <Dropdown.Toggle size={Button.SIZE.EXTRA_SMALL} variant={Button.VARIANT.LINK} chevron={false} css={css` margin: 0; border-radius: 0px; font-size: 0.75rem; color: var(--system-text-primary-dark); background: transparent; `} > <Icon name="nr-i18n" size="20px" /> </Dropdown.Toggle> <Dropdown.Menu> {locales.map(({ isDefault, locale, localName }) => ( <Dropdown.MenuItem key={locale} onClick={() => handleLocaleClick({ locale })} as="a" href={path.join( isDefault ? '' : `/${locale}`, location.pathname.replace(matchLocalePath, '') )} css={css` text-decoration: none; color: var(--primary-text-color); `} > {localName} </Dropdown.MenuItem> ))} </Dropdown.Menu> </Dropdown> )} <DarkModeToggle css={css` font-size: 0.75rem; @media screen and (max-width: ${mobileBreakpoint}) { margin: 0; } color: var(--system-text-primary-dark); `} size="27px" /> </li> <li css={css` display: flex; align-items: right; flex-direction: row; `} > <Button as={ExternalLink} size={Button.SIZE.SMALL} variant={Button.VARIANT.LINK} href="https://one.newrelic.com" css={css` white-space: nowrap; font-size: 18px; span { color: var(--system-text-primary-dark); } @media screen and (max-width: ${mobileBreakpoint}) { display: none; } `} instrumentation={{ component: 'headerLogInButton', layoutElement: 'globalHeader', }} > <span>{t('button.login')}</span> </Button> <Button as={ExternalLink} className={className} css={css` font-size: 18px; white-space: nowrap; span { color: var(--brand-button-primary-accent); } padding-right: 0; `} href="https://newrelic.com/signup" size={Button.SIZE.SMALL} variant={Button.VARIANT.LINK} instrumentation={{ component: 'SignUpButton', layoutElement: 'globalHeader', }} > <span>{t('button.startNow')}</span> </Button> </li> </ul> </div> </div> </> ); }; GlobalHeader.propTypes = { className: PropTypes.string, activeSite: PropTypes.oneOf(Object.values(NR_SITES)), }; const NavList = ({ listType, activeSite = null }) => { const navList = []; HEADER_LINKS.forEach(({ text, href }) => { switch (listType) { case 'main': navList.push( <li key={href}> <GlobalNavLink href={href} activeSite={activeSite && HEADER_LINKS.get(activeSite)} instrumentation={{ component: 'globalHeader', layoutElement: 'globalHeader', }} > {text} </GlobalNavLink> </li> ); break; case 'dropdown': navList.push( <Dropdown.MenuItem key={href} href={href}> {text} </Dropdown.MenuItem> ); break; } }); return navList; }; export default GlobalHeader;