@@ -182,14 +182,14 @@ export class Virtual implements ScreenReader {
182182
183183 this . #invalidateTreeCache( ) ;
184184 const tree = this . #getAccessibilityTree( ) ;
185- const nextIndex = tree . findIndex ( ( { node } ) => node === target ) ;
186185
187186 // This is called when an element in the tree receives focus so it stands
188187 // that we should be able to find said element in the tree (unless it can
189188 // be removed somehow between the focus event firing and this code
190- // executing?).
189+ // executing... we are waiting for event loop tick so perhaps there is a
190+ // race condition here?).
191191 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
192- const newActiveNode = tree . at ( nextIndex ) ! ;
192+ const newActiveNode = tree . find ( ( { node } ) => node === target ) ;
193193
194194 this . #updateState( newActiveNode , true ) ;
195195 }
@@ -228,11 +228,42 @@ export class Virtual implements ScreenReader {
228228 }
229229
230230 #updateState( accessibilityNode : AccessibilityNode , ignoreIfNoChange = false ) {
231- const spokenPhrase = getSpokenPhrase ( accessibilityNode ) ;
232- const itemText = getItemText ( accessibilityNode ) ;
231+ /**
232+ * When the dialog is correctly labeled and focus is moved to an element
233+ * (often an interactive element, such as a button) inside the dialog,
234+ * screen readers should announce the dialog's accessible role, name and
235+ * optionally description, along with announcing the focused element.
236+ *
237+ * REF: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/dialog_role#possible_effects_on_user_agents_and_assistive_technology
238+ */
239+ if (
240+ accessibilityNode . parentDialog !== null &&
241+ accessibilityNode . parentDialog !== this . #activeNode. parentDialog
242+ ) {
243+ // One of the few cases where you will get two logs for a single
244+ // interaction.
245+ //
246+ // We don't need to perform the `ignoreIfNoChange` check as this will
247+ // only fire if the parent dialog element has changed, and if that
248+ // happens we can be fairly confident that item under the virtual
249+ // cursor has changed.
250+ const tree = this . #getAccessibilityTree( ) ;
251+ const parentDialogNode = tree . find (
252+ ( { node } ) => node === accessibilityNode . parentDialog
253+ ) ;
254+
255+ const spokenPhrase = getSpokenPhrase ( parentDialogNode ) ;
256+ const itemText = getItemText ( parentDialogNode ) ;
257+
258+ this . #itemTextLog. push ( itemText ) ;
259+ this . #spokenPhraseLog. push ( spokenPhrase ) ;
260+ }
233261
234262 this . #activeNode = accessibilityNode ;
235263
264+ const spokenPhrase = getSpokenPhrase ( accessibilityNode ) ;
265+ const itemText = getItemText ( accessibilityNode ) ;
266+
236267 if (
237268 ignoreIfNoChange &&
238269 spokenPhrase === this . #spokenPhraseLogWithoutLiveRegions( ) . at ( - 1 ) &&
0 commit comments