Explorar el Código

Bug Fix: Utilize `aria-busy` to prevent VoiceOver from reading the SR field (#805).

Naotoshi Fujita hace 3 años
padre
commit
9dfc5b3dc6

+ 19 - 12
dist/js/splide.cjs.js

@@ -1,6 +1,6 @@
 /*!
 /*!
  * Splide.js
  * Splide.js
- * Version  : 4.0.3
+ * Version  : 4.0.4
  * License  : MIT
  * License  : MIT
  * Copyright: 2022 Naotoshi Fujita
  * Copyright: 2022 Naotoshi Fujita
  */
  */
@@ -697,7 +697,8 @@ var ARIA_HIDDEN = ARIA_PREFIX + "hidden";
 var ARIA_ORIENTATION = ARIA_PREFIX + "orientation";
 var ARIA_ORIENTATION = ARIA_PREFIX + "orientation";
 var ARIA_ROLEDESCRIPTION = ARIA_PREFIX + "roledescription";
 var ARIA_ROLEDESCRIPTION = ARIA_PREFIX + "roledescription";
 var ARIA_LIVE = ARIA_PREFIX + "live";
 var ARIA_LIVE = ARIA_PREFIX + "live";
-var ARIA_RELEVANT = ARIA_PREFIX + "relevant";
+var ARIA_BUSY = ARIA_PREFIX + "busy";
+var ARIA_ATOMIC = ARIA_PREFIX + "atomic";
 var ALL_ATTRIBUTES = [ROLE, TAB_INDEX, DISABLED, ARIA_CONTROLS, ARIA_CURRENT, ARIA_LABEL, ARIA_LABELLEDBY, ARIA_HIDDEN, ARIA_ORIENTATION, ARIA_ROLEDESCRIPTION];
 var ALL_ATTRIBUTES = [ROLE, TAB_INDEX, DISABLED, ARIA_CONTROLS, ARIA_CURRENT, ARIA_LABEL, ARIA_LABELLEDBY, ARIA_HIDDEN, ARIA_ORIENTATION, ARIA_ROLEDESCRIPTION];
 var CLASS_ROOT = PROJECT_CODE;
 var CLASS_ROOT = PROJECT_CODE;
 var CLASS_TRACK = PROJECT_CODE + "__track";
 var CLASS_TRACK = PROJECT_CODE + "__track";
@@ -2751,7 +2752,7 @@ function Wheel(Splide2, Components2, options) {
   };
   };
 }
 }
 
 
