Task 4b: Fix PatientBanner scroll condensation
Root cause: sentinel element with `absolute top-0` inside PatientBanner was positioned at viewport top, always triggering the IntersectionObserver's -100px rootMargin threshold — banner was permanently stuck in condensed state. Fix: Restructured PMRInterface layout from document-scroll to flex container with explicit scroll container (`overflow-y-auto` on main). Lifted scroll condensation logic to PMRInterface, passing `isCondensed` prop down to PatientBanner. Replaced IntersectionObserver with scroll event listener on the main element for reliable scroll position detection. Key changes: - PMRInterface: flex h-screen overflow-hidden layout (sidebar + content column) - PatientBanner: accepts isCondensed prop, removed sticky/sentinel/hook - ClinicalSidebar: h-full instead of h-screen sticky (parent handles sizing) - useScrollCondensation: scroll event on container element via callback ref Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,35 +1,30 @@
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
|
||||
interface UseScrollCondensationOptions {
|
||||
threshold?: number
|
||||
scrollContainer?: HTMLElement | null
|
||||
}
|
||||
|
||||
export function useScrollCondensation(options: UseScrollCondensationOptions = {}) {
|
||||
const { threshold = 100 } = options
|
||||
const { threshold = 100, scrollContainer } = options
|
||||
const [isCondensed, setIsCondensed] = useState(false)
|
||||
const sentinelRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const handleScroll = useCallback(() => {
|
||||
if (!scrollContainer) return
|
||||
setIsCondensed(scrollContainer.scrollTop >= threshold)
|
||||
}, [scrollContainer, threshold])
|
||||
|
||||
useEffect(() => {
|
||||
const sentinel = sentinelRef.current
|
||||
if (!sentinel) return
|
||||
if (!scrollContainer) return
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
const [entry] = entries
|
||||
setIsCondensed(!entry.isIntersecting)
|
||||
},
|
||||
{
|
||||
rootMargin: `-${threshold}px 0px 0px 0px`,
|
||||
threshold: 0,
|
||||
}
|
||||
)
|
||||
|
||||
observer.observe(sentinel)
|
||||
scrollContainer.addEventListener('scroll', handleScroll, { passive: true })
|
||||
// Check initial state
|
||||
handleScroll()
|
||||
|
||||
return () => {
|
||||
observer.disconnect()
|
||||
scrollContainer.removeEventListener('scroll', handleScroll)
|
||||
}
|
||||
}, [threshold])
|
||||
}, [scrollContainer, handleScroll])
|
||||
|
||||
return { isCondensed, sentinelRef }
|
||||
return { isCondensed }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user