Change:
Testing Press alt+F2, VoiceOver starts reading the response Press alt+], the view shows the next response but VoiceOver is still reading that response and it never reads the next response Maybe related, but sometimes, it also doesn't read the response when I press alt+F2. It will say "you are now on a text area" and just sit there. Then, it only wants to read the text a single character at a time when I move the cursor.
Actually, I believe this might be working as expected - I have to move the cursor for the screen reader to move on to the next content. and could you pls let us know if this is a bug or working as expected?
Unfortunately, this is a voiceover issue, but I believe last time we something like this it was resolved my slightly increasing the wait time for certain focus event. I don't remember the full context and cannot find the issue right now. does it sound familiar? It was related to the opening and closing of the contextual help I believe.
Great recall the issue you are talking about is
Correct. I believe it could be the same underlying cause. By the way, having to move the cursor to read content is totally fine as you described. the real issue is that Voiceover is not announcing the change of context.
Makes sense - because without that announcement, you wouldn't know to move your cursor
I wonder if we have a way to calculate the total number of responses. if we do, we could issue an alert announcing position information when we move back and forth. This would resolve the lack of context for macOs and improve the experience in the other platforms. Thoughts?
Yes that makes sense to me - I linked an issue where this is a request for the notification a11y view and we could also support this for the responses
It might have to be an August thing - I'll investigate.
this is also an issue for notifications
I think we have to go with what you suggested i tried a bunch of hacks and setTimeouts and it didn't work
I think it could make the feature more helpful for all platforms. Moving between suggestions is right now a bit confusing because I can't tell for sure if the one on focus is the last one, or if it truly moved to a different one after pressing the command. In the copilot chat panel, for example, I find much more practical and easier to simply move to the list of responses and go on from there. In addition, hacking assistive technology rarely justifies the effort, and often leads to undesirable outcomes that are not easy to anticipate.
it seems focus still gets trapped initially - even alert isn't taking precedent. i'm hoping it's just what I'm experiencing. about to make a PR with a change that does this for notifications and chat responses
What do you mean it gets trapped? Do you want me to review something. I have half an hour until next meeting.
yes, the linked PR please sorry I have been doing a lot atm
Verified by with the follow up item of to be addressed in August

Discussion:
import { NotificationFocusedContext } from 'vs/workbench/common/contextkeys'; import { IAccessibleViewService, AccessibleViewService, IAccessibleContentProvider, IAccessibleViewOptions, AccessibleViewType, accessibleViewIsShown } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { IHoverService } from 'vs/workbench/services/hover/browser/hover'; <ins> import { alert } from 'vs/base/browser/ui/aria/aria'; </ins> registerAccessibilityConfiguration(); registerSingleton(IAccessibleViewService, AccessibleViewService, InstantiationType.Delayed);

} commandService.executeCommand('notifications.showList'); let notificationIndex: number | undefined; <ins> let length: number | undefined; </ins> const list = listService.lastFocusedList; if (list instanceof WorkbenchList) { notificationIndex = list.indexOf(notification); <ins> length = list.length; </ins> } if (notificationIndex === undefined) { return false; } function focusList(): void { commandService.executeCommand('notifications.showList'); if (list && notificationIndex !== undefined) {

} focusList(); list.focusNext(); <ins> alertFocusChange(notificationIndex, length, 'next'); </ins> renderAccessibleView(); }, previous(): void {

} focusList(); list.focusPrevious(); <ins> alertFocusChange(notificationIndex, length, 'previous'); </ins> renderAccessibleView(); }, verbositySettingKey: AccessibilityVerbositySettingId.Notification,

} workbenchContributionsRegistry.registerWorkbenchContribution(AccessibleViewNavigatorContribution, LifecyclePhase.Eventually); <ins> export function alertFocusChange(index: number | undefined, length: number | undefined, type: 'next' | 'previous'): void { if (index === undefined || length === undefined) { return; } const number = index + 1; if (type === 'next' && number + 1 <= length) { alert(`Focused ${number + 1} of ${length}`); } else if (type === 'previous' && number - 1 > 0) { alert(`Focused ${number - 1} of ${length}`); } return; } </ins>

this._accessibleView = this._register(this._instantiationService.createInstance(AccessibleView)); } this._accessibleView.show(provider); } next(): void { this._accessibleView?.next();

import { ChatAccessibilityService } from 'vs/workbench/contrib/chat/browser/chatAccessibilityService'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { QuickQuestionMode } from 'vs/workbench/contrib/chat/browser/actions/quickQuestionActions/quickQuestionAction'; <ins> import { alertFocusChange } from 'vs/workbench/contrib/accessibility/browser/accessibility.contribution'; </ins> // Register configuration const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);

if (!responseContent) { return false; } <ins> const responses = verifiedWidget.viewModel?.getItems().filter(i => isResponseVM(i)); const length = responses?.length; const responseIndex = responses?.findIndex(i => i === focusedItem); </ins> accessibleViewService.show({ verbositySettingKey: AccessibilityVerbositySettingId.Chat,

}, next() { verifiedWidget.moveFocus(focusedItem, 'next'); <ins> alertFocusChange(responseIndex, length, 'next'); </ins> renderAccessibleView(accessibleViewService, widgetService, codeEditorService); }, previous() { verifiedWidget.moveFocus(focusedItem, 'previous'); <ins> alertFocusChange(responseIndex, length, 'previous'); </ins> renderAccessibleView(accessibleViewService, widgetService, codeEditorService); }, options: { ariaLabel: nls.localize('chatAccessibleView', "Chat Accessible View"), type: AccessibleViewType.View }