Files
accounted/components/ScrollbarReveal.tsx
T
admin e7f0070e84
masterplan-lock / check (push) Successful in 19s
ci / sonar (push) Failing after 21s
security / scan (push) Failing after 1m37s
fix(restore): återställ default branch-filer som raderades av docs-publiceringen (7e33543)
Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i
server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma
strängvärde byggs med konkatenering i stället för att matcha mönstret.
2026-11-10 09:37:22 +01:00

43 lines
1.2 KiB
TypeScript

'use client'
import { useEffect } from 'react'
// How long after the last scroll event the scrollbar stays visible.
const IDLE_MS = 700
/**
* Reveals scrollbars only while their container is actually scrolling.
* One capture-phase listener on the document catches scroll events from
* every scroll container (panel, sidebar, dialogs, dropdown lists) and
* stamps .is-scrolling on the scrolled element; globals.css makes the
* thumb visible for that class and transparent otherwise. Renders nothing.
*/
export function ScrollbarReveal() {
useEffect(() => {
const timers = new WeakMap<Element, number>()
const onScroll = (e: Event) => {
const target = e.target
const el =
target === document ? document.documentElement : (target as Element)
if (!(el instanceof Element)) return
el.classList.add('is-scrolling')
const prev = timers.get(el)
if (prev) window.clearTimeout(prev)
timers.set(
el,
window.setTimeout(() => el.classList.remove('is-scrolling'), IDLE_MS),
)
}
document.addEventListener('scroll', onScroll, {
capture: true,
passive: true,
})
return () =>
document.removeEventListener('scroll', onScroll, { capture: true })
}, [])
return null
}