mirror of
https://gitee.com/ElemeFE/element.git
synced 2024-12-03 20:58:09 +08:00
RadioGroup:add accessibility
This commit is contained in:
parent
798bb8e75d
commit
7a84a3e44a
@ -6,6 +6,11 @@
|
|||||||
{ 'is-active': value === label },
|
{ 'is-active': value === label },
|
||||||
{ 'is-disabled': isDisabled }
|
{ 'is-disabled': isDisabled }
|
||||||
]"
|
]"
|
||||||
|
role="radio"
|
||||||
|
:aria-checked="value === label"
|
||||||
|
:aria-disabled="isDisabled"
|
||||||
|
:tabindex="tabIndex"
|
||||||
|
@keydown.space.stop.prevent="value = label"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
class="el-radio-button__orig-radio"
|
class="el-radio-button__orig-radio"
|
||||||
@ -13,7 +18,9 @@
|
|||||||
type="radio"
|
type="radio"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
:name="name"
|
:name="name"
|
||||||
:disabled="isDisabled">
|
:disabled="isDisabled"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
<span class="el-radio-button__inner" :style="value === label ? activeStyle : null">
|
<span class="el-radio-button__inner" :style="value === label ? activeStyle : null">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<template v-if="!$slots.default">{{label}}</template>
|
<template v-if="!$slots.default">{{label}}</template>
|
||||||
@ -62,6 +69,9 @@
|
|||||||
},
|
},
|
||||||
isDisabled() {
|
isDisabled() {
|
||||||
return this.disabled || this._radioGroup.disabled;
|
return this.disabled || this._radioGroup.disabled;
|
||||||
|
},
|
||||||
|
tabIndex() {
|
||||||
|
return !this.isDisabled ? (this._radioGroup ? (this.value === this.label ? 0 : -1) : 0) : -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="el-radio-group">
|
<div
|
||||||
|
class="el-radio-group"
|
||||||
|
role="radiogroup"
|
||||||
|
@keydown="handleKeydown"
|
||||||
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import Emitter from 'element-ui/src/mixins/emitter';
|
import Emitter from 'element-ui/src/mixins/emitter';
|
||||||
|
|
||||||
|
const keyCode = Object.freeze({
|
||||||
|
LEFT: 37,
|
||||||
|
UP: 38,
|
||||||
|
RIGHT: 39,
|
||||||
|
DOWN: 40
|
||||||
|
});
|
||||||
export default {
|
export default {
|
||||||
name: 'ElRadioGroup',
|
name: 'ElRadioGroup',
|
||||||
|
|
||||||
@ -20,6 +30,47 @@
|
|||||||
textColor: String,
|
textColor: String,
|
||||||
disabled: Boolean
|
disabled: Boolean
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
// 当radioGroup没有默认选项时,第一个可以选中Tab导航
|
||||||
|
let radios = this.$el.querySelectorAll('[type=radio]');
|
||||||
|
if (![].some.call(radios, radio => radio.checked)) {
|
||||||
|
this.$el.querySelectorAll('[role=radio]')[0].tabIndex = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleKeydown(e) { // 左右上下按键 可以在radio组内切换不同选项
|
||||||
|
const target = e.target;
|
||||||
|
const className = target.nodeName === 'INPUT' ? '[type=radio]' : '[role=radio]';
|
||||||
|
const radios = this.$el.querySelectorAll(className);
|
||||||
|
const length = radios.length;
|
||||||
|
const index = [].indexOf.call(radios, target);
|
||||||
|
const roleRadios = this.$el.querySelectorAll('[role=radio]');
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case keyCode.LEFT:
|
||||||
|
case keyCode.UP:
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
if (index === 0) {
|
||||||
|
roleRadios[length - 1].click();
|
||||||
|
} else {
|
||||||
|
roleRadios[index - 1].click();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case keyCode.RIGHT:
|
||||||
|
case keyCode.DOWN:
|
||||||
|
if (index === (length - 1)) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
roleRadios[0].click();
|
||||||
|
} else {
|
||||||
|
roleRadios[index + 1].click();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(value) {
|
value(value) {
|
||||||
this.$emit('change', value);
|
this.$emit('change', value);
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<label class="el-radio">
|
<label
|
||||||
|
class="el-radio"
|
||||||
|
role="radio"
|
||||||
|
:aria-checked="model === label"
|
||||||
|
:aria-disabled="isDisabled"
|
||||||
|
:tabindex="tabIndex"
|
||||||
|
@keydown.space.stop.prevent="model = label"
|
||||||
|
>
|
||||||
<span class="el-radio__input"
|
<span class="el-radio__input"
|
||||||
:class="{
|
:class="{
|
||||||
'is-disabled': isDisabled,
|
'is-disabled': isDisabled,
|
||||||
@ -16,7 +23,9 @@
|
|||||||
@focus="focus = true"
|
@focus="focus = true"
|
||||||
@blur="focus = false"
|
@blur="focus = false"
|
||||||
:name="name"
|
:name="name"
|
||||||
:disabled="isDisabled">
|
:disabled="isDisabled"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
</span>
|
</span>
|
||||||
<span class="el-radio__label">
|
<span class="el-radio__label">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
@ -46,7 +55,6 @@
|
|||||||
focus: false
|
focus: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
isGroup() {
|
isGroup() {
|
||||||
let parent = this.$parent;
|
let parent = this.$parent;
|
||||||
@ -60,12 +68,10 @@
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
model: {
|
model: {
|
||||||
get() {
|
get() {
|
||||||
return this.isGroup ? this._radioGroup.value : this.value;
|
return this.isGroup ? this._radioGroup.value : this.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
set(val) {
|
set(val) {
|
||||||
if (this.isGroup) {
|
if (this.isGroup) {
|
||||||
this.dispatch('ElRadioGroup', 'input', [val]);
|
this.dispatch('ElRadioGroup', 'input', [val]);
|
||||||
@ -79,6 +85,9 @@
|
|||||||
return this.isGroup
|
return this.isGroup
|
||||||
? this._radioGroup.disabled || this.disabled
|
? this._radioGroup.disabled || this.disabled
|
||||||
: this.disabled;
|
: this.disabled;
|
||||||
|
},
|
||||||
|
tabIndex() {
|
||||||
|
return !this.isDisabled ? (this.isGroup ? (this.model === this.label ? 0 : -1) : 0) : -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -75,6 +75,12 @@
|
|||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
.el-radio-button__inner { /*获得焦点时 样式提醒*/
|
||||||
|
box-shadow: 0 0 1px 1px var(--radio-button-checked-border-color) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
&:last-child {
|
&:last-child {
|
||||||
.el-radio-button__inner {
|
.el-radio-button__inner {
|
||||||
border-radius: 0 var(--border-radius-base) var(--border-radius-base) 0;
|
border-radius: 0 var(--border-radius-base) var(--border-radius-base) 0;
|
||||||
|
@ -11,6 +11,13 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@utils-user-select none;
|
@utils-user-select none;
|
||||||
|
|
||||||
|
&:focus { /*获得焦点时 样式提醒*/
|
||||||
|
outline: none;
|
||||||
|
.el-radio__inner {
|
||||||
|
box-shadow: 0 0 1px 1px var(--radio-input-border-color-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& + .el-radio {
|
& + .el-radio {
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user