-var SR_REMOVAL_DELAY = 50;
+var SR_REMOVAL_DELAY = 90;
 
 
 function Live(Splide2, Components2, options) {
 function Live(Splide2, Components2, options) {
   var _EventInterface14 = EventInterface(Splide2),
   var _EventInterface14 = EventInterface(Splide2),
@@ -2760,26 +2761,32 @@ function Live(Splide2, Components2, options) {
   var track = Components2.Elements.track;
   var track = Components2.Elements.track;
   var enabled = options.live && !options.isNavigation;
   var enabled = options.live && !options.isNavigation;
   var sr = create("span", CLASS_SR);
   var sr = create("span", CLASS_SR);
-  var timer;
+  var interval = RequestInterval(SR_REMOVAL_DELAY, apply(toggle, false));
 
 
   function mount() {
   function mount() {
     if (enabled) {
     if (enabled) {
       disable(!Components2.Autoplay.isPaused());
       disable(!Components2.Autoplay.isPaused());
-      setAttribute(track, ARIA_RELEVANT, "additions");
+      setAttribute(track, ARIA_ATOMIC, true);
       sr.textContent = "\u2026";
       sr.textContent = "\u2026";
       on(EVENT_AUTOPLAY_PLAY, apply(disable, true));
       on(EVENT_AUTOPLAY_PLAY, apply(disable, true));
       on(EVENT_AUTOPLAY_PAUSE, apply(disable, false));
       on(EVENT_AUTOPLAY_PAUSE, apply(disable, false));
-      on([EVENT_MOVED, EVENT_SCROLLED], function () {
-        setAttribute(sr, ARIA_HIDDEN, false);
-        append(track, sr);
-        timer && clearTimeout(timer);
-        timer = setTimeout(setAttribute, SR_REMOVAL_DELAY, sr, ARIA_HIDDEN, true);
-      });
+      on([EVENT_MOVED, EVENT_SCROLLED], apply(toggle, true));
+    }
+  }
+
+  function toggle(active) {
+    setAttribute(track, ARIA_BUSY, active);
+
+    if (active) {
+      append(track, sr);
+      interval.start();
+    } else {
+      remove(sr);
     }
     }
   }
   }
 
 
   function destroy() {
   function destroy() {
-    removeAttribute(track, [ARIA_LIVE, ARIA_RELEVANT]);
+    removeAttribute(track, [ARIA_LIVE, ARIA_ATOMIC, ARIA_BUSY]);
     remove(sr);
     remove(sr);
   }
   }
 
 

+ 19 - 12
dist/js/splide.esm.js

@@ -4,7 +4,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
 
 
 /*!
 /*!
  * Splide.js
  * Splide.js
- * Version  : 4.0.3
+ * Version  : 4.0.4
  * License  : MIT
  * License  : MIT
  * Copyright: 2022 Naotoshi Fujita
  * Copyright: 2022 Naotoshi Fujita
  */
  */
@@ -692,7 +692,8 @@ var ARIA_HIDDEN = ARIA_PREFIX + "hidden";
 var ARIA_ORIENTATION = ARIA_PREFIX + "orientation";
 var ARIA_ORIENTATION = ARIA_PREFIX + "orientation";
 var ARIA_ROLEDESCRIPTION = ARIA_PREFIX + "roledescription";
 var ARIA_ROLEDESCRIPTION = ARIA_PREFIX + "roledescription";
 var ARIA_LIVE = ARIA_PREFIX + "live";
 var ARIA_LIVE = ARIA_PREFIX + "live";
-var ARIA_RELEVANT = ARIA_PREFIX + "relevant";
+var ARIA_BUSY = ARIA_PREFIX + "busy";
+var ARIA_ATOMIC = ARIA_PREFIX + "atomic";
 var ALL_ATTRIBUTES = [ROLE, TAB_INDEX, DISABLED, ARIA_CONTROLS, ARIA_CURRENT, ARIA_LABEL, ARIA_LABELLEDBY, ARIA_HIDDEN, ARIA_ORIENTATION, ARIA_ROLEDESCRIPTION];
 var ALL_ATTRIBUTES = [ROLE, TAB_INDEX, DISABLED, ARIA_CONTROLS, ARIA_CURRENT, ARIA_LABEL, ARIA_LABELLEDBY, ARIA_HIDDEN, ARIA_ORIENTATION, ARIA_ROLEDESCRIPTION];
 var CLASS_ROOT = PROJECT_CODE;
 var CLASS_ROOT = PROJECT_CODE;
 var CLASS_TRACK = PROJECT_CODE + "__track";
 var CLASS_TRACK = PROJECT_CODE + "__track";
@@ -2746,7 +2747,7 @@ function Wheel(Splide2, Components2, options) {
   };
   };
 }
 }
 
 
