Skip to content

Commit

Permalink
fix(a11y): stepper-completed step does not have accessible notificati…
Browse files Browse the repository at this point in the history
…on after completion (vmware-clarity#1334)

Please check if your PR fulfills the following requirements:

- [x] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
- [ ] If applicable, have a visual design approval

What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->

- [x] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] Other... Please describe:

In the Stepper, when the step is complete, keyboard focus moves to the
next step but there's no indication that the previous step is completed
by the screen reader.
<!-- Please describe the current behavior that you are modifying, or
link to a relevant issue. -->

Issue Number: [CDE-699](https://jira.eng.vmware.com/browse/CDE-699)

The screen reader will announce that the current step is complete (or
failed) and move focus to the next step or stay in the same step in case
of an error.

- [ ] Yes
- [x] No

<!-- If this PR contains a breaking change, please describe the impact
and migration path for existing applications below. -->

---------

Co-authored-by: Andrea Fernandes <andreaf1@vmware.com>
(cherry picked from commit 0c02a7a)
  • Loading branch information
andyfeds authored and Andrea Fernandes committed Apr 4, 2024
1 parent 72f44b2 commit 653a739
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 5 deletions.
9 changes: 9 additions & 0 deletions projects/angular/clarity.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@ export class ClrAccordionPanel implements OnInit, OnChanges {
get panelNumber(): number;
panelOpen: boolean;
panelOpenChange: EventEmitter<boolean>;
// (undocumented)
protected stepCompleteText(panelNumber: number): string;
// (undocumented)
protected stepErrorText(panelNumber: number): string;
// (undocumented)
togglePanel(): void;
// (undocumented)
static ɵcmp: i0.ɵɵComponentDeclaration<ClrAccordionPanel, "clr-accordion-panel", never, { "disabled": "clrAccordionPanelDisabled"; "panelOpen": "clrAccordionPanelOpen"; }, { "panelOpenChange": "clrAccordionPanelOpenChange"; }, ["accordionDescription"], ["clr-accordion-title, clr-step-title", "clr-accordion-description, clr-step-description", "*"], false, never>;
Expand Down Expand Up @@ -990,6 +995,10 @@ export interface ClrCommonStrings {
singleSelectionAriaLabel: string;
sortColumn: string;
stackViewChanged: string;
// (undocumented)
stepComplete: string;
// (undocumented)
stepError: string;
success: string;
// (undocumented)
timelineStepCurrent: string;
Expand Down
8 changes: 5 additions & 3 deletions projects/angular/src/accordion/accordion-panel.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
[class.clr-accordion-header-has-description]="(accordionDescription.changes | async)?.length || accordionDescription.length"
#headerButton
>
<span class="clr-sr-only">
<ng-container *ngIf="panel.status === AccordionStatus.Error">{{commonStrings.keys.danger}}</ng-container>
<ng-container *ngIf="panel.status === AccordionStatus.Complete">{{commonStrings.keys.success}}</ng-container>
<span class="clr-sr-only" role="status">
<ng-container *ngIf="panel.status === AccordionStatus.Error"> {{ stepErrorText(panelNumber)}} </ng-container>
<ng-container *ngIf="panel.status === AccordionStatus.Complete">
{{ stepCompleteText(panelNumber)}}
</ng-container>
</span>
<span class="clr-accordion-status">
<cds-icon shape="angle" direction="right" class="clr-accordion-angle"></cds-icon>
Expand Down
8 changes: 8 additions & 0 deletions projects/angular/src/accordion/accordion-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ export class ClrAccordionPanel implements OnInit, OnChanges {
return `clr-accordion-header-${id}`;
}

protected stepCompleteText(panelNumber: number) {
return this.commonStrings.parse(this.commonStrings.keys.stepComplete, { STEP: panelNumber.toString() });
}

protected stepErrorText(panelNumber: number) {
return this.commonStrings.parse(this.commonStrings.keys.stepError, { STEP: panelNumber.toString() });
}

private emitPanelChange(panel: AccordionPanelModel) {
if (panel.index !== this._panelIndex) {
this._panelIndex = panel.index;
Expand Down
4 changes: 2 additions & 2 deletions projects/angular/src/accordion/stepper/stepper-panel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ describe('ClrStep Reactive Forms', () => {
fixture.detectChanges();

const statusMessage = fixture.nativeElement.querySelector('button .clr-sr-only');
expect(statusMessage.innerText.trim()).toBe('Error');
expect(statusMessage.innerText.trim()).toBe('Error in step 1');

mockStep.status = AccordionStatus.Complete;
(stepperService as MockStepperService).step.next(mockStep);
fixture.detectChanges();

expect(statusMessage.innerText.trim()).toBe('Success');
expect(statusMessage.innerText.trim()).toBe(`Step 1 complete`);
});

it('should add aria-disabled attribute to the header button based on the appropriate step state', () => {
Expand Down
4 changes: 4 additions & 0 deletions projects/angular/src/utils/i18n/common-strings.default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,8 @@ export const commonStringsDefault: ClrCommonStrings = {
* Datagrid footer; sr-only text after the number of selected rows.
*/
selectedRows: 'Selected rows',

// Accordion/Stepper
stepComplete: 'Step {STEP} complete',
stepError: 'Error in step {STEP}',
};
4 changes: 4 additions & 0 deletions projects/angular/src/utils/i18n/common-strings.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,4 +282,8 @@ export interface ClrCommonStrings {
* Datagrid footer; sr-only text after the number of selected rows.
*/
selectedRows: string;

//Stepper: Screen-reader text for completed/failed step
stepComplete: string;
stepError: string;
}

0 comments on commit 653a739

Please # to comment.