Updated sticky header logic.

This commit is contained in:
Mike Cao 2023-02-09 08:22:36 -08:00
parent 45c13da262
commit f062cdbed2
8 changed files with 31 additions and 24 deletions

View File

@ -1,15 +1,21 @@
import { useEffect, useRef } from 'react';
import classNames from 'classnames';
import useSticky from 'hooks/useSticky';
export default function StickyHeader({ className, stickyClassName, stickyStyle, children }) {
const { ref, isSticky } = useSticky();
const initialWidth = useRef(0);
useEffect(() => {
initialWidth.current = ref.current.clientWidth;
}, [ref]);
return (
<div
ref={ref}
data-sticky={isSticky}
className={classNames(className, { [stickyClassName]: isSticky })}
style={isSticky ? { ...stickyStyle, width: ref?.current?.clientWidth } : null}
style={isSticky ? { ...stickyStyle, width: initialWidth.current } : null}
>
{children}
</div>

View File

@ -19,7 +19,7 @@ export default function AppLayout({ title, children }) {
<div className={styles.nav}>
<NavBar />
</div>
<div className={styles.body}>
<div className={styles.body} id="layout-body">
<Container>
<main>{children}</main>
</Container>

View File

@ -6,11 +6,10 @@
.nav {
grid-row: 1 / 3;
height: 100vh;
position: fixed;
}
.body {
grid-area: 1 / 2;
overflow: auto;
height: 100vh;
}

View File

@ -2,21 +2,25 @@
display: flex;
flex-direction: column;
justify-content: center;
min-height: 90px;
min-width: 140px;
}
.value {
min-height: 36px;
display: flex;
align-items: center;
font-size: 36px;
font-weight: 700;
white-space: nowrap;
min-height: 60px;
}
.label {
white-space: nowrap;
display: flex;
align-items: center;
gap: 5px;
white-space: nowrap;
min-height: 30px;
}
.change {

View File

@ -2,10 +2,7 @@
display: flex;
cursor: pointer;
min-height: 80px;
}
.bar > div + div {
padding-left: 20px;
gap: 20px;
}
@media only screen and (max-width: 992px) {

View File

@ -1,6 +1,6 @@
import { useMemo } from 'react';
import { useIntl } from 'react-intl';
import { Button, Icon, Text, Row, Column, Loading } from 'react-basics';
import { Button, Icon, Text, Row, Column, Container } from 'react-basics';
import Link from 'next/link';
import PageviewsChart from './PageviewsChart';
import MetricsBar from './MetricsBar';

View File

@ -18,6 +18,7 @@
.header {
min-height: 90px;
margin-bottom: 20px;
}
.metrics {
@ -25,16 +26,15 @@
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
}
.sticky {
position: fixed;
top: 0;
margin: auto;
background: var(--base50);
border-bottom: 1px solid var(--base300);
z-index: 3;
width: inherit;
}
.filter {

View File

@ -1,27 +1,28 @@
import { useState, useEffect, useRef } from 'react';
export default function useSticky(defaultSticky = false) {
export default function useSticky(
element = document.getElementById('layout-body'),
defaultSticky = false,
) {
const [isSticky, setIsSticky] = useState(defaultSticky);
const ref = useRef(null);
const initialTop = useRef(0);
const initialTop = useRef(null);
useEffect(() => {
const handleScroll = () => {
if (window.pageYOffset > initialTop.current) {
setIsSticky(true);
} else {
setIsSticky(false);
}
setIsSticky(element.scrollTop > initialTop.current);
};
initialTop.current = ref.current.offsetTop;
if (initialTop.current === null) {
initialTop.current = ref.current.offsetTop;
}
window.addEventListener('scroll', handleScroll);
element.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
element.removeEventListener('scroll', handleScroll);
};
}, []);
}, [setIsSticky]);
return { ref, isSticky };
}