Change:
Testing Have multiple terminal tabs open. In one tab have a couple of split terminals. Visually they look like they belong to a tree, however this information is not conveyed to the screen reader. Here are some ideas on how to improve this: Put for elements that are inside the tree. Currently all elements have an aria-level = 1. If you prefer to leave it like that then the role of the whole thing should be a and not a Modify aria label of an element in case he is part of a split
We're converting this into a list next iteration , I think we need to indicate to the screen reader that it's a split though. Not sure how the special characters are read out now.
hmm, should we be surfacing the fact that it's a split terminal to the screen reader at all? I think it's purely a UI feature so it shouldn't make a difference if you can't see the UI?
oh great that you moving to the list. You should have a correct role then. I would still convey the group number as part of the aria label, since we do the same for editors in editor groups. It is useful for users to know how things are grouped on the screen in case there are navigation actions like switch tab, or move focus inside a terminal tab. Just make sure that the group label is at the end of the list element aria label so it is easy to skip. Special character is not read out now because it is not part of the aria label.
Good point
Scoped this issue down, conversion to list will be handled in
I see the code changes which look good, however when I try this out the group is not applied to the aria label, it is the same as before. I have a ZSH, one tab with one terminal, and another tabs with two terminals. And all their labels are just
! When I inspect a split terminal tab label, it has the correct aria label.
Oh but you are setting the on the wrong HTML element You should use the so the is properly set on the element. It has to be on that element, since that element has focus and that is what the Screen Reader will read. So I think it should be fixed here

Discussion:
import { IListService, WorkbenchObjectTree } from 'vs/platform/list/browser/listService'; import { ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; <del> import { DefaultStyleController } from 'vs/base/browser/ui/list/listWidget'; </del> <ins> import { DefaultStyleController, IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; </ins> import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';

identityProvider: { getId: e => e?.instanceId }, <del> accessibilityProvider: { getAriaLabel: e => e?.title, getWidgetAriaLabel: () => localize('terminal.tabs', "Terminal tabs") }, </del> <ins> accessibilityProvider: instantiationService.createInstance(TerminalTabsAccessibilityProvider), </ins> styleController: id => new DefaultStyleController(DOM.createStyleSheet(container), id), filter: undefined, smoothScrolling: configurationService.getValue<boolean>('workbench.list.smoothScrolling'),

const hasText = !this.shouldHideText(); template.element.classList.toggle('has-text', hasText); <del> let ariaLabel: string = ''; </del> let prefix: string = ''; if (tab.terminalInstances.length > 1) { const terminalIndex = tab.terminalInstances.indexOf(instance); <del> ariaLabel = localize({ key: 'splitTerminalAriaLabel', comment: [ `The terminal's ID`, `The terminal's title`, `The terminal's split number`, `The terminal group's total split number` ] }, "Terminal {0} {1}, split {2} of {3}", instance.instanceId, instance.title, terminalIndex + 1, tab.terminalInstances.length); </del> if (terminalIndex === 0) { prefix = `┌ `; } else if (terminalIndex === tab!.terminalInstances.length - 1) {

} else { prefix = `├ `; } <del> } else { ariaLabel = localize({ key: 'terminalAriaLabel', comment: [ `The terminal's ID`, `The terminal's title` ] }, "Terminal {0} {1}", instance.instanceId, instance.title); </del> } let title = instance.title;

const primaryStatus = instance.statusList.primary; if (primaryStatus && primaryStatus.severity >= Severity.Warning) { label = `${prefix}$(${primaryStatus.icon?.id || instance.icon?.id})`; <del> ariaLabel = ''; </del> } else { label = `${prefix}$(${instance.icon?.id})`; }

} })); <del> // Set aria lable to expose split information to screen reader template.label.element.querySelector('.label-name')?.setAttribute('aria-label', ariaLabel); </del> template.label.setResource({ resource: instance.resource, name: label,

}; elementDispoables?: DisposableStore; } <ins> class TerminalTabsAccessibilityProvider implements IListAccessibilityProvider<ITerminalInstance> { constructor(@ITerminalService private readonly _terminalService: ITerminalService) { } getWidgetAriaLabel(): string { return localize('terminal.tabs', "Terminal tabs"); } getAriaLabel(instance: ITerminalInstance): string { let ariaLabel: string = ''; const tab = this._terminalService.getTabForInstance(instance); if (tab && tab.terminalInstances?.length > 1) { const terminalIndex = tab.terminalInstances.indexOf(instance); ariaLabel = localize({ key: 'splitTerminalAriaLabel', comment: [ `The terminal's ID`, `The terminal's title`, `The terminal's split number`, `The terminal group's total split number` ] }, "Terminal {0} {1}, split {2} of {3}", instance.instanceId, instance.title, terminalIndex + 1, tab.terminalInstances.length); } else { ariaLabel = localize({ key: 'terminalAriaLabel', comment: [ `The terminal's ID`, `The terminal's title` ] }, "Terminal {0} {1}", instance.instanceId, instance.title); } return ariaLabel; } } </ins>