-var SR_REMOVAL_DELAY = 50;
+var SR_REMOVAL_DELAY = 90;
 
 
 function Live(Splide2, Components2, options) {
 function Live(Splide2, Components2, options) {
   var _EventInterface14 = EventInterface(Splide2),
   var _EventInterface14 = EventInterface(Splide2),
@@ -2755,26 +2756,32 @@ function Live(Splide2, Components2, options) {
   var track = Components2.Elements.track;
   var track = Components2.Elements.track;
   var enabled = options.live && !options.isNavigation;
   var enabled = options.live && !options.isNavigation;
   var sr = create("span", CLASS_SR);
   var sr = create("span", CLASS_SR);
-  var timer;
+  var interval = RequestInterval(SR_REMOVAL_DELAY, apply(toggle, false));
 
 
   function mount() {
   function mount() {
     if (enabled) {
     if (enabled) {
       disable(!Components2.Autoplay.isPaused());
       disable(!Components2.Autoplay.isPaused());
-      setAttribute(track, ARIA_RELEVANT, "additions");
+      setAttribute(track, ARIA_ATOMIC, true);
       sr.textContent = "\u2026";
       sr.textContent = "\u2026";
       on(EVENT_AUTOPLAY_PLAY, apply(disable, true));
       on(EVENT_AUTOPLAY_PLAY, apply(disable, true));
       on(EVENT_AUTOPLAY_PAUSE, apply(disable, false));
       on(EVENT_AUTOPLAY_PAUSE, apply(disable, false));
-      on([EVENT_MOVED, EVENT_SCROLLED], function () {
-        setAttribute(sr, ARIA_HIDDEN, false);
-        append(track, sr);
-        timer && clearTimeout(timer);
-        timer = setTimeout(setAttribute, SR_REMOVAL_DELAY, sr, ARIA_HIDDEN, true);
-      });
+      on([EVENT_MOVED, EVENT_SCROLLED], apply(toggle, true));
+    }
+  }
+
+  function toggle(active) {
+    setAttribute(track, ARIA_BUSY, active);
+
+    if (active) {
+      append(track, sr);
+      interval.start();
+    } else {
+      remove(sr);
     }
     }
   }
   }
 
 
   function destroy() {
   function destroy() {
-    removeAttribute(track, [ARIA_LIVE, ARIA_RELEVANT]);
+    removeAttribute(track, [ARIA_LIVE, ARIA_ATOMIC, ARIA_BUSY]);
     remove(sr);
     remove(sr);
   }
   }
 
 

+ 19 - 12
dist/js/splide.js

@@ -4,7 +4,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
 
 
 /*!
 /*!
  * Splide.js
  * Splide.js
- * Version  : 4.0.3
+ * Version  : 4.0.4
  * License  : MIT
  * License  : MIT
  * Copyright: 2022 Naotoshi Fujita
  * Copyright: 2022 Naotoshi Fujita
  */
  */
@@ -692,7 +692,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
   var ARIA_ORIENTATION = ARIA_PREFIX + "orientation";
   var ARIA_ORIENTATION = ARIA_PREFIX + "orientation";
   var ARIA_ROLEDESCRIPTION = ARIA_PREFIX + "roledescription";
   var ARIA_ROLEDESCRIPTION = ARIA_PREFIX + "roledescription";
   var ARIA_LIVE = ARIA_PREFIX + "live";
   var ARIA_LIVE = ARIA_PREFIX + "live";
-  var ARIA_RELEVANT = ARIA_PREFIX + "relevant";
+  var ARIA_BUSY = ARIA_PREFIX + "busy";
+  var ARIA_ATOMIC = ARIA_PREFIX + "atomic";
   var ALL_ATTRIBUTES = [ROLE, TAB_INDEX, DISABLED, ARIA_CONTROLS, ARIA_CURRENT, ARIA_LABEL, ARIA_LABELLEDBY, ARIA_HIDDEN, ARIA_ORIENTATION, ARIA_ROLEDESCRIPTION];
   var ALL_ATTRIBUTES = [ROLE, TAB_INDEX, DISABLED, ARIA_CONTROLS, ARIA_CURRENT, ARIA_LABEL, ARIA_LABELLEDBY, ARIA_HIDDEN, ARIA_ORIENTATION, ARIA_ROLEDESCRIPTION];
   var CLASS_ROOT = PROJECT_CODE;
   var CLASS_ROOT = PROJECT_CODE;
   var CLASS_TRACK = PROJECT_CODE + "__track";
   var CLASS_TRACK = PROJECT_CODE + "__track";
@@ -2744,7 +2745,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     };
     };
   }
   }
 
 
