diff --git a/components/header.module.css b/components/header.module.css index e4be5d3da7..f0287a740c 100644 --- a/components/header.module.css +++ b/components/header.module.css @@ -72,7 +72,7 @@ .navbarNav { width: 100%; align-items: center; - height: 39px; + height: var(--navbar-height); align-content: center; } @@ -101,12 +101,21 @@ padding-left: 0 !important; } +.navbarSpacer { + height: var(--navbar-total-height); +} + .sticky { position: fixed; - border-bottom: 1px solid var(--theme-toolbarActive); - width: 100vw; - top: -1px; - padding-top: 1px; + left: 0; + right: 0; + top: 0; + padding-top: var(--navbar-padding-top); background-color: var(--bs-body-bg); + border-bottom: var(--navbar-border-width) solid transparent; z-index: 1000; } + +.sticky.scrolled { + border-bottom-color: var(--theme-toolbarActive); +} diff --git a/components/nav/desktop/top-bar.js b/components/nav/desktop/top-bar.js index c1e0169d65..41ea95d32b 100644 --- a/components/nav/desktop/top-bar.js +++ b/components/nav/desktop/top-bar.js @@ -1,27 +1,39 @@ -import { Nav, Navbar } from 'react-bootstrap' +import { Nav, Navbar, Container } from 'react-bootstrap' import styles from '../../header.module.css' import { AnonCorner, Back, Brand, MeCorner, NavPrice, SearchItem } from '../common' import { useMe } from '../../me' import { useCommentsNavigatorContext, CommentsNavigator } from '@/components/use-comments-navigator' +import classNames from 'classnames' +import { useScrollThreshold } from '@/components/use-scroll-threshold' export default function TopBar ({ prefix, sub, path, topNavKey, dropNavKey }) { const { me } = useMe() const { navigator, commentCount } = useCommentsNavigatorContext() + const { sentinelRef, past } = useScrollThreshold(0) + return ( - - - + <> +
+
+
+ + + + + +
+ ) } diff --git a/components/nav/index.js b/components/nav/index.js index beacbd6fcf..8e5e5b3d8d 100644 --- a/components/nav/index.js +++ b/components/nav/index.js @@ -1,7 +1,6 @@ import { useRouter } from 'next/router' import DesktopHeader from './desktop/header' import MobileHeader from './mobile/header' -import StickyBar from './sticky-bar' import { PriceCarouselProvider } from './price-carousel' export default function Navigation ({ sub }) { @@ -20,7 +19,6 @@ export default function Navigation ({ sub }) { - ) } diff --git a/components/nav/mobile/header.js b/components/nav/mobile/header.js index a3b0cf775b..17ed86d201 100644 --- a/components/nav/mobile/header.js +++ b/components/nav/mobile/header.js @@ -1,13 +1,13 @@ import { Container } from 'react-bootstrap' import TopBar from './top-bar' -import SecondBar from './second-bar' +import NavSelectBar from './navselect-bar' export default function Header (props) { return (
+ -
) diff --git a/components/nav/mobile/navselect-bar.js b/components/nav/mobile/navselect-bar.js new file mode 100644 index 0000000000..cdba95a9c5 --- /dev/null +++ b/components/nav/mobile/navselect-bar.js @@ -0,0 +1,22 @@ +import { Nav, Navbar } from 'react-bootstrap' +import styles from '../../header.module.css' +import { Back, NavSelect, hasNavSelect } from '../common' +import SecondBar from './second-bar' + +export default function NavSelectBar ({ sub, topNavKey, path, pathname }) { + if (!hasNavSelect({ path, pathname })) return null + return ( + <> + + + + + + ) +} diff --git a/components/nav/mobile/second-bar.js b/components/nav/mobile/second-bar.js index 25ac2def2b..d8e71f651d 100644 --- a/components/nav/mobile/second-bar.js +++ b/components/nav/mobile/second-bar.js @@ -1,12 +1,12 @@ import { Nav, Navbar } from 'react-bootstrap' -import { NavPrice, NavWalletSummary, Sorts, hasNavSelect } from '../common' +import { NavPrice, NavWalletSummary, Sorts } from '../common' import styles from '../../header.module.css' import { useMe } from '@/components/me' export default function SecondBar (props) { const { me } = useMe() const { topNavKey } = props - if (!hasNavSelect(props)) return null + return (
+ ) } diff --git a/components/nav/sticky-bar.js b/components/nav/sticky-bar.js deleted file mode 100644 index 9503281b02..0000000000 --- a/components/nav/sticky-bar.js +++ /dev/null @@ -1,62 +0,0 @@ -import { useEffect, useRef } from 'react' -import styles from '@/components/header.module.css' -import { Container, Nav, Navbar } from 'react-bootstrap' -import { NavPrice, MeCorner, AnonCorner, SearchItem, Back, NavWalletSummary, Brand, SignUpButton } from './common' -import { useMe } from '@/components/me' -import classNames from 'classnames' -import { CommentsNavigator, useCommentsNavigatorContext } from '../use-comments-navigator' - -export default function StickyBar ({ prefix, sub, path, topNavKey, dropNavKey }) { - const ref = useRef() - const { me } = useMe() - const { navigator, commentCount } = useCommentsNavigatorContext() - - useEffect(() => { - const stick = () => { - if (window.scrollY > 100) { - ref.current?.classList.remove(styles.hide) - } else { - ref.current?.classList.add(styles.hide) - } - } - - window.addEventListener('scroll', stick) - - return () => { - window.removeEventListener('scroll', stick) - } - }, [ref?.current]) - - return ( -
- - - - - - - - - - -
- ) -} diff --git a/components/use-scroll-threshold.js b/components/use-scroll-threshold.js new file mode 100644 index 0000000000..8dab538bd6 --- /dev/null +++ b/components/use-scroll-threshold.js @@ -0,0 +1,19 @@ +import { useEffect, useRef, useState } from 'react' + +export function useScrollThreshold (offset = 0) { + const [past, setPast] = useState(false) + const ref = useRef(null) + + useEffect(() => { + if (!ref.current) return + + const observer = new window.IntersectionObserver(([entry]) => { + setPast(!entry.isIntersecting) + }, { root: null, rootMargin: `${offset}px 0px 0px 0px`, threshold: 0 }) + + observer.observe(ref.current) + return () => observer.disconnect() + }, [offset]) + + return { sentinelRef: ref, past } +} diff --git a/styles/globals.scss b/styles/globals.scss index 0d4a7bd4a7..858493ee8e 100644 --- a/styles/globals.scss +++ b/styles/globals.scss @@ -181,6 +181,13 @@ $zindex-sticky: 900; --theme-note-fresh: rgba(0, 124, 190, 0.75); } +:root { + --navbar-height: 39px; + --navbar-padding-top: 0.25rem; + --navbar-border-width: 1px; + --navbar-total-height: calc(var(--navbar-height) + var(--navbar-padding-top) + var(--navbar-border-width)); +} + @import '../node_modules/bootstrap/scss/bootstrap.scss'; @media screen and (min-width: 899px) {