@@ -32,49 +32,42 @@ const useMediaQuery = (query: string) => {
3232export const Overview = ( pr : PullRequest ) => {
3333 const isSingleColumnLayout = useMediaQuery ( '(max-width: 768px)' ) ;
3434 const titleRef = React . useRef < HTMLDivElement > ( null ) ;
35- const sentinelRef = React . useRef < HTMLDivElement > ( null ) ;
3635
3736 React . useEffect ( ( ) => {
38- const sentinel = sentinelRef . current ;
3937 const title = titleRef . current ;
4038
41- if ( ! sentinel || ! title ) {
39+ if ( ! title ) {
4240 return ;
4341 }
4442
4543 // Initially ensure title is not stuck
4644 title . classList . remove ( 'stuck' ) ;
4745
48- // Use IntersectionObserver to detect when the title becomes sticky
49- // The sentinel is positioned right before the title
50- // When sentinel scrolls out of view (past the top), title becomes stuck
51- const observer = new IntersectionObserver (
52- ( [ entry ] ) => {
53- // When sentinel is intersecting (visible), title is NOT stuck
54- // When sentinel is not intersecting (scrolled past top), title IS stuck
55- if ( entry . isIntersecting ) {
56- title . classList . remove ( 'stuck' ) ;
57- } else {
58- title . classList . add ( 'stuck' ) ;
59- }
60- } ,
61- {
62- // Use threshold 1 to only trigger when sentinel is fully visible/invisible
63- // This prevents false positives when sentinel is partially visible
64- threshold : [ 1 ]
46+ // Use scroll event to detect when title actually becomes sticky
47+ // Check if the title's top position is at the viewport top (sticky position)
48+ const handleScroll = ( ) => {
49+ const rect = title . getBoundingClientRect ( ) ;
50+ // Title is stuck when its top is at position 0 (sticky top: 0)
51+ // Add small threshold to account for sub-pixel rendering
52+ if ( rect . top <= 1 ) {
53+ title . classList . add ( 'stuck' ) ;
54+ } else {
55+ title . classList . remove ( 'stuck' ) ;
6556 }
66- ) ;
57+ } ;
58+
59+ // Check initial state after a brief delay to ensure layout is settled
60+ const timeoutId = setTimeout ( handleScroll , 100 ) ;
6761
68- observer . observe ( sentinel ) ;
62+ window . addEventListener ( 'scroll' , handleScroll , { passive : true } ) ;
6963
7064 return ( ) => {
71- observer . disconnect ( ) ;
65+ clearTimeout ( timeoutId ) ;
66+ window . removeEventListener ( 'scroll' , handleScroll ) ;
7267 } ;
7368 } , [ ] ) ;
7469
7570 return < >
76- { /* Sentinel element positioned just before the sticky title */ }
77- < div ref = { sentinelRef } style = { { height : '1px' } } />
7871 < div id = "title" className = "title" ref = { titleRef } >
7972 < div className = "details" >
8073 < Header { ...pr } />
0 commit comments