Skip to content

Commit 6a0d1e9

Browse files
committed
fix(material/stepper): generalize stepper aria roles
Updates Angular Components Material Stepper to use general aria roles like group, region, button as opposed to tab, tablist, tabpanel as this doesn't serve the vertical stepper correctly. Fixes b/361783174
1 parent 020c6af commit 6a0d1e9

File tree

4 files changed

+30
-27
lines changed

4 files changed

+30
-27
lines changed

src/cdk/stepper/step-header.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {FocusableOption} from '../a11y';
1212
@Directive({
1313
selector: '[cdkStepHeader]',
1414
host: {
15-
'role': 'tab',
15+
'role': 'button',
1616
},
1717
})
1818
export class CdkStepHeader implements FocusableOption {

src/material/stepper/step-header.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import {_CdkPrivateStyleLoader, _VisuallyHiddenLoader} from '@angular/cdk/privat
3535
host: {
3636
'class': 'mat-step-header',
3737
'[class]': '"mat-" + (color || "primary")',
38-
'role': 'tab',
38+
'role': 'button',
3939
},
4040
encapsulation: ViewEncapsulation.None,
4141
changeDetection: ChangeDetectionStrategy.OnPush,

src/material/stepper/stepper.html

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
@switch (orientation) {
1212
@case ('horizontal') {
13-
<div class="mat-horizontal-stepper-wrapper">
13+
<div class="mat-horizontal-stepper-wrapper" role="group">
1414
<div class="mat-horizontal-stepper-header-container">
1515
@for (step of steps; track step) {
1616
<ng-container
@@ -27,7 +27,7 @@
2727
<div
2828
#animatedContainer
2929
class="mat-horizontal-stepper-content"
30-
role="tabpanel"
30+
role="region"
3131
[id]="_getStepContentId($index)"
3232
[attr.aria-labelledby]="_getStepLabelId($index)"
3333
[class]="'mat-horizontal-stepper-content-' + _getAnimationDirection($index)"
@@ -40,28 +40,30 @@
4040
}
4141

4242
@case ('vertical') {
43-
@for (step of steps; track step) {
44-
<div class="mat-step">
45-
<ng-container
46-
[ngTemplateOutlet]="stepTemplate"
47-
[ngTemplateOutletContext]="{step}"/>
48-
<div
49-
#animatedContainer
50-
class="mat-vertical-content-container"
51-
[class.mat-stepper-vertical-line]="!$last"
52-
[class.mat-vertical-content-container-active]="selectedIndex === $index"
53-
[attr.inert]="selectedIndex === $index ? null : ''">
54-
<div class="mat-vertical-stepper-content"
55-
role="tabpanel"
56-
[id]="_getStepContentId($index)"
57-
[attr.aria-labelledby]="_getStepLabelId($index)">
58-
<div class="mat-vertical-content">
59-
<ng-container [ngTemplateOutlet]="step.content"/>
43+
<div class="mat-vertical-stepper-wrapper" role="group">
44+
@for (step of steps; track step) {
45+
<div class="mat-step">
46+
<ng-container
47+
[ngTemplateOutlet]="stepTemplate"
48+
[ngTemplateOutletContext]="{step}"/>
49+
<div
50+
#animatedContainer
51+
class="mat-vertical-content-container"
52+
[class.mat-stepper-vertical-line]="!$last"
53+
[class.mat-vertical-content-container-active]="selectedIndex === $index"
54+
[attr.inert]="selectedIndex === $index ? null : ''">
55+
<div class="mat-vertical-stepper-content"
56+
role="region"
57+
[id]="_getStepContentId($index)"
58+
[attr.aria-labelledby]="_getStepLabelId($index)">
59+
<div class="mat-vertical-content">
60+
<ng-container [ngTemplateOutlet]="step.content"/>
61+
</div>
6062
</div>
6163
</div>
6264
</div>
63-
</div>
64-
}
65+
}
66+
</div>
6567
}
6668
}
6769

@@ -74,13 +76,15 @@
7476
(keydown)="_onKeydown($event)"
7577
[tabIndex]="_getFocusIndex() === step.index() ? 0 : -1"
7678
[id]="_getStepLabelId(step.index())"
77-
[attr.aria-posinset]="step.index() + 1"
78-
[attr.aria-setsize]="steps.length"
7979
[attr.aria-controls]="_getStepContentId(step.index())"
80-
[attr.aria-selected]="step.isSelected()"
80+
[attr.aria-expanded]="orientation === 'vertical' ? step.isSelected() : undefined"
81+
[attr.aria-current]="step.isSelected() ? 'step' : undefined"
82+
[attr.aria-pressed]="step.isSelected()"
8183
[attr.aria-label]="step.ariaLabel || null"
8284
[attr.aria-labelledby]="(!step.ariaLabel && step.ariaLabelledby) ? step.ariaLabelledby : null"
8385
[attr.aria-disabled]="step.isNavigable() ? null : true"
86+
[attr.aria-owns]="_getStepContentId(step.index())"
87+
[attr.mat-step-index]="step.index()"
8488
[index]="step.index()"
8589
[state]="step.indicatorType()"
8690
[label]="step.stepLabel || step.label"

src/material/stepper/stepper.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ export class MatStep extends CdkStep implements ErrorStateMatcher, AfterContentI
131131
'[class.mat-stepper-animating]': '_isAnimating()',
132132
'[style.--mat-stepper-animation-duration]': '_getAnimationDuration()',
133133
'[attr.aria-orientation]': 'orientation',
134-
'role': 'tablist',
135134
},
136135
providers: [{provide: CdkStepper, useExisting: MatStepper}],
137136
encapsulation: ViewEncapsulation.None,

0 commit comments

Comments
 (0)