In these examples, clicking outside of an active focus trap will disable the focus trap. This is not the default behavior. It's just a workaround so focus behavior is not broken on the page if a user forgets to disable the focus trap after interacting with the example.
Enable trap Before trap Focus trap is disabled . Focus will not be trapped in here.
First trapped Second trapped Third trapped After trap code editor import React from 'react'
import { useFocusTrap , useOnOutsideClick } from '@primer/react'
export default function Default ( ) {
const [ trapEnabled , setTrapEnabled ] = React . useState ( false )
const { containerRef } = useFocusTrap ( { disabled : ! trapEnabled } )
const exampleContainerRef = React . useRef < HTMLDivElement > (null)
useOnOutsideClick( {
onClickOutside : ( ) => {
setTrapEnabled ( false )
} ,
containerRef : exampleContainerRef ,
} )
/* END: not needed for using `useFocusTrap` */
return (
< div ref = { exampleContainerRef } style = { { display : 'flex' , flexDirection : 'column' , gap : '1rem' } } >
< button onClick = { ( ) => setTrapEnabled ( ! trapEnabled ) } > { trapEnabled ? 'Disable' : 'Enable' } trap </ button >
< button > Before trap </ button >
< div
ref = { containerRef as React . RefObject < HTMLDivElement > }
style = { {
border : '1px solid' ,
margin : '1rem' ,
padding : '1rem' ,
display : 'flex' ,
flexDirection : 'column' ,
gap : '1rem' ,
} }
>
{ trapEnabled ? (
< div >
Focus trap is < strong > enabled </ strong > . Focus will be trapped in here.
</ div >
) : (
< div >
Focus trap is < strong > disabled </ strong > . Focus will < strong > not </ strong > be trapped in here.
</ div >
) }
< button > First trapped </ button >
< button > Second trapped </ button >
< button > Third trapped </ button >
</ div >
< button > After trap </ button >
</ div >
)
}
Enable trap Before trap Focus trap is disabled . Focus will not be trapped in here.
First trapped Second trapped (focus goes here first) Third trapped After trap code editor import React from 'react'
import { useFocusTrap , useOnOutsideClick } from '@primer/react'
export default function Default ( ) {
const [ trapEnabled , setTrapEnabled ] = React . useState ( false )
const initialFocusRef = React . useRef < HTMLButtonElement > (null)
const { containerRef } = useFocusTrap( { disabled : ! trapEnabled , initialFocusRef } )
/* START: not needed for using `useFocusTrap`
This is just a workaround so focus behavior is not broken on the page if a
user forgets to disable the focus trap after interacting with the example.
*/
const exampleContainerRef = React.useRef < HTMLDivElement > (null)
useOnOutsideClick( {
onClickOutside : ( ) => {
setTrapEnabled ( false )
} ,
containerRef : exampleContainerRef ,
} )
/* END: not needed for using `useFocusTrap` */
return (
< div ref = { exampleContainerRef } style = { { display : 'flex' , flexDirection : 'column' , gap : '1rem' } } >
< button onClick = { ( ) => setTrapEnabled ( ! trapEnabled ) } > { trapEnabled ? 'Disable' : 'Enable' } trap </ button >
< button > Before trap </ button >
< div
ref = { containerRef as React . RefObject < HTMLDivElement > }
style = { {
border : '1px solid' ,
margin : '1rem' ,
padding : '1rem' ,
display : 'flex' ,
flexDirection : 'column' ,
gap : '1rem' ,
} }
>
{ trapEnabled ? (
< div >
Focus trap is < strong > enabled </ strong > . Focus will be trapped in here.
</ div >
) : (
< div >
Focus trap is < strong > disabled </ strong > . Focus will < strong > not </ strong > be trapped in here.
</ div >
) }
< button > First trapped </ button >
< button ref = { initialFocusRef } > Second trapped (focus goes here first) </ button >
< button > Third trapped </ button >
</ div >
< button > After trap </ button >
</ div >
)
}
Press the Escape key while focused in the trap to toggle the focus trap off.
When the focus trap is turned off, focus will return to the element focused before entering the focus trap.
Enable trap Before trap Focus trap is disabled . Focus will not be trapped in here.
First trapped Second trapped Third trapped After trap code editor import React from 'react'
import { useFocusTrap , useOnOutsideClick } from '@primer/react'
export default function Toggle ( ) {
const [ trapEnabled , setTrapEnabled ] = React . useState ( false )
const { containerRef } = useFocusTrap ( { disabled : ! trapEnabled , restoreFocusOnCleanUp : true } )
React . useEffect ( ( ) => {
if ( ! exampleContainerRef . current ?. contains ( document . activeElement ) ) {
return
}
const handleKeyDown = ( event : KeyboardEvent ) => {
if ( event . key === 'Escape' ) {
setTrapEnabled ( false )
}
}
window . addEventListener ( 'keydown' , handleKeyDown )
return ( ) => {
window . removeEventListener ( 'keydown' , handleKeyDown )
}
} )
const exampleContainerRef = React . useRef < HTMLDivElement > (null)
useOnOutsideClick( {
onClickOutside : ( ) => {
setTrapEnabled ( false )
} ,
containerRef : exampleContainerRef ,
} )
/* END: not needed for using `useFocusTrap` */
return (
< div ref = { exampleContainerRef } style = { { display : 'flex' , flexDirection : 'column' , gap : '1rem' } } >
< button onClick = { ( ) => setTrapEnabled ( ! trapEnabled ) } > { trapEnabled ? 'Disable' : 'Enable' } trap </ button >
< button > Before trap </ button >
< div
ref = { containerRef as React . RefObject < HTMLDivElement > }
style = { {
border : '1px solid' ,
margin : '1rem' ,
padding : '1rem' ,
display : 'flex' ,
flexDirection : 'column' ,
gap : '1rem' ,
} }
>
{ trapEnabled ? (
< div >
Focus trap is < strong > enabled </ strong > . Focus will be trapped in here.
</ div >
) : (
< div >
Focus trap is < strong > disabled </ strong > . Focus will < strong > not </ strong > be trapped in here.
</ div >
) }
< button > First trapped </ button >
< button > Second trapped </ button >
< button > Third trapped </ button >
</ div >
< button > After trap </ button >
</ div >
)
}
Press the Escape key while focused in the trap to toggle the focus trap off.
When the focus trap is turned off, focus will always return to the same element.
Enable trap Disabling the trap moves focus here Before trap Focus trap is disabled . Focus will not be trapped in here.
First trapped Second trapped Third trapped After trap code editor import React from 'react'
import { useFocusTrap , useOnOutsideClick } from '@primer/react'
export default function Toggle ( ) {
const [ trapEnabled , setTrapEnabled ] = React . useState ( false )
const returnFocusRef = React . useRef < HTMLButtonElement > (null)
const { containerRef } = useFocusTrap( {
disabled : ! trapEnabled ,
returnFocusRef : trapEnabled ? returnFocusRef : undefined ,
} )
/* Pressing the "Escape" key will turn the focus trap off */
React.useEffect(() => {
if ( ! exampleContainerRef . current ?. contains ( document . activeElement ) ) {
return
}
const handleKeyDown = ( event : KeyboardEvent ) => {
if ( event . key === 'Escape' ) {
setTrapEnabled ( false )
}
}
window . addEventListener ( 'keydown' , handleKeyDown )
return ( ) => {
window . removeEventListener ( 'keydown' , handleKeyDown )
}
} )
/* START: not needed for using `useFocusTrap`
This is just a workaround so focus behavior is not broken on the page if a
user forgets to disable the focus trap after interacting with the example.
*/
const exampleContainerRef = React.useRef < HTMLDivElement > (null)
useOnOutsideClick( {
onClickOutside : ( ) => {
setTrapEnabled ( false )
} ,
containerRef : exampleContainerRef ,
} )
/* END: not needed for using `useFocusTrap` */
return (
< div ref = { exampleContainerRef } style = { { display : 'flex' , flexDirection : 'column' , gap : '1rem' } } >
< button onClick = { ( ) => setTrapEnabled ( ! trapEnabled ) } > { trapEnabled ? 'Disable' : 'Enable' } trap </ button >
< button ref = { returnFocusRef } > Disabling the trap moves focus here </ button >
< button > Before trap </ button >
< div
ref = { containerRef as React . RefObject < HTMLDivElement > }
style = { {
border : '1px solid' ,
margin : '1rem' ,
padding : '1rem' ,
display : 'flex' ,
flexDirection : 'column' ,
gap : '1rem' ,
} }
>
{ trapEnabled ? (
< div >
Focus trap is < strong > enabled </ strong > . Focus will be trapped in here.
</ div >
) : (
< div >
Focus trap is < strong > disabled </ strong > . Focus will < strong > not </ strong > be trapped in here.
</ div >
) }
< button > First trapped </ button >
< button > Second trapped </ button >
< button > Third trapped </ button >
</ div >
< button > After trap </ button >
</ div >
)
}
Loading data for useFocusTrap...