@@ -7,7 +7,7 @@ import FixIssuesContentPreview from './Widgets/FixIssuesContentPreview'
77import LeftArrowIcon from './Icons/LeftArrowIcon'
88import RightArrowIcon from './Icons/RightArrowIcon'
99import CloseIcon from './Icons/CloseIcon'
10- import { FORM_CLASSIFICATIONS , formFromIssue , formNameFromRule , formNames } from '../Services/Ufixit'
10+ import { formNameFromRule } from '../Services/Ufixit'
1111import * as Html from '../Services/Html'
1212import Api from '../Services/Api'
1313
@@ -34,14 +34,14 @@ export default function FixIssuesPage({
3434 initialSeverity = '' ,
3535 initialSearchTerm = '' ,
3636 contentItemCache,
37- addContentItemToCache,
3837 report,
3938 sections,
4039 processNewReport,
4140 addMessage,
4241 sessionIssues,
4342 updateSessionIssue,
44- processServerError
43+ processServerError,
44+ setModalActive
4545} )
4646{
4747
@@ -66,9 +66,10 @@ export default function FixIssuesPage({
6666
6767 const WIDGET_STATE = settings . WIDGET_STATE
6868
69- const dialogId = "issue-dialog"
69+ const dialogId = "udoit- issue-dialog"
7070
7171 const [ activeIssue , setActiveIssue ] = useState ( null )
72+ const [ mostRecentIssueId , setMostRecentIssueId ] = useState ( null )
7273 const [ tempActiveIssue , setTempActiveIssue ] = useState ( null )
7374 const [ activeContentItem , setActiveContentItem ] = useState ( null )
7475 const [ tempActiveContentItem , setTempActiveContentItem ] = useState ( null )
@@ -250,6 +251,39 @@ export default function FixIssuesPage({
250251 }
251252 } , [ ] )
252253
254+ const handleEscapeKey = ( e ) => {
255+ if ( e . key === 'Escape' && widgetState === WIDGET_STATE . FIXIT ) {
256+ e . preventDefault ( )
257+ closeDialog ( )
258+ }
259+ }
260+
261+ // Pull focus into the dialog when it opens, and return focus to the most recently clicked issue when it closes
262+ useEffect ( ( ) => {
263+ if ( widgetState === WIDGET_STATE . FIXIT ) {
264+ const dialog = document . getElementById ( dialogId )
265+ if ( dialog ) {
266+ dialog . addEventListener ( 'keydown' , handleEscapeKey )
267+ const title = dialog . querySelector ( '#ufixit-dialog-title' )
268+ if ( title ) {
269+ title . focus ( )
270+ }
271+ }
272+ }
273+ else if ( widgetState === WIDGET_STATE . LIST ) {
274+ if ( mostRecentIssueId ) {
275+ const issueElement = document . getElementById ( `issue-item-${ mostRecentIssueId } ` )
276+ if ( issueElement ) {
277+ issueElement . focus ( )
278+ }
279+ const dialog = document . getElementById ( dialogId )
280+ if ( dialog ) {
281+ dialog . removeEventListener ( 'keydown' , handleEscapeKey )
282+ }
283+ }
284+ }
285+ } , [ widgetState ] )
286+
253287 // When the filters or search term changes, update the filtered issues list
254288 useEffect ( ( ) => {
255289
@@ -350,9 +384,14 @@ export default function FixIssuesPage({
350384 return
351385 }
352386
353- setWidgetState ( settings . WIDGET_STATE . FIXIT )
354- const activeIssueClone = JSON . parse ( JSON . stringify ( activeIssue ) )
387+ setMostRecentIssueId ( activeIssue . id )
388+
389+ // We ONLY want this to trigger events on a real change.
390+ if ( widgetState !== WIDGET_STATE . FIXIT ) {
391+ openDialog ( )
392+ }
355393
394+ const activeIssueClone = JSON . parse ( JSON . stringify ( activeIssue ) )
356395 activeIssueClone . issueData . initialHtml = Html . getIssueHtml ( activeIssueClone . issueData )
357396 setTempActiveIssue ( activeIssueClone )
358397
@@ -365,7 +404,6 @@ export default function FixIssuesPage({
365404 setActiveContentItem ( null )
366405 }
367406 setShowLearnMore ( false )
368- openDialog ( )
369407
370408 } , [ activeIssue ] )
371409
@@ -824,34 +862,24 @@ export default function FixIssuesPage({
824862
825863 const openDialog = ( ) => {
826864 setWidgetState ( WIDGET_STATE . FIXIT )
827-
828- const dialog = document . getElementById ( dialogId )
829- if ( dialog && ! dialog . open ) {
830- dialog . showModal ( )
831-
832- const title = dialog . querySelector ( '#dialog-title' )
833- if ( title ) {
834- title . focus ( )
835- }
836- }
865+ setModalActive ( true )
837866 }
838867
839868 const closeDialog = ( ) => {
840869 setWidgetState ( WIDGET_STATE . LIST )
870+ setModalActive ( false )
841871 setActiveIssue ( null )
842-
843- const dialog = document . getElementById ( dialogId )
844- if ( dialog ) {
845- dialog . close ( )
846- }
847872 }
848873
849874 return (
850875 < >
851876 { widgetState === settings . WIDGET_STATE . LOADING ? (
852877 < > </ >
853878 ) : (
854- < >
879+ < div
880+ inert = { widgetState === WIDGET_STATE . FIXIT ? "inert" : undefined }
881+ aria-hidden = { widgetState === WIDGET_STATE . FIXIT }
882+ >
855883 < h1 className = "pageTitle" > { t ( 'barriers.title' ) } </ h1 >
856884 < p className = "pageSubtitle" > { t ( 'barriers.subtitle' ) } </ p >
857885
@@ -873,12 +901,19 @@ export default function FixIssuesPage({
873901 groupedList = { groupedList }
874902 setActiveIssue = { setActiveIssue }
875903 />
876- </ >
904+ </ div >
877905 ) }
878- < dialog id = { dialogId } className = "dialog-full-screen" onClose = { closeDialog } aria-labelledby = "dialog-title" >
906+ < div
907+ id = { dialogId }
908+ role = "dialog"
909+ aria-modal = "true"
910+ className = { `dialog-full-screen ${ widgetState === WIDGET_STATE . FIXIT ? 'open' : 'hidden' } ` }
911+ onClose = { closeDialog }
912+ aria-labelledby = "ufixit-dialog-title"
913+ >
879914 < div className = "flex-column h-100" >
880915 < div className = "dialog-header" >
881- < h2 id = "dialog-title" tabIndex = "-1" > { tempActiveIssue ?. formLabel } </ h2 >
916+ < h2 id = "ufixit- dialog-title" tabIndex = "-1" > { tempActiveIssue ?. formLabel } </ h2 >
882917 < CloseIcon
883918 onClick = { closeDialog }
884919 onKeyDown = { ( e ) => {
@@ -984,7 +1019,7 @@ export default function FixIssuesPage({
9841019 </ div >
9851020 </ div >
9861021 </ div >
987- </ dialog >
1022+ </ div >
9881023 </ >
9891024 )
9901025}
0 commit comments