@@ -521,6 +521,7 @@ export function TabStrip({
521521 const autoScrollRafRef = useRef < number | null > ( null )
522522 const autoScrollDirectionRef = useRef ( 0 )
523523 const revealScrollRef = useRef < AnimationPlaybackControls | null > ( null )
524+ const revealScrollLeftRef = useRef ( 0 )
524525 const focusedTabRef = useRef < {
525526 id : string
526527 element : HTMLButtonElement
@@ -607,6 +608,7 @@ export function TabStrip({
607608 revealScrollRef . current = animate ( node . scrollLeft , nextLeft , {
608609 ...REVEAL_SCROLL_TRANSITION ,
609610 onUpdate : ( left ) => {
611+ revealScrollLeftRef . current = left
610612 node . scrollLeft = left
611613 } ,
612614 } )
@@ -626,17 +628,25 @@ export function TabStrip({
626628 revealActiveTab ( )
627629 }
628630 updateLayout ( )
629- node . addEventListener ( 'scroll' , updateOverflow , { passive : true } )
631+ const handleScroll = ( ) => {
632+ updateOverflow ( )
633+ // A position the reveal did not set means touch, the scrollbar, or the
634+ // keyboard took over scrolling, so the reveal yields to it.
635+ if ( revealScrollRef . current && Math . abs ( node . scrollLeft - revealScrollLeftRef . current ) > 1 ) {
636+ stopRevealScroll ( )
637+ }
638+ }
639+ node . addEventListener ( 'scroll' , handleScroll , { passive : true } )
630640 if ( typeof ResizeObserver === 'undefined' ) {
631- return ( ) => node . removeEventListener ( 'scroll' , updateOverflow )
641+ return ( ) => node . removeEventListener ( 'scroll' , handleScroll )
632642 }
633643 const observer = new ResizeObserver ( updateLayout )
634644 observer . observe ( node )
635645 return ( ) => {
636646 observer . disconnect ( )
637- node . removeEventListener ( 'scroll' , updateOverflow )
647+ node . removeEventListener ( 'scroll' , handleScroll )
638648 }
639- } , [ regularTabs . length , revealActiveTab , updateOverflow ] )
649+ } , [ regularTabs . length , revealActiveTab , stopRevealScroll , updateOverflow ] )
640650
641651 useEffect ( ( ) => {
642652 const strip = stripRef . current
@@ -658,12 +668,7 @@ export function TabStrip({
658668 event . preventDefault ( )
659669 }
660670 strip . addEventListener ( 'wheel' , handleWheel , { passive : false } )
661- // Touch, pen, and scrollbar drags scroll natively without a wheel event.
662- strip . addEventListener ( 'pointerdown' , stopRevealScroll )
663- return ( ) => {
664- strip . removeEventListener ( 'wheel' , handleWheel )
665- strip . removeEventListener ( 'pointerdown' , stopRevealScroll )
666- }
671+ return ( ) => strip . removeEventListener ( 'wheel' , handleWheel )
667672 } , [ stopRevealScroll , updateOverflow ] )
668673
669674 const handleDragStart = useCallback (
0 commit comments