Change top bar to only appear whene scrolling up
This commit is contained in:
@@ -29,11 +29,14 @@ function onFilterChange(event) {
|
||||
}
|
||||
|
||||
// Scroll-driven show/hide: the header slides out of view on scroll-down and
|
||||
// back in on scroll-up. This is show/hide via `transform` (not the old
|
||||
// resize behaviour) — the header is position:fixed, so translating it never
|
||||
// reflows content, and the app's programmatic scrolls resolve to sensible
|
||||
// states: scrollTo(0, 0) lands near the top → shown; the list-view
|
||||
// read-correction scrollBy moves only a few px → stays under the threshold.
|
||||
// back in only on scroll-up — never merely by proximity to the top. This is
|
||||
// show/hide via `transform` (not the old resize behaviour) — the header is
|
||||
// position:fixed, so translating it never reflows content. The app's
|
||||
// programmatic scrolls resolve to sensible states without any top-of-page
|
||||
// special case: scrollTo(0, 0) (article paging, layout toggle) is itself a
|
||||
// large upward jump, so it crosses REVEAL_THRESHOLD like a real scroll-up and
|
||||
// reveals the header that way; the list-view read-correction scrollBy moves
|
||||
// only a few px → stays under the threshold and leaves a hidden header hidden.
|
||||
const hidden = ref(false)
|
||||
const REVEAL_THRESHOLD = 12 // px of accumulated travel before toggling
|
||||
// When the feed list mutates itself (read-correction scrollBy + array-splice
|
||||
@@ -45,25 +48,13 @@ const REVEAL_THRESHOLD = 12 // px of accumulated travel before toggling
|
||||
const PROGRAMMATIC_SUPPRESS_MS = 300
|
||||
let lastY = 0
|
||||
let accumulated = 0
|
||||
// Cached in onMounted() below instead of re-read via headerRef.offsetHeight
|
||||
// on every scroll event. The header is a fixed size (see onMounted), so
|
||||
// re-measuring it here was pure waste — worse, a DevTools performance trace
|
||||
// showed that offsetHeight read landing right after an unrelated DOM write
|
||||
// elsewhere on the page (e.g. the article view swapping in a new article)
|
||||
// forces the browser into a synchronous, forced-reflow layout pass right
|
||||
// there mid-script, instead of its normal scheduled one. Stays 0 until
|
||||
// onMounted() below sets it (before the scroll listener is attached, so
|
||||
// onScroll() never runs against the unset value) — keep that ordering if
|
||||
// this ever changes.
|
||||
let headerHeight = 0
|
||||
|
||||
function onScroll() {
|
||||
const y = Math.max(0, window.scrollY)
|
||||
|
||||
// Always reveal near the very top, and keep it visible while the menu is
|
||||
// open (the dropdown is anchored to the header, so hiding it would slide the
|
||||
// open menu off-screen).
|
||||
if (y <= headerHeight || menuOpen.value) {
|
||||
// Keep the header visible while the menu is open (the dropdown is anchored
|
||||
// to the header, so hiding it would slide the open menu off-screen).
|
||||
if (menuOpen.value) {
|
||||
hidden.value = false
|
||||
accumulated = 0
|
||||
lastY = y
|
||||
@@ -99,11 +90,9 @@ function onScrollRaf() {
|
||||
onMounted(() => {
|
||||
// Drives #app's padding-top / RssFeeds' scroll-margin-top so content below
|
||||
// the fixed header isn't hidden behind it at scroll position 0. The header is
|
||||
// a fixed size, so this is measured once on mount and never changes — and
|
||||
// onScroll() reuses this same measurement instead of re-reading it.
|
||||
// a fixed size, so this is measured once on mount and never changes.
|
||||
const h = headerRef.value?.getBoundingClientRect().height ?? 0
|
||||
document.documentElement.style.setProperty('--app-nav-height', `${h}px`)
|
||||
headerHeight = h
|
||||
|
||||
lastY = Math.max(0, window.scrollY)
|
||||
window.addEventListener('scroll', onScrollRaf, { passive: true })
|
||||
|
||||
Reference in New Issue
Block a user