@@ -171,6 +171,19 @@ function SideDrawerPush({ open, onClose, title, backLabel, host, hostWidth, chil
171171 const el = host . current ;
172172 return ( ) => pageOf ( el ) . forEach ( ( p ) => { p . style . transition = '' ; p . style . translate = '' ; } ) ;
173173 } , [ host ] ) ;
174+ // A pushed page takes focus (so Escape and the keyboard land in it); popping hands it back to where it came from.
175+ const returnTo = useRef < HTMLElement | null > ( null ) ;
176+ const focusedOpen = useRef ( open ) ;
177+ useEffect ( ( ) => {
178+ if ( focusedOpen . current === open ) return ;
179+ focusedOpen . current = open ;
180+ if ( open ) {
181+ returnTo . current = document . activeElement instanceof HTMLElement ? document . activeElement : null ;
182+ panel . current ?. focus ( { preventScroll : true } ) ;
183+ } else if ( panel . current ?. contains ( document . activeElement ) ) {
184+ returnTo . current ?. focus ( { preventScroll : true } ) ;
185+ }
186+ } , [ open ] ) ;
174187
175188 const down = ( e : React . PointerEvent ) => {
176189 if ( e . button || ! open ) return ;
@@ -231,12 +244,12 @@ function SideDrawerPush({ open, onClose, title, backLabel, host, hostWidth, chil
231244 'absolute inset-0 bg-black transition-opacity duration-spring-smooth ease-spring-smooth motion-reduce:transition-none' ,
232245 open ? 'pointer-events-auto opacity-12' : 'pointer-events-none opacity-0' ,
233246 ) } />
234- < div ref = { panel } data-slot = "side-drawer-panel" role = "dialog" aria-label = { typeof title === 'string' ? title : undefined }
247+ < div ref = { panel } data-slot = "side-drawer-panel" role = "dialog" tabIndex = { - 1 } aria-label = { typeof title === 'string' ? title : undefined }
235248 aria-hidden = { ! open } inert = { ! open || undefined }
236249 onPointerDownCapture = { down } onPointerMove = { move } onPointerUp = { up } onPointerCancel = { up }
237250 onKeyDown = { ( e ) => { if ( e . key === 'Escape' && open ) { e . stopPropagation ( ) ; onClose ?.( ) ; } } }
238251 className = { cn (
239- 'absolute inset-0 flex touch-pan-y flex-col overflow-hidden bg-background will-change-transform [transform:translateX(var(--side-drawer-x))] transition-transform duration-spring-smooth ease-spring-smooth motion-reduce:transition-none' ,
252+ 'absolute inset-0 flex touch-pan-y flex-col overflow-hidden bg-background outline-none will-change-transform [transform:translateX(var(--side-drawer-x))] transition-transform duration-spring-smooth ease-spring-smooth motion-reduce:transition-none' ,
240253 open ? 'pointer-events-auto' : 'pointer-events-none' ,
241254 ( open || shown ) && 'shadow-[-10px_0_30px_black] shadow-black/16' ,
242255 ! open && ! shown && 'invisible' ,
0 commit comments