diff --git a/landing/global.css b/landing/global.css index 8dbeda3d4..acdbc1652 100644 --- a/landing/global.css +++ b/landing/global.css @@ -1,71 +1,74 @@ :root { + --landing-page-z-index: 0; + --mobile-nav-z-index: 1; + --header-z-index: 2; --purple: #7e57c2; --white: #fff; --white1: #ebedee; --grey: #808080; --btn-bg: var(--purple); --unselected: var(--grey); --btn-color: var(--white1); --logo-color: var(--white); --sub-heading-color: var(--purple); --sans-serif: 'IBM Plex Sans', sans-serif; --white-100: #ffffff; --white-90: #f5f5f5; --white-80: #ebebeb; --white-70: #e0e0e0; --white-60: #cccccc; --black-100: #0a0a0a; --black-90: #1f1f1f; --black-80: #404040; --black-70: #666666; --black-60: #808080; --violet-dark-100: #7e57c2; --violet-dark-80: #6d49ab; --violet-dark-60: #563894; --violet-dark-40: #44297a; --violet-dark-40: #331f5c; --success-light-10: #d5f6e3; --success-light-50: #6cdf9c; --success-primary: #00c853; --success-dark-50: #029841; --success-dark-90: #034920; --error-light-10: #feebe6; --error-light-50: #f9947b; --error-primary: #f53100; --error-dark-50: #b62602; --error-dark-90: #4f1203; --page-background: #111111; --light-dark-page-background: #1a1a1a; --comparison-cards: #18181a; } /* ===== GENERAL PAGE STYLES ===== */ html, body, :global(div#react-root) { height: 100%; } p { font-size: clamp(0.75rem, 0.5408rem + 1.0458vw, 1.75rem); } a { transition: 0.2s; text-decoration: none; } @media screen and (-webkit-min-device-pixel-ratio: 0) and (min-resolution: 0.001dpcm) { img { image-rendering: -webkit-optimize-contrast !important; } } @media not all and (min-resolution: 0.001dpcm) { @supports (-webkit-appearance: none) and (stroke-color: transparent) { img { image-rendering: unset !important; } } } diff --git a/landing/header.css b/landing/header.css index 851785cde..edd84b8cf 100644 --- a/landing/header.css +++ b/landing/header.css @@ -1,144 +1,153 @@ nav.headerContainer { display: flex; justify-content: center; } div.headerNavContentContainer { display: flex; align-items: center; justify-content: space-between; padding: 18px 32px; width: 1850px; + z-index: var(--header-z-index); + background-color: transparent; + transition: 650ms; + transition-property: background-color; +} + +div.headerContainerMobileNavActive { + background-color: var(--comparison-cards); + transition: 250ms; } .logo { display: flex; align-items: center; min-width: 180px; } .logoText { color: var(--white-100); margin-right: 8px; } .betaBadge { padding: 4px 16px; background-color: #ebebeb26; border-radius: 16px; color: var(--white-100); } .tab { color: var(--black-60); transition: 150ms; transition-property: color; } .tab:hover { color: var(--white-100); } .activeTab { color: var(--white-100); } .pageNav { display: flex; column-gap: 72px; } .socialIconsContainer { display: flex; justify-self: flex-end; align-items: center; } .icon { color: var(--white-100); } div.socialIconsContainer a { -webkit-tap-highlight-color: transparent; } div.twitterIcon, div.githubIcon, div.webappIcon { display: flex; justify-content: center; align-items: center; font-size: 24px; margin-inline: 4px; border-radius: 50px; width: 44px; height: 44px; transition: 300ms; } div.menuIcon { display: none; } div.twitterIcon svg, div.githubIcon svg, div.webappIcon svg { transition: 300ms; } @media screen and (hover: hover) { div.githubIcon:hover svg { color: #151013; transition: 300ms; } div.githubIcon:hover { background-color: #ffffff; transition: 300ms; } div.webappIcon:hover { background-color: var(--btn-bg); transition: 300ms; } div.twitterIcon:hover { background-color: #1d9bf0; transition: 300ms; } } @media screen and (max-width: 848px) { .pageNav { display: none; } div.twitterIcon, div.githubIcon, div.webappIcon { display: none; } div.menuIcon { display: flex; justify-content: center; align-items: center; font-size: 24px; margin-inline: 4px; border-radius: 50px; width: 44px; height: 44px; transition: 300ms; } div.menuIcon svg { transition: 300ms; } } @media screen and (max-width: 848px) and (hover: hover) { div.menuIcon:hover { cursor: pointer; background-color: var(--btn-bg); transition: 300ms; } } diff --git a/landing/header.react.js b/landing/header.react.js index 5542dca19..a99f8bd7b 100644 --- a/landing/header.react.js +++ b/landing/header.react.js @@ -1,86 +1,110 @@ // @flow import { faTwitter, faGithub } from '@fortawesome/free-brands-svg-icons'; import { faExternalLinkAlt, faBars } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import classNames from 'classnames'; import * as React from 'react'; import { NavLink } from 'react-router-dom'; +import type { SetState } from 'lib/types/hook-types.js'; + import css from './header.css'; import typography from './typography.css'; -function Header(): React.Node { +type Props = { + +showMobileNav: boolean, + +setShowMobileNav: SetState, +}; + +function Header(props: Props): React.Node { + const { showMobileNav, setShowMobileNav } = props; + + const headerContentContainerClassName = classNames({ + [css.headerNavContentContainer]: true, + [css.headerContainerMobileNavActive]: showMobileNav, + }); + const logoTextClassName = classNames([typography.heading2, css.logoText]); const badgeClassName = classNames([typography.paragraph2, css.betaBadge]); const navLinkClassName = classNames([typography.subheading2, css.tab]); + const onClickLogo = React.useCallback(() => { + setShowMobileNav(false); + }, [setShowMobileNav]); + + const onClickMobileNavIcon = React.useCallback(() => { + setShowMobileNav(!showMobileNav); + }, [setShowMobileNav, showMobileNav]); + return ( ); } export default Header; diff --git a/landing/landing.css b/landing/landing.css index 31d535469..62cb1138e 100644 --- a/landing/landing.css +++ b/landing/landing.css @@ -1,159 +1,159 @@ .container { background: radial-gradient(ellipse at bottom, #1f252e, #111827) fixed; font-family: var(--sans-serif); -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; color: white; word-break: break-word; height: 100%; position: relative; - z-index: 0; + z-index: var(--landing-page-z-index); } .innerContainer { background-color: var(--page-background); margin: 0; padding: 0; height: 100%; overflow: auto; } .innerContainerMobileNav { overflow-y: hidden; } .pageContentContainer { position: relative; } .wrapper { transition-property: max-width; transition: 300ms; max-width: 1850px; margin-left: auto; margin-right: auto; display: grid; align-items: center; padding-top: 7vh; padding-bottom: 235px; grid-template-columns: 40px repeat(12, 1fr) 40px; grid-template-rows: repeat(auto-fill, 1fr); column-gap: 1.5%; row-gap: 75px; grid-template-areas: '. hImg hImg hImg hImg . hInfo hInfo hInfo hInfo hInfo hInfo hInfo .' '. fImg fImg fImg fImg fImg . fInfo fInfo fInfo fInfo fInfo fInfo .' '. cInfo cInfo cInfo cInfo cInfo cInfo . cImg cImg cImg cImg cImg cImg' '. eImg eImg eImg eImg eImg . eInfo eInfo eInfo eInfo eInfo eInfo .' '. sInfo sInfo sInfo sInfo sInfo sInfo . sImg sImg sImg sImg sImg .' 'oImg oImg oImg oImg oImg oImg . oInfo oInfo oInfo oInfo oInfo oInfo .' '. lInfo lInfo lInfo lInfo lInfo lInfo . lImg lImg lImg lImg lImg .'; } @media screen and (max-width: 1099px) { .wrapper { margin-left: auto; margin-right: auto; display: grid; align-items: center; padding-top: 7vh; padding-bottom: 235px; grid-template-columns: 16px repeat(6, 1fr) 16px; grid-template-rows: repeat(auto-fill, 1fr); column-gap: 1.5%; row-gap: 75px; grid-template-areas: '. hInfo hInfo hInfo hInfo hInfo hInfo .' '. fInfo fInfo fInfo fInfo fInfo fInfo .' '. fImg fImg fImg fImg fImg fImg .' '. cInfo cInfo cInfo cInfo cInfo cInfo .' '. cImg cImg cImg cImg cImg cImg cImg' '. eInfo eInfo eInfo eInfo eInfo eInfo .' '. eImg eImg eImg eImg eImg eImg .' '. sInfo sInfo sInfo sInfo sInfo sInfo .' '. sImg sImg sImg sImg sImg sImg .' '. oInfo oInfo oInfo oInfo oInfo oInfo .' 'oImg oImg oImg oImg oImg oImg oImg .' '. lInfo lInfo lInfo lInfo lInfo lInfo .' '. lImg lImg lImg lImg lImg lImg .'; } .heroImage { display: none; } .heroInfo { display: flex; flex-direction: column; padding-bottom: 1.5rem; } .federatedImage { justify-self: center; } .encryptedImage { justify-self: center; max-width: 585px; } .sovereignImage { justify-self: center; } } .heroImage { grid-area: hImg; } .heroInfo { grid-area: hInfo; } .federatedImage { grid-area: fImg; } .federatedInfo { grid-area: fInfo; } .customizableImage { grid-area: cImg; } .customizableInfo { grid-area: cInfo; } .encryptedImage { grid-area: eImg; } .encryptedInfo { grid-area: eInfo; } .sovereignImage { grid-area: sImg; } .sovereignInfo { grid-area: sInfo; } .openSourceImage { grid-area: oImg; } .openSourceInfo { grid-area: oInfo; } .lessNoisyImage { grid-area: lImg; } .lessNoisyInfo { grid-area: lInfo; } diff --git a/landing/landing.react.js b/landing/landing.react.js index ca8ed57da..450634a9e 100644 --- a/landing/landing.react.js +++ b/landing/landing.react.js @@ -1,116 +1,121 @@ // @flow import classNames from 'classnames'; import * as React from 'react'; import { useRouteMatch } from 'react-router-dom'; import { ModalProvider, useModalContext, } from 'lib/components/modal-provider.react.js'; import AppLanding from './app-landing.react.js'; import Footer from './footer.react.js'; import Header from './header.react.js'; import Investors from './investors.react.js'; import Keyservers from './keyservers.react.js'; import css from './landing.css'; import MobileNav from './mobile-nav.react.js'; import Privacy from './privacy.react.js'; import QR from './qr.react.js'; import SIWE from './siwe.react.js'; import Support from './support.react.js'; import Team from './team.react.js'; import Terms from './terms.react.js'; import useScrollToTopOnNavigate from './use-scroll-to-top-on-navigate.react.js'; import './reset.css'; import './global.css'; function Landing(): React.Node { const onSIWE = useRouteMatch({ path: '/siwe' }); if (onSIWE) { return ; } return ( ); } function LandingSite(): React.Node { const modalContext = useModalContext(); const modals = React.useMemo( () => modalContext.modals.map(([modal, key]) => ( {modal} )), [modalContext.modals], ); const [showMobileNav, setShowMobileNav] = React.useState(false); const innerContainerClassName = classNames({ [css.innerContainer]: true, [css.innerContainerMobileNav]: showMobileNav, }); useScrollToTopOnNavigate(); const onPrivacy = useRouteMatch({ path: '/privacy' }); const onTerms = useRouteMatch({ path: '/terms' }); const onSupport = useRouteMatch({ path: '/support' }); const onKeyservers = useRouteMatch({ path: '/keyservers' }); const onQR = useRouteMatch({ path: '/qr' }); const onTeam = useRouteMatch({ path: '/team' }); const onInvestors = useRouteMatch({ path: '/investors' }); const activePage = React.useMemo(() => { if (onPrivacy) { return ; } else if (onTerms) { return ; } else if (onSupport) { return ; } else if (onKeyservers) { return ; } else if (onQR) { return ; } else if (onTeam) { return ; } else if (onInvestors) { return ; } else { return ; } }, [onKeyservers, onPrivacy, onSupport, onTerms, onTeam, onInvestors, onQR]); - let header =
; - if (onQR) { - header = null; + let header; + if (!onQR) { + header = ( +
+ ); } - let footer =