Found while diagnosing a CI failure in LibreChat-AI#15684 (projects.spec.ts, long-metadata test).
After the viewport crosses from desktop width back to phone width without a reload, opening the mobile drawer takes the desktop toggle path: kickDrawerAnimation finds no registered drawer animator and returns 'none', so OpenSidebar starts its desktop-only 250ms timer that focuses CLOSE_SIDEBAR_ID. In the drawer that id is the close button, so focus is pulled out of whatever the user opened in the meantime; a sidebar row's options menu opened within that window is dismissed about 200ms after it appears.
Observed with focus logging: the menu receives focus, about 180ms later focus moves to close-sidebar-button, and the menu is removed. A fresh load at phone width does not show it (the drawer registers its slide and the mode is 'slide').
Surfaces: client/src/routes/Root.tsx (useDrawerSwipe enablement), client/src/hooks/Nav/useDrawerSwipe.ts (animator registration across a breakpoint cross), client/src/components/Chat/Menus/OpenSidebar.tsx (the 'none' focus timer).
Expected: crossing the breakpoint re-registers the drawer animator, or the desktop focus timer does not run while the mobile drawer is the sidebar.
Found while diagnosing a CI failure in LibreChat-AI#15684 (projects.spec.ts, long-metadata test).
After the viewport crosses from desktop width back to phone width without a reload, opening the mobile drawer takes the desktop toggle path:
kickDrawerAnimationfinds no registered drawer animator and returns'none', soOpenSidebarstarts its desktop-only 250ms timer that focusesCLOSE_SIDEBAR_ID. In the drawer that id is the close button, so focus is pulled out of whatever the user opened in the meantime; a sidebar row's options menu opened within that window is dismissed about 200ms after it appears.Observed with focus logging: the menu receives focus, about 180ms later focus moves to
close-sidebar-button, and the menu is removed. A fresh load at phone width does not show it (the drawer registers its slide and the mode is'slide').Surfaces:
client/src/routes/Root.tsx(useDrawerSwipeenablement),client/src/hooks/Nav/useDrawerSwipe.ts(animator registration across a breakpoint cross),client/src/components/Chat/Menus/OpenSidebar.tsx(the'none'focus timer).Expected: crossing the breakpoint re-registers the drawer animator, or the desktop focus timer does not run while the mobile drawer is the sidebar.