From f3e1f18e1b1f8c19aa6152b8970ecf3dcbc23195 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 22 Mar 2023 01:53:34 -0700 Subject: [PATCH] Updated sticky header logic. --- components/common/StickyHeader.js | 32 ------------------ components/metrics/WebsiteChart.js | 33 ++++++++++--------- components/metrics/WebsiteChart.module.css | 15 +++++---- .../pages/realtime/RealtimeDashboard.js | 5 +-- hooks/useSticky.js | 22 ++++++------- package.json | 2 +- yarn.lock | 8 ++--- 7 files changed, 41 insertions(+), 76 deletions(-) delete mode 100644 components/common/StickyHeader.js diff --git a/components/common/StickyHeader.js b/components/common/StickyHeader.js deleted file mode 100644 index 639709f9..00000000 --- a/components/common/StickyHeader.js +++ /dev/null @@ -1,32 +0,0 @@ -import { useMeasure } from 'react-basics'; -import classNames from 'classnames'; -import useSticky from 'hooks/useSticky'; - -export default function StickyHeader({ - className, - stickyClassName, - stickyStyle, - enabled = true, - scrollElement, - children, -}) { - const { ref: scrollRef, isSticky } = useSticky({ scrollElement }); - const { ref: measureRef, dimensions } = useMeasure(); - const active = enabled && isSticky; - - return ( -
-
- {children} -
-
- ); -} diff --git a/components/metrics/WebsiteChart.js b/components/metrics/WebsiteChart.js index f11410d8..c3a1268b 100644 --- a/components/metrics/WebsiteChart.js +++ b/components/metrics/WebsiteChart.js @@ -2,11 +2,11 @@ import { useMemo } from 'react'; import { useIntl } from 'react-intl'; import { Button, Icon, Text, Row, Column } from 'react-basics'; import Link from 'next/link'; +import classNames from 'classnames'; import PageviewsChart from './PageviewsChart'; import MetricsBar from './MetricsBar'; import WebsiteHeader from './WebsiteHeader'; import DateFilter from 'components/input/DateFilter'; -import StickyHeader from 'components/common/StickyHeader'; import ErrorMessage from 'components/common/ErrorMessage'; import FilterTags from 'components/metrics/FilterTags'; import RefreshButton from 'components/input/RefreshButton'; @@ -16,9 +16,9 @@ import useTimezone from 'hooks/useTimezone'; import usePageQuery from 'hooks/usePageQuery'; import { getDateArray, getDateLength } from 'lib/date'; import Icons from 'components/icons'; -import { UI_LAYOUT_BODY } from 'lib/constants'; import { labels } from 'components/messages'; import styles from './WebsiteChart.module.css'; +import useSticky from '../../hooks/useSticky'; export default function WebsiteChart({ websiteId, @@ -37,6 +37,7 @@ export default function WebsiteChart({ query: { url, referrer, os, browser, device, country }, } = usePageQuery(); const { get, useQuery } = useApi(); + const { ref, isSticky } = useSticky({ enabled: stickyHeader }); const { data, isLoading, error } = useQuery( ['websites:pageviews', websiteId, modified, url, referrer, os, browser, device, country], @@ -81,21 +82,21 @@ export default function WebsiteChart({ )} - - - - - - - - - - - + + + + + + + + {error && } diff --git a/components/metrics/WebsiteChart.module.css b/components/metrics/WebsiteChart.module.css index 3a3d4718..3db8bc63 100644 --- a/components/metrics/WebsiteChart.module.css +++ b/components/metrics/WebsiteChart.module.css @@ -17,22 +17,23 @@ } .header { - position: relative; display: flex; justify-content: space-between; align-items: center; + padding: 10px 0; min-height: 90px; margin-bottom: 20px; + background: var(--base50); } .sticky { - position: fixed; - top: 0; - background: var(--base50); + position: sticky; + top: -1px; + z-index: 2; +} + +.isSticky { border-bottom: 1px solid var(--base300); - z-index: 3; - width: inherit; - padding-top: 10px; } .actions { diff --git a/components/pages/realtime/RealtimeDashboard.js b/components/pages/realtime/RealtimeDashboard.js index 9c33d2ac..35906c45 100644 --- a/components/pages/realtime/RealtimeDashboard.js +++ b/components/pages/realtime/RealtimeDashboard.js @@ -6,7 +6,6 @@ import firstBy from 'thenby'; import { GridRow, GridColumn } from 'components/layout/Grid'; import Page from 'components/layout/Page'; import RealtimeChart from 'components/metrics/RealtimeChart'; -import StickyHeader from 'components/common/StickyHeader'; import PageHeader from 'components/layout/PageHeader'; import WorldMap from 'components/common/WorldMap'; import RealtimeLog from 'components/pages/realtime/RealtimeLog'; @@ -104,9 +103,7 @@ export default function RealtimeDashboard({ websiteId }) { - - - +
diff --git a/hooks/useSticky.js b/hooks/useSticky.js index dc264f9d..e2f561b3 100644 --- a/hooks/useSticky.js +++ b/hooks/useSticky.js @@ -1,25 +1,23 @@ import { useState, useEffect, useRef } from 'react'; -export default function useSticky({ scrollElement = document, defaultSticky = false }) { +export default function useSticky({ defaultSticky = false, enabled = true }) { const [isSticky, setIsSticky] = useState(defaultSticky); const ref = useRef(null); - const initialTop = useRef(null); useEffect(() => { - const handleScroll = () => { - setIsSticky((scrollElement?.scrollTop ?? window.scrollY) > initialTop.current); - }; + let observer; + const handler = ([entry]) => setIsSticky(entry.intersectionRatio < 1); - if (initialTop.current === null) { - initialTop.current = ref?.current?.offsetTop; + if (enabled && ref.current) { + observer = new IntersectionObserver(handler, { threshold: [1] }); + observer.observe(ref.current); } - - scrollElement.addEventListener('scroll', handleScroll, true); - return () => { - scrollElement.removeEventListener('scroll', handleScroll, true); + if (observer) { + observer.disconnect(); + } }; - }, [ref, setIsSticky, scrollElement]); + }, [ref]); return { ref, isSticky }; } diff --git a/package.json b/package.json index 5153f6cc..71452dca 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "node-fetch": "^3.2.8", "npm-run-all": "^4.1.5", "react": "^18.2.0", - "react-basics": "^0.73.0", + "react-basics": "^0.74.0", "react-beautiful-dnd": "^13.1.0", "react-dom": "^18.2.0", "react-intl": "^5.24.7", diff --git a/yarn.lock b/yarn.lock index ed85f811..28d0d787 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7076,10 +7076,10 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-basics@^0.73.0: - version "0.73.0" - resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.73.0.tgz#9555563f3407ac417dc833dfca47588123d55535" - integrity sha512-eEK8yWWrXO7JATBlPKBfFQlD1hNZoNeEtlYNx+QjOCLKu1qjClutP5nXWHmX4gHE97XFwUKzbTU35NkNEy5C0w== +react-basics@^0.74.0: + version "0.74.0" + resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.74.0.tgz#153433bc485d6b71d8edf377d1a83f1d55133e24" + integrity sha512-Z9XwgEOSRvcPqFqFZL6HR59t/XrqhIB8uoYwbmon3IFX2W0kOPqkX1Box0c+2BibJoHp4N4mbfuZWK2kSEnq9g== dependencies: classnames "^2.3.1" date-fns "^2.29.3"