diff --git a/packages/notification/src/vaadin-notification.d.ts b/packages/notification/src/vaadin-notification.d.ts
index 88c6c29fbf..3ebc31fb9e 100644
--- a/packages/notification/src/vaadin-notification.d.ts
+++ b/packages/notification/src/vaadin-notification.d.ts
@@ -40,6 +40,7 @@ export interface NotificationCustomEventMap {
export interface NotificationEventMap extends HTMLElementEventMap, NotificationCustomEventMap {}
export interface ShowOptions {
+ assertive?: boolean;
duration?: number;
position?: NotificationPosition;
theme?: string;
@@ -116,6 +117,7 @@ declare class Notification extends OverlayClassMixin(ThemePropertyMixin(ElementM
*
* ```
* {
+ * assertive?: boolean
* position?: string
* duration?: number
* theme?: string
@@ -123,6 +125,7 @@ declare class Notification extends OverlayClassMixin(ThemePropertyMixin(ElementM
* ```
*
* See the individual documentation for:
+ * - [`assertive`](#/elements/vaadin-notification#property-assertive)
* - [`position`](#/elements/vaadin-notification#property-position)
* - [`duration`](#/elements/vaadin-notification#property-duration)
*
@@ -131,6 +134,13 @@ declare class Notification extends OverlayClassMixin(ThemePropertyMixin(ElementM
*/
static show(contents: TemplateResult | string, options?: ShowOptions): Notification;
+ /**
+ * When true, the notification card has `aria-live` attribute set to
+ * `assertive` instead of `polite`. This makes screen readers announce
+ * the notification content immediately when it appears.
+ */
+ assertive: boolean;
+
/**
* The duration in milliseconds to show the notification.
* Set to `0` or a negative number to disable the notification auto-closing.
diff --git a/packages/notification/src/vaadin-notification.js b/packages/notification/src/vaadin-notification.js
index 852164ea59..5db86c1343 100644
--- a/packages/notification/src/vaadin-notification.js
+++ b/packages/notification/src/vaadin-notification.js
@@ -208,7 +208,6 @@ class NotificationCard extends ThemableMixin(PolymerElement) {
ready() {
super.ready();
this.setAttribute('role', 'alert');
- this.setAttribute('aria-live', 'polite');
}
}
@@ -273,7 +272,10 @@ class Notification extends OverlayClassMixin(ThemePropertyMixin(ElementMixin(Pol
display: none !important;
}
-
+
`;
}
@@ -283,6 +285,16 @@ class Notification extends OverlayClassMixin(ThemePropertyMixin(ElementMixin(Pol
static get properties() {
return {
+ /**
+ * When true, the notification card has `aria-live` attribute set to
+ * `assertive` instead of `polite`. This makes screen readers announce
+ * the notification content immediately when it appears.
+ */
+ assertive: {
+ type: Boolean,
+ value: false,
+ },
+
/**
* The duration in milliseconds to show the notification.
* Set to `0` or a negative number to disable the notification auto-closing.
@@ -340,6 +352,7 @@ class Notification extends OverlayClassMixin(ThemePropertyMixin(ElementMixin(Pol
*
* ```
* {
+ * assertive?: boolean
* position?: string
* duration?: number
* theme?: string
@@ -347,6 +360,7 @@ class Notification extends OverlayClassMixin(ThemePropertyMixin(ElementMixin(Pol
* ```
*
* See the individual documentation for:
+ * - [`assertive`](#/elements/vaadin-notification#property-assertive)
* - [`position`](#/elements/vaadin-notification#property-position)
* - [`duration`](#/elements/vaadin-notification#property-duration)
*
@@ -373,6 +387,9 @@ class Notification extends OverlayClassMixin(ThemePropertyMixin(ElementMixin(Pol
if (options && options.position) {
notification.position = options.position;
}
+ if (options && options.assertive) {
+ notification.assertive = options.assertive;
+ }
if (options && options.theme) {
notification.setAttribute('theme', options.theme);
}
@@ -436,6 +453,11 @@ class Notification extends OverlayClassMixin(ThemePropertyMixin(ElementMixin(Pol
this.renderer(this._card, this);
}
+ /** @private */
+ __computeAriaLive(assertive) {
+ return assertive ? 'assertive' : 'polite';
+ }
+
/** @private */
_rendererChanged(renderer, opened, card) {
if (!card) {
diff --git a/packages/notification/test/dom/__snapshots__/notification.test.snap.js b/packages/notification/test/dom/__snapshots__/notification.test.snap.js
index 5643e71d5a..2477558526 100644
--- a/packages/notification/test/dom/__snapshots__/notification.test.snap.js
+++ b/packages/notification/test/dom/__snapshots__/notification.test.snap.js
@@ -36,3 +36,14 @@ snapshots["vaadin-notification card class"] =
`;
/* end snapshot vaadin-notification card class */
+snapshots["vaadin-notification assertive"] =
+`
+ content
+
+`;
+/* end snapshot vaadin-notification assertive */
+
diff --git a/packages/notification/test/dom/notification.test.js b/packages/notification/test/dom/notification.test.js
index b5c80e43ac..f267d6b0fe 100644
--- a/packages/notification/test/dom/notification.test.js
+++ b/packages/notification/test/dom/notification.test.js
@@ -29,4 +29,9 @@ describe('vaadin-notification', () => {
notification.overlayClass = 'custom';
await expect(card).dom.to.equalSnapshot();
});
+
+ it('assertive', async () => {
+ notification.assertive = true;
+ await expect(card).dom.to.equalSnapshot();
+ });
});
diff --git a/packages/notification/test/notification.test.js b/packages/notification/test/notification.test.js
index 10193fe45a..5208f7ada2 100644
--- a/packages/notification/test/notification.test.js
+++ b/packages/notification/test/notification.test.js
@@ -173,6 +173,18 @@ describe('vaadin-notification', () => {
it('notification card should have `aria-live="polite"`', () => {
expect(notification._card.getAttribute('aria-live')).to.be.equal('polite');
});
+
+ it('should update `aria-live` to "assertive" when assertive is set to true', () => {
+ notification.assertive = true;
+ expect(notification._card.getAttribute('aria-live')).to.be.equal('assertive');
+ });
+
+ it('should update `aria-live` to "polite" when assertive is set to false', () => {
+ notification.assertive = true;
+
+ notification.assertive = false;
+ expect(notification._card.getAttribute('aria-live')).to.be.equal('polite');
+ });
});
describe('methods', () => {
diff --git a/packages/notification/test/statichelper.test.js b/packages/notification/test/statichelper.test.js
index 4b8bd63697..8da8e4938b 100644
--- a/packages/notification/test/statichelper.test.js
+++ b/packages/notification/test/statichelper.test.js
@@ -35,6 +35,11 @@ describe('static helpers', () => {
expect(notification.position).to.equal('top-center');
});
+ it('show should use assertive property when set to true', () => {
+ const notification = Notification.show('Hello world', { assertive: true });
+ expect(notification.assertive).to.be.true;
+ });
+
it('show should set the given theme attribute', () => {
const notification = Notification.show('Hello world', { theme: 'error' });
expect(notification.getAttribute('theme')).to.equal('error');
diff --git a/packages/notification/test/typings/notification.types.ts b/packages/notification/test/typings/notification.types.ts
index c3875b45e7..4f9295026c 100644
--- a/packages/notification/test/typings/notification.types.ts
+++ b/packages/notification/test/typings/notification.types.ts
@@ -20,6 +20,7 @@ assertType(notification);
assertType(notification);
// Properties
+assertType(notification.assertive);
assertType(notification.duration);
assertType(notification.opened);
assertType(notification.position);
@@ -36,7 +37,7 @@ notification.addEventListener('closed', (event) => {
assertType(event);
});
-Notification.show('Hello world', { position: 'middle', duration: 7000, theme: 'error' });
+Notification.show('Hello world', { assertive: true, position: 'middle', duration: 7000, theme: 'error' });
const renderer: NotificationRenderer = (root, owner) => {
assertType(root);