@@ -47,7 +47,13 @@ const ROW_HEIGHT = 28;
4747const STATIC_BEFORE = 19 ;
4848const STATIC_AFTER = 60 ;
4949
50- export const DeclarationsSidebar = ( { onNavigate } : { onNavigate ?: ( ) => void } ) => {
50+ export const DeclarationsSidebar = ( {
51+ onNavigate,
52+ sidebarOpen,
53+ } : {
54+ onNavigate ?: ( ) => void ;
55+ sidebarOpen ?: boolean ;
56+ } ) => {
5157 const { declarations, game } = useContext ( DeclarationsContext ) ;
5258 const { filter, setFilter } = useContext ( SidebarFilterContext ) ;
5359 const { module : activeModule = "" , scope = "" } = useParams ( ) ;
@@ -191,6 +197,21 @@ export const DeclarationsSidebar = ({ onNavigate }: { onNavigate?: () => void })
191197 }
192198 } , [ activeModule , scope , activeIndex , virtualizer ] ) ;
193199
200+ // When the mobile sidebar opens, the virtualizer's scroll element transitions
201+ // from display:none to display:flex. The element had zero dimensions while hidden,
202+ // so the virtualizer rendered no items and scrollTop was lost. Re-measure and
203+ // scroll to the active item.
204+ useEffect ( ( ) => {
205+ if ( ! sidebarOpen || ! parentRef . current ) return ;
206+ const raf = requestAnimationFrame ( ( ) => {
207+ virtualizer . measure ( ) ;
208+ if ( activeIndex >= 0 ) {
209+ virtualizer . scrollToIndex ( activeIndex , { align : "center" } ) ;
210+ }
211+ } ) ;
212+ return ( ) => cancelAnimationFrame ( raf ) ;
213+ } , [ sidebarOpen ] ) ;
214+
194215 const handleSidebarNavigate = useCallback ( ( ) => {
195216 navigatedFromSidebarRef . current = true ;
196217 onNavigate ?.( ) ;
@@ -312,6 +333,7 @@ const SidebarSearchInput = styled(SearchInput)`
312333const SidebarList = styled . div `
313334 flex: 1;
314335 overflow: auto;
336+ overscroll-behavior: contain;
315337` ;
316338
317339const SidebarUl = styled . ul `
0 commit comments