Skip to content
This repository has been archived by the owner on Mar 27, 2023. It is now read-only.

Commit

Permalink
fix: alerts in wizzard are read immediately when not urgent
Browse files Browse the repository at this point in the history
Signed-off-by: Bozhidar Dryanovski <bozhidar.dryanovski@gmail.com>
  • Loading branch information
bdryanovski committed Aug 13, 2019
1 parent bf8430a commit d241772
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 12 deletions.
4 changes: 4 additions & 0 deletions golden/clr-angular.d.ts
Expand Up @@ -91,6 +91,7 @@ export declare class ClrAlert {
readonly alertClass: string;
alertIconShape: string;
alertType: string;
assertive: boolean;
cdr: ChangeDetectorRef;
closable: boolean;
clrCloseButtonAriaLabel: string;
Expand All @@ -100,6 +101,9 @@ export declare class ClrAlert {
readonly isHidden: boolean;
isSmall: boolean;
multiAlertService: MultiAlertService;
off: boolean;
polite: boolean;
readonly setAriaLive: string;
constructor(iconService: AlertIconAndTypesService, cdr: ChangeDetectorRef, multiAlertService: MultiAlertService, commonStrings: ClrCommonStringsService);
close(): void;
open(): void;
Expand Down
2 changes: 1 addition & 1 deletion src/clr-angular/emphasis/alert/alert.html
Expand Up @@ -11,7 +11,7 @@
[class.alert-hidden]="isHidden"
[class.alert-sm]="isSmall"
[class.alert-app-level]="isAppLevel"
role="alert">
[attr.aria-live]="setAriaLive">
<div class="alert-items">
<ng-content></ng-content>
</div>
Expand Down
52 changes: 43 additions & 9 deletions src/clr-angular/emphasis/alert/alert.spec.ts
Expand Up @@ -19,7 +19,11 @@ const CLOSE_ARIA_LABEL = 'Close Test Alert';
[clrAlertClosable]="isClosable"
[(clrAlertClosed)]="closed"
[clrAlertAppLevel]="isAppLevel"
[clrCloseButtonAriaLabel]="closeAriaLabel">
[clrCloseButtonAriaLabel]="closeAriaLabel"
[clrOff]="clrOff"
[clrAssertive]="clrAssertive"
[clrPolite]="clrPolite"
>
<div class="alert-item">
<span class="alert-text">
{{alertMsg}}
Expand All @@ -39,6 +43,11 @@ class TestComponent {
isAppLevel: boolean = false;
closeAriaLabel: string = CLOSE_ARIA_LABEL;

// AriaLive
clrOff: boolean = false;
clrAssertive: boolean = false;
clrPolite: boolean = false;

alertMsg: string = 'This is an alert!';
}

Expand Down Expand Up @@ -121,21 +130,46 @@ export default function(): void {
expect(compiled.querySelector('.alert')).toBeNull();
});

it('Has an ARIA role of alert', () => {
const myAlert: HTMLElement = compiled.querySelector('.alert');
expect(myAlert.getAttribute('role')).toBe('alert');
});

it('should be able to set close button text', () => {
fixture.componentInstance.isClosable = true;
fixture.detectChanges();
expect(compiled.querySelector('.close').getAttribute('aria-label')).toBe(CLOSE_ARIA_LABEL);
});

it('should not have an aria-live when using role alert', () => {
// https://www.w3.org/TR/wai-aria-1.1/#alert
it("should have an aria-live value of polite when you don't apply any attribute", () => {
const myAlert: HTMLElement = compiled.querySelector('.alert');
expect(myAlert.getAttribute('aria-live')).toBe('polite');
});

it('should have an aria-live value of off when apply clrOff', () => {
const myAlert: HTMLElement = compiled.querySelector('.alert');
fixture.componentInstance.clrOff = true;
fixture.detectChanges();
expect(myAlert.getAttribute('aria-live')).toBe('off');
});

it('should have an aria-live value of assertive when apply clrAssertive', () => {
const myAlert: HTMLElement = compiled.querySelector('.alert');
fixture.componentInstance.clrAssertive = true;
fixture.detectChanges();
expect(myAlert.getAttribute('aria-live')).toBe('assertive');
});

it('should follow the aria-live priority when all of them are set', () => {
const myAlert: HTMLElement = compiled.querySelector('.alert');
expect(myAlert.getAttribute('aria-live')).toBe(null);
fixture.componentInstance.clrAssertive = true;
fixture.componentInstance.clrPolite = true;
fixture.componentInstance.clrOff = true;
fixture.detectChanges();
expect(myAlert.getAttribute('aria-live')).toBe('assertive');
});

it('should set clrPolite and clrOff - clrOff will be used', () => {
const myAlert: HTMLElement = compiled.querySelector('.alert');
fixture.componentInstance.clrPolite = true;
fixture.componentInstance.clrOff = true;
fixture.detectChanges();
expect(myAlert.getAttribute('aria-live')).toBe('off');
});

it('shows and hides the alert based on the clrAlertClosed input', () => {
Expand Down
28 changes: 28 additions & 0 deletions src/clr-angular/emphasis/alert/alert.ts
Expand Up @@ -8,6 +8,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, Optional, Output } f
// providers
import { AlertIconAndTypesService } from './providers/icon-and-types.service';
import { MultiAlertService } from './providers/multi-alert.service';
import { isBooleanAttributeSet } from '../../utils/component/is-boolean-attribute-set';
import { ClrCommonStringsService } from '../../utils/i18n/common-strings.service';

@Component({
Expand Down Expand Up @@ -42,6 +43,33 @@ export class ClrAlert {
return this.iconService.alertType;
}

/**
* clrPolite is not used in the code. Is here just to provide
* code complition and also mark component what type AriaLive
* will be used.
*/
@Input('clrPolite') polite: boolean = true;
@Input('clrAssertive') assertive: boolean;
@Input('clrOff') off: boolean;
/**
* There is an order on how the attributes will take effect.
* Assertive, Off, Polite.
*
* Polite is default if non is passed.
*
* In the case of setting all of them to true. Assertive will be used.
*
*/
get setAriaLive(): string {
if (isBooleanAttributeSet(this.assertive)) {
return 'assertive';
}
if (isBooleanAttributeSet(this.off)) {
return 'off';
}
return 'polite';
}

@Input('clrAlertIcon')
set alertIconShape(value: string) {
this.iconService.alertIconShape = value;
Expand Down
3 changes: 1 addition & 2 deletions src/dev/src/app/wizard/wizard-async-validation.demo.html
@@ -1,5 +1,5 @@
<!--
~ Copyright (c) 2016-2018 VMware, Inc. All Rights Reserved.
~ Copyright (c) 2016-2019 VMware, Inc. All Rights Reserved.
~ This software is released under MIT license.
~ The full license information can be found in LICENSE in the root directory of this project.
-->
Expand All @@ -17,7 +17,6 @@
<clr-wizard-page clrWizardPagePreventDefault="true" (clrWizardPageOnCommit)="onCommit()" (clrWizardPageOnCancel)="doCancel()">
<ng-template clrPageTitle>Form with async validation</ng-template>
<!-- mandatory -->

<div class="spinner" *ngIf="loadingFlag">
Loading...
</div>
Expand Down
33 changes: 33 additions & 0 deletions src/website/src/app/documentation/demos/alert/alerts.demo.html
Expand Up @@ -556,6 +556,39 @@ <h3 id="summary-of-options">Summary of Options</h3>
<td class="left">If true, renders an app-level alert.</td>
</tr>

<tr>
<td class="left">
<b>[clrPolite]</b>
<div class="hidden-sm-up">Type: Boolean</div>
<div class="hidden-sm-up">Default: true</div>
</td>
<td class="left hidden-xs-down">true, false</td>
<td class="hidden-xs-down">true</td>
<td class="left">aria-live will be set to "polite"</td>
</tr>

<tr>
<td class="left">
<b>[clrAssertive]</b>
<div class="hidden-sm-up">Type: Boolean</div>
<div class="hidden-sm-up">Default: false</div>
</td>
<td class="left hidden-xs-down">true, false</td>
<td class="hidden-xs-down">false</td>
<td class="left">aria-live will be set to "assertive"</td>
</tr>

<tr>
<td class="left">
<b>[clrOff]</b>
<div class="hidden-sm-up">Type: Boolean</div>
<div class="hidden-sm-up">Default: false</div>
</td>
<td class="left hidden-xs-down">true, false</td>
<td class="hidden-xs-down">false</td>
<td class="left">aria-live will be set to "off"</td>
</tr>

<tr>
<td class="left">
<b>[clrCloseButtonAriaLabel]</b>
Expand Down

0 comments on commit d241772

Please sign in to comment.