diff --git a/landing/header.css b/landing/header.css index 4073f6b97..3fc677b58 100644 --- a/landing/header.css +++ b/landing/header.css @@ -1,155 +1,155 @@ 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 { +div.commAppIcon { 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 { +div.commAppIcon 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 { + div.commAppIcon:hover { background-color: var(--btn-bg); transition: 300ms; } div.twitterIcon:hover { background-color: #1d9bf0; transition: 300ms; } } /* max-width should be kept in sync with HEADER_BREAKPOINT in header.react */ @media screen and (max-width: 848px) { .pageNav { display: none; } div.twitterIcon, div.githubIcon, - div.webappIcon { + div.commAppIcon { 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; } } /* max-width should be kept in sync with HEADER_BREAKPOINT in header.react */ -@media screen and (max-width: 848px) and (hover: hover) { +@media screen and (max-width: 904px) 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 1297728df..05599d6c8 100644 --- a/landing/header.react.js +++ b/landing/header.react.js @@ -1,130 +1,145 @@ // @flow import { faTwitter, faGithub } from '@fortawesome/free-brands-svg-icons'; import { faExternalLinkAlt, faBars, faTimes, + faDownload, } 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'; // This value comes from the breakpoint value in header.css. Please make sure // that this value is in sync with header.css if ever changed -export const HEADER_BREAKPOINT = 848; // px +export const HEADER_BREAKPOINT = 904; // px 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.react.js b/landing/landing.react.js index d33da34f2..cdbc83a6d 100644 --- a/landing/landing.react.js +++ b/landing/landing.react.js @@ -1,157 +1,170 @@ // @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 ConnectFarcaster from './connect-farcaster.react.js'; +import Download from './download.react.js'; import Footer from './footer.react.js'; import Header, { HEADER_BREAKPOINT } 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' }); const onConnectFarcaster = useRouteMatch({ path: '/connect-farcaster' }); if (onSIWE) { return ; } else if (onConnectFarcaster) { return ; } return ( ); } function LandingSite(): React.Node { const modalContext = useModalContext(); const modals = React.useMemo( () => modalContext.modals.map(([modal, key]) => ( {modal} )), [modalContext.modals], ); const isModalOpen = modals.length > 0; React.useEffect(() => { const { body } = document; if (!body || !isModalOpen) { return undefined; } body.style.overflow = 'hidden'; return () => { body.style.overflow = 'auto'; }; }, [isModalOpen]); const [showMobileNav, setShowMobileNav] = React.useState(false); const handleResize = React.useCallback(() => { if (window.innerWidth > HEADER_BREAKPOINT) { setShowMobileNav(false); } }, [setShowMobileNav]); React.useEffect(() => { if (!showMobileNav) { return undefined; } window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, [handleResize, showMobileNav]); 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 onDownload = useRouteMatch({ path: '/download' }); 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 if (onDownload) { + return ; } else { return ; } - }, [onKeyservers, onPrivacy, onSupport, onTerms, onTeam, onInvestors, onQR]); + }, [ + onPrivacy, + onTerms, + onSupport, + onKeyservers, + onQR, + onTeam, + onInvestors, + onDownload, + ]); let header; if (!onQR) { header = (
); } let footer; if (!onQR) { footer =