-  var SR_REMOVAL_DELAY = 50;
+  var SR_REMOVAL_DELAY = 90;
 
 
   function Live(Splide2, Components2, options) {
   function Live(Splide2, Components2, options) {
     var _EventInterface14 = EventInterface(Splide2),
     var _EventInterface14 = EventInterface(Splide2),
@@ -2753,26 +2754,32 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     var track = Components2.Elements.track;
     var track = Components2.Elements.track;
     var enabled = options.live && !options.isNavigation;
     var enabled = options.live && !options.isNavigation;
     var sr = create("span", CLASS_SR);
     var sr = create("span", CLASS_SR);
-    var timer;
+    var interval = RequestInterval(SR_REMOVAL_DELAY, apply(toggle, false));
 
 
     function mount() {
     function mount() {
       if (enabled) {
       if (enabled) {
         disable(!Components2.Autoplay.isPaused());
         disable(!Components2.Autoplay.isPaused());
-        setAttribute(track, ARIA_RELEVANT, "additions");
+        setAttribute(track, ARIA_ATOMIC, true);
         sr.textContent = "\u2026";
         sr.textContent = "\u2026";
         on(EVENT_AUTOPLAY_PLAY, apply(disable, true));
         on(EVENT_AUTOPLAY_PLAY, apply(disable, true));
         on(EVENT_AUTOPLAY_PAUSE, apply(disable, false));
         on(EVENT_AUTOPLAY_PAUSE, apply(disable, false));
-        on([EVENT_MOVED, EVENT_SCROLLED], function () {
-          setAttribute(sr, ARIA_HIDDEN, false);
-          append(track, sr);
-          timer && clearTimeout(timer);
-          timer = setTimeout(setAttribute, SR_REMOVAL_DELAY, sr, ARIA_HIDDEN, true);
-        });
+        on([EVENT_MOVED, EVENT_SCROLLED], apply(toggle, true));
+      }
+    }
+
+    function toggle(active) {
+      setAttribute(track, ARIA_BUSY, active);
+
+      if (active) {
+        append(track, sr);
+        interval.start();
+      } else {
+        remove(sr);
       }
       }
     }
     }
 
 
     function destroy() {
     function destroy() {
-      removeAttribute(track, [ARIA_LIVE, ARIA_RELEVANT]);
+      removeAttribute(track, [ARIA_LIVE, ARIA_ATOMIC, ARIA_BUSY]);
       remove(sr);
       remove(sr);
     }
     }
 
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/js/splide.min.js


BIN
dist/js/splide.min.js.gz


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/js/splide.min.js.map


+ 9 - 8
package-lock.json

@@ -1,12 +1,12 @@
 {
 {
   "name": "@splidejs/splide",
   "name": "@splidejs/splide",
-  "version": "4.0.3",
+  "version": "4.0.4",
   "lockfileVersion": 2,
   "lockfileVersion": 2,
   "requires": true,
   "requires": true,
   "packages": {
   "packages": {
     "": {
     "": {
       "name": "@splidejs/splide",
       "name": "@splidejs/splide",
-      "version": "4.0.3",
+      "version": "4.0.4",
       "license": "MIT",
       "license": "MIT",
       "devDependencies": {
       "devDependencies": {
         "@babel/core": "^7.16.10",
         "@babel/core": "^7.16.10",
@@ -14,6 +14,7 @@
         "@rollup/plugin-babel": "^5.3.0",
         "@rollup/plugin-babel": "^5.3.0",
         "@rollup/plugin-node-resolve": "^13.1.3",
         "@rollup/plugin-node-resolve": "^13.1.3",
         "@types/jest": "^27.4.0",
         "@types/jest": "^27.4.0",
+        "@types/node": "^17.0.35",
         "@typescript-eslint/eslint-plugin": "^5.10.0",
         "@typescript-eslint/eslint-plugin": "^5.10.0",
         "@typescript-eslint/parser": "^5.10.0",
         "@typescript-eslint/parser": "^5.10.0",
         "autoprefixer": "^10.4.2",
         "autoprefixer": "^10.4.2",
@@ -2620,9 +2621,9 @@
       "dev": true
       "dev": true
     },
     },
     "node_modules/@types/node": {
     "node_modules/@types/node": {
-      "version": "16.9.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz",
-      "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==",
+      "version": "17.0.35",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz",
+      "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==",
       "dev": true
       "dev": true
     },
     },
     "node_modules/@types/normalize-package-data": {
     "node_modules/@types/normalize-package-data": {
@@ -12915,9 +12916,9 @@
       "dev": true
       "dev": true
     },
     },
     "@types/node": {
     "@types/node": {
-      "version": "16.9.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz",
-      "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==",
+      "version": "17.0.35",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz",
+      "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==",
       "dev": true
       "dev": true
     },
     },
     "@types/normalize-package-data": {
     "@types/normalize-package-data": {

+ 2 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@splidejs/splide",
   "name": "@splidejs/splide",
-  "version": "4.0.3",
+  "version": "4.0.4",
   "description": "Splide is a lightweight, flexible and accessible slider/carousel. No dependencies, no Lighthouse errors.",
   "description": "Splide is a lightweight, flexible and accessible slider/carousel. No dependencies, no Lighthouse errors.",
   "author": "Naotoshi Fujita",
   "author": "Naotoshi Fujita",
   "license": "MIT",
   "license": "MIT",
@@ -34,6 +34,7 @@
     "@rollup/plugin-babel": "^5.3.0",
     "@rollup/plugin-babel": "^5.3.0",
     "@rollup/plugin-node-resolve": "^13.1.3",
     "@rollup/plugin-node-resolve": "^13.1.3",
     "@types/jest": "^27.4.0",
     "@types/jest": "^27.4.0",
+    "@types/node": "^17.0.35",
     "@typescript-eslint/eslint-plugin": "^5.10.0",
     "@typescript-eslint/eslint-plugin": "^5.10.0",
     "@typescript-eslint/parser": "^5.10.0",
     "@typescript-eslint/parser": "^5.10.0",
     "autoprefixer": "^10.4.2",
     "autoprefixer": "^10.4.2",

+ 25 - 15
src/js/components/Live/Live.ts

@@ -1,7 +1,7 @@
-import { ARIA_HIDDEN, ARIA_LIVE, ARIA_RELEVANT } from '../../constants/attributes';
+import { ARIA_ATOMIC, ARIA_BUSY, ARIA_LIVE } from '../../constants/attributes';
 import { CLASS_SR } from '../../constants/classes';
 import { CLASS_SR } from '../../constants/classes';
 import { EVENT_AUTOPLAY_PAUSE, EVENT_AUTOPLAY_PLAY, EVENT_MOVED, EVENT_SCROLLED } from '../../constants/events';
 import { EVENT_AUTOPLAY_PAUSE, EVENT_AUTOPLAY_PLAY, EVENT_MOVED, EVENT_SCROLLED } from '../../constants/events';
-import { EventInterface } from '../../constructors';
+import { EventInterface, RequestInterval } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { Splide } from '../../core/Splide/Splide';
 import { BaseComponent, Components, Options } from '../../types';
 import { BaseComponent, Components, Options } from '../../types';
 import { append, apply, create, remove, removeAttribute, setAttribute } from '../../utils';
 import { append, apply, create, remove, removeAttribute, setAttribute } from '../../utils';
@@ -19,7 +19,7 @@ export interface LiveComponent extends BaseComponent {
 /**
 /**
  * Delay in milliseconds before removing the SR field for Windows Narrator.
  * Delay in milliseconds before removing the SR field for Windows Narrator.
  */
  */
-const SR_REMOVAL_DELAY = 50;
+const SR_REMOVAL_DELAY = 90;
 
 
 /**
 /**
  * The component for implementing Live Region to the slider.
  * The component for implementing Live Region to the slider.
@@ -49,30 +49,40 @@ export function Live( Splide: Splide, Components: Components, options: Options )
   const sr = create( 'span', CLASS_SR );
   const sr = create( 'span', CLASS_SR );
 
 
   /**
   /**
-   * Keeps the timer ID.
+   * Holds the RequestInterval instance.
    */
    */
-  let timer: number;
+  const interval = RequestInterval( SR_REMOVAL_DELAY, apply( toggle, false ) );
 
 
   /**
   /**
    * Called when the component is mounted.
    * Called when the component is mounted.
-   * - The `aria-relevant` attribute is important to prevent NVDA from reading contents twice
-   * - Immediately assigning `aria-hidden` makes Windows Narrator silent, hence requires the delay around 50ms.
+   * - JAWS needs `aria-atomic` to make the `aria-busy` work.
+   * - Immediately removing the SR makes Windows Narrator silent, hence requires the delay around 50ms.
    */
    */
   function mount(): void {
   function mount(): void {
     if ( enabled ) {
     if ( enabled ) {
       disable( ! Components.Autoplay.isPaused() );
       disable( ! Components.Autoplay.isPaused() );
-      setAttribute( track, ARIA_RELEVANT, 'additions' );
+      setAttribute( track, ARIA_ATOMIC, true );
       sr.textContent = '…';
       sr.textContent = '…';
 
 
       on( EVENT_AUTOPLAY_PLAY, apply( disable, true ) );
       on( EVENT_AUTOPLAY_PLAY, apply( disable, true ) );
       on( EVENT_AUTOPLAY_PAUSE, apply( disable, false ) );
       on( EVENT_AUTOPLAY_PAUSE, apply( disable, false ) );
+      on( [ EVENT_MOVED, EVENT_SCROLLED ], apply( toggle, true ) );
+    }
+  }
+
+  /**
+   * Toggles the SR field and `aria-busy`.
+   *
+   * @param active - Determines whether to activate the field or not.
+   */
+  function toggle( active: boolean ): void {
+    setAttribute( track, ARIA_BUSY, active );
 
 
-      on( [ EVENT_MOVED, EVENT_SCROLLED ], () => {
-        setAttribute( sr, ARIA_HIDDEN, false );
-        append( track, sr );
-        timer && clearTimeout( timer );
-        timer = setTimeout( setAttribute, SR_REMOVAL_DELAY, sr, ARIA_HIDDEN, true );
-      } );
+    if ( active ) {
+      append( track, sr );
+      interval.start();
+    } else {
+      remove( sr );
     }
     }
   }
   }
 
 
@@ -80,7 +90,7 @@ export function Live( Splide: Splide, Components: Components, options: Options )
    * Destroys the component.
    * Destroys the component.
    */
    */
   function destroy(): void {
   function destroy(): void {
-    removeAttribute( track, [ ARIA_LIVE, ARIA_RELEVANT ] );
+    removeAttribute( track, [ ARIA_LIVE, ARIA_ATOMIC, ARIA_BUSY ] );
     remove( sr );
     remove( sr );
   }
   }
 
 

+ 22 - 8
src/js/components/Live/test/general.test.ts

@@ -1,22 +1,35 @@
-import { ARIA_RELEVANT, ARIA_LIVE } from '../../../constants/attributes';
+import { ARIA_ATOMIC, ARIA_LIVE, ARIA_BUSY } from '../../../constants/attributes';
 import { CLASS_SR } from '../../../constants/classes';
 import { CLASS_SR } from '../../../constants/classes';
-import { init } from '../../../test';
+import { init, wait } from '../../../test';
 
 
 
 
 describe( 'Live', () => {
 describe( 'Live', () => {
-  test( 'can append a SR text to the track element after move.', () => {
+  test( 'can append a SR text and add aria-busy="true" to the track element after move.', () => {
     const splide = init( { live: true, speed: 0 } );
     const splide = init( { live: true, speed: 0 } );
+    const { track } = splide.Components.Elements;
+
+    splide.go( 1 );
+    expect( track.getElementsByClassName( CLASS_SR ).length ).toBe( 1 );
+    expect( track.getAttribute( ARIA_BUSY ) ).toBe( 'true' );
+  } );
+
+  test( 'can remove a SR text and aria-busy from the track element.', async () => {
+    const splide = init( { live: true, speed: 0 } );
+    const { track } = splide.Components.Elements;
 
 
     splide.go( 1 );
     splide.go( 1 );
-    expect( splide.Components.Elements.track.getElementsByClassName( CLASS_SR ).length ).toBe( 1 );
+
+    await wait( 200 );
+    expect( track.getElementsByClassName( CLASS_SR ).length ).toBe( 0 );
+    expect( track.getAttribute( ARIA_BUSY ) ).toBe( 'false' );
   } );
   } );
 
 
-  test( 'can assign aria-live="polite" and aria-relevant="additions" to the list element.', () => {
+  test( 'can assign aria-live="polite" and aria-atomic="true" to the list element.', () => {
     const splide = init( { live: true } );
     const splide = init( { live: true } );
     const { track } = splide.Components.Elements;
     const { track } = splide.Components.Elements;
 
 
     expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
     expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
-    expect( track.getAttribute( ARIA_RELEVANT ) ).toBe( 'additions' );
+    expect( track.getAttribute( ARIA_ATOMIC ) ).toBe( 'true' );
   } );
   } );
 
 
   test( 'can remove aria attributes on destroy.', () => {
   test( 'can remove aria attributes on destroy.', () => {
@@ -26,7 +39,8 @@ describe( 'Live', () => {
     splide.destroy();
     splide.destroy();
 
 
     expect( track.getAttribute( ARIA_LIVE ) ).toBeNull();
     expect( track.getAttribute( ARIA_LIVE ) ).toBeNull();
-    expect( track.getAttribute( ARIA_RELEVANT ) ).toBeNull();
+    expect( track.getAttribute( ARIA_ATOMIC ) ).toBeNull();
+    expect( track.getAttribute( ARIA_BUSY ) ).toBeNull();
   } );
   } );
 
 
   test( 'should assign aria attribute again on refresh.', () => {
   test( 'should assign aria attribute again on refresh.', () => {
@@ -36,7 +50,7 @@ describe( 'Live', () => {
     splide.refresh();
     splide.refresh();
 
 
     expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
     expect( track.getAttribute( ARIA_LIVE ) ).toBe( 'polite' );
-    expect( track.getAttribute( ARIA_RELEVANT ) ).toBe( 'additions' );
+    expect( track.getAttribute( ARIA_ATOMIC ) ).toBe( 'true' );
   } );
   } );
 
 
   test( 'can assign aria-live="off" to the list element when the autoplay is `true`.', () => {
   test( 'can assign aria-live="off" to the list element when the autoplay is `true`.', () => {

+ 2 - 1
src/js/constants/attributes.ts

@@ -12,7 +12,8 @@ export const ARIA_HIDDEN          = `${ ARIA_PREFIX }hidden`;
 export const ARIA_ORIENTATION     = `${ ARIA_PREFIX }orientation`;
 export const ARIA_ORIENTATION     = `${ ARIA_PREFIX }orientation`;
 export const ARIA_ROLEDESCRIPTION = `${ ARIA_PREFIX }roledescription`;
 export const ARIA_ROLEDESCRIPTION = `${ ARIA_PREFIX }roledescription`;
 export const ARIA_LIVE            = `${ ARIA_PREFIX }live`;
 export const ARIA_LIVE            = `${ ARIA_PREFIX }live`;
-export const ARIA_RELEVANT        = `${ ARIA_PREFIX }relevant`;
+export const ARIA_BUSY            = `${ ARIA_PREFIX }busy`;
+export const ARIA_ATOMIC          = `${ ARIA_PREFIX }atomic`;
 
 
 /**
 /**
  * The array with all attributes to remove later.
  * The array with all attributes to remove later.

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio