Kaynağa Gözat

add accessibility for slider and fixbug for unittest

maran 7 yıl önce
ebeveyn
işleme
0a597a949e

+ 1 - 0
examples/docs/zh-CN/slider.md

@@ -237,6 +237,7 @@
 | range | 是否为范围选择 | boolean | — | false |
 | vertical | 是否竖向模式 | boolean | — | false |
 | height | Slider 高度,竖向模式时必填 | String | — | — |
+| label | label for screen reader | String | — | — |
 | debounce | 输入时的去抖延迟,毫秒,仅在`show-input`等于true时有效 | number | — | 300 |
 
 ### Events

+ 22 - 3
packages/slider/src/button.vue

@@ -6,7 +6,15 @@
     @mousedown="onButtonDown"
     :class="{ 'hover': hovering, 'dragging': dragging }"
     :style="wrapperStyle"
-    ref="button">
+    ref="button"
+    tabindex="0"
+    @focus="handleMouseEnter"
+    @blur="handleMouseLeave"
+    @keydown.left="onLeftKeyDown"
+    @keydown.right="onRightKeyDown"
+    @keydown.down.prevent="onLeftKeyDown"
+    @keydown.up.prevent="onRightKeyDown"
+  >
     <el-tooltip placement="top" ref="tooltip" :disabled="!showTooltip">
       <span slot="content">{{ formatValue }}</span>
       <div class="el-slider__button" :class="{ 'hover': hovering, 'dragging': dragging }"></div>
@@ -125,7 +133,16 @@
         window.addEventListener('mouseup', this.onDragEnd);
         window.addEventListener('contextmenu', this.onDragEnd);
       },
-
+      onLeftKeyDown() {
+        if (this.disabled) return;
+        this.newPosition = parseFloat(this.currentPosition) - this.step / (this.max - this.min) * 100;
+        this.setPosition(this.newPosition);
+      },
+      onRightKeyDown() {
+        if (this.disabled) return;
+        this.newPosition = parseFloat(this.currentPosition) + this.step / (this.max - this.min) * 100;
+        this.setPosition(this.newPosition);
+      },
       onDragStart(event) {
         this.dragging = true;
         this.isClick = true;
@@ -187,7 +204,9 @@
         let value = steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min;
         value = parseFloat(value.toFixed(this.precision));
         this.$emit('input', value);
-        this.$refs.tooltip && this.$refs.tooltip.updatePopper();
+        this.$nextTick(() => {
+          this.$refs.tooltip && this.$refs.tooltip.updatePopper();
+        });
         if (!this.dragging && this.value !== this.oldValue) {
           this.oldValue = this.value;
         }

+ 18 - 1
packages/slider/src/main.vue

@@ -1,6 +1,12 @@
 <template>
   <div class="el-slider"
-    :class="{ 'is-vertical': vertical, 'el-slider--with-input': showInput }">
+    :class="{ 'is-vertical': vertical, 'el-slider--with-input': showInput }"
+     role="slider"
+     :aria-valuemin="min"
+     :aria-valuemax="max"
+     :aria-orientation="vertical ? 'vertical': 'horizontal'"
+     :aria-disabled="disabled"
+  >
     <el-input-number
       v-model="firstValue"
       v-if="showInput && !range"
@@ -107,6 +113,9 @@
       debounce: {
         type: Number,
         default: 300
+      },
+      label: {
+        type: String
       }
     },
 
@@ -317,6 +326,7 @@
     },
 
     mounted() {
+      let valuetext;
       if (this.range) {
         if (Array.isArray(this.value)) {
           this.firstValue = Math.max(this.min, this.value[0]);
@@ -326,6 +336,7 @@
           this.secondValue = this.max;
         }
         this.oldValue = [this.firstValue, this.secondValue];
+        valuetext = `${this.firstValue}-${this.secondValue}`;
       } else {
         if (typeof this.value !== 'number' || isNaN(this.value)) {
           this.firstValue = this.min;
@@ -333,7 +344,13 @@
           this.firstValue = Math.min(this.max, Math.max(this.min, this.value));
         }
         this.oldValue = this.firstValue;
+        valuetext = this.firstValue;
       }
+      this.$el.setAttribute('aria-valuetext', valuetext);
+
+      // label screen reader
+      this.$el.setAttribute('aria-label', this.label ? this.label : `slider between ${this.min} and ${this.max}`);
+
       this.resetSize();
       window.addEventListener('resize', this.resetSize);
     },

+ 2 - 4
test/unit/specs/cascader.spec.js

@@ -1,4 +1,4 @@
-import { createVue, destroyVM, triggerEvent } from '../util';
+import { createVue, destroyVM, triggerEvent, triggerClick } from '../util';
 
 describe('Cascader', () => {
   let vm;
@@ -355,7 +355,6 @@ describe('Cascader', () => {
     vm.$el.click();
     setTimeout(_ => {
       expect(document.body.querySelector('.el-cascader-menus')).to.be.exist;
-
       const menu = vm.$refs.cascader.menu;
       const menuElm = menu.$el;
       const item1 = menuElm.children[1].querySelector('.el-cascader-menu__item');
@@ -366,8 +365,7 @@ describe('Cascader', () => {
       expect(item1.classList.contains('is-active')).to.be.true;
       expect(item2.classList.contains('is-active')).to.be.true;
       expect(item3.classList.contains('is-active')).to.be.true;
-
-      document.body.click();
+      triggerClick(document, 'mouseup');
       setTimeout(_ => {
         expect(document.body.querySelector('.el-cascader-menus').style.display).to.be.equal('none');
         done();

+ 1 - 0
test/unit/util.js

@@ -19,6 +19,7 @@ const createElm = function() {
  * @param  {Object} vm
  */
 exports.destroyVM = function(vm) {
+  vm.$destroy && vm.$destroy();
   vm.$el &&
   vm.$el.parentNode &&
   vm.$el.parentNode.removeChild(vm.$el);