Accessibility for SelectButton

pull/2770/head
Tuğçe Küçükoğlu 2022-07-06 14:57:49 +03:00
parent 519359e2d4
commit 3df8b0eb1f
5 changed files with 52 additions and 33 deletions

View File

@ -46,12 +46,6 @@ const SelectButtonProps = [
type: "string",
default: "null",
description: "A property to uniquely identify an option."
},
{
name: "ariaLabelledBy",
type: "string",
default: "null",
description: "Establishes relationships between the component and label(s) where its value should be one or more element IDs."
}
];

View File

@ -51,10 +51,6 @@ export interface SelectButtonProps {
* A property to uniquely identify an option.
*/
dataKey?: string | undefined;
/**
* Establishes relationships between the component and label(s) where its value should be one or more element IDs.
*/
ariaLabelledBy?: string | undefined;
}
export interface SelectButtonSlots {

View File

@ -1,9 +1,8 @@
<template>
<div :class="containerClass" role="group">
<div v-for="(option, i) of options" :key="getOptionRenderKey(option)" :aria-label="getOptionLabel(option)" role="button" :aria-pressed="isSelected(option)"
@click="onOptionSelect($event, option, i)" @keydown.enter.prevent="onOptionSelect($event, option, i)" @keydown.space.prevent="onOptionSelect($event, option)"
:tabindex="isOptionDisabled(option) ? null : '0'" @focus="onFocus($event)" @blur="onBlur($event)" :aria-labelledby="ariaLabelledBy" v-ripple
:class="getButtonClass(option)">
:class="getButtonClass(option)" :tabindex="isOptionDisabled(option) ? null : '0'" v-ripple
@click="onOptionSelect($event, option)" @keydown="onKeydown($event, option)" @focus="onFocus($event)" @blur="onBlur($event)">
<slot name="option" :option="option" :index="i">
<span class="p-button-label">{{getOptionLabel(option)}}</span>
</slot>
@ -26,8 +25,7 @@ export default {
optionDisabled: null,
multiple: Boolean,
disabled: Boolean,
dataKey: null,
ariaLabelledBy: null
dataKey: null
},
methods: {
getOptionLabel(option) {
@ -58,12 +56,19 @@ export default {
newValue = this.modelValue ? [...this.modelValue, optionValue]: [optionValue];
}
else {
newValue = optionValue;
newValue = selected ? null : optionValue;
}
this.$emit('update:modelValue', newValue);
this.$emit('change', {event: event, value: newValue});
},
onKeydown(event, option) {
//space
if (event.which === 32) {
this.onOptionSelect(event, option);
event.preventDefault();
}
},
isSelected(option) {
let selected = false;
let optionValue = this.getOptionValue(option);

View File

@ -17,7 +17,7 @@
<SelectButton v-model="value2" :options="paymentOptions" optionLabel="name" multiple />
<h5>Custom Content</h5>
<SelectButton v-model="value3" :options="justifyOptions" dataKey="value">
<SelectButton v-model="value3" :options="justifyOptions" optionLabel="value" dataKey="value" >
<template #option="slotProps">
<i :class="slotProps.option.icon"></i>
</template>
@ -45,10 +45,10 @@ export default {
{name: 'Option 3', value: 3}
],
justifyOptions: [
{icon: 'pi pi-align-left', value: 'left'},
{icon: 'pi pi-align-right', value: 'Right'},
{icon: 'pi pi-align-center', value: 'Center'},
{icon: 'pi pi-align-justify', value: 'Justify'}]
{icon: 'pi pi-align-left', value: 'Left', tabindex: 2},
{icon: 'pi pi-align-right', value: 'Right', tabindex: 2},
{icon: 'pi pi-align-center', value: 'Center', tabindex: 3},
{icon: 'pi pi-align-justify', value: 'Justify', tabindex: 4}]
}
},
components: {

View File

@ -117,12 +117,6 @@ export default {
<td>string</td>
<td>null</td>
<td>A property to uniquely identify an option.</td>
</tr>
<tr>
<td>ariaLabelledBy</td>
<td>string</td>
<td>null</td>
<td>Establishes relationships between the component and label(s) where its value should be one or more element IDs.</td>
</tr>
</tbody>
</table>
@ -178,6 +172,36 @@ export default {
</table>
</div>
<h5>Accessibility</h5>
<DevelopmentSection>
<h6>Screen Reader</h6>
<p>The container element that wraps the buttons has a <i>group</i> role whereas each button element uses <i>button</i> role and <i>aria-pressed</i> is updated depending on selection state.
Value to describe an option is automatically set using the <i>aria-label</i> property that refers to the label of an option so it is still suggested to define a label even the option display
consists of presentational content like icons only.</p>
<h6>Keyboard Support</h6>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Key</th>
<th>Function</th>
</tr>
</thead>
<tbody>
<tr>
<td><i>tab</i></td>
<td>Moves focus to the buttons.</td>
</tr>
<tr>
<td><i>space</i></td>
<td>Toggles the checked state of a button.</td>
</tr>
</tbody>
</table>
</div>
</DevelopmentSection>
<h5>Dependencies</h5>
<p>None.</p>
</AppDoc>
@ -200,7 +224,7 @@ export default {
<SelectButton v-model="value2" :options="paymentOptions" optionLabel="name" multiple />
<h5>Custom Content</h5>
<SelectButton v-model="value3" :options="justifyOptions" dataKey="value">
<SelectButton v-model="value3" :options="justifyOptions" optionLabel="value" dataKey="value">
<template #option="slotProps">
<i :class="slotProps.option.icon"></i>
</template>
@ -222,7 +246,7 @@ export default {
{name: 'Option 3', value: 3}
],
justifyOptions: [
{icon: 'pi pi-align-left', value: 'left'},
{icon: 'pi pi-align-left', value: 'Left'},
{icon: 'pi pi-align-right', value: 'Right'},
{icon: 'pi pi-align-center', value: 'Center'},
{icon: 'pi pi-align-justify', value: 'Justify'}]
@ -244,7 +268,7 @@ export default {
<SelectButton v-model="value2" :options="paymentOptions" optionLabel="name" multiple />
<h5>Custom Content</h5>
<SelectButton v-model="value3" :options="justifyOptions" dataKey="value">
<SelectButton v-model="value3" :options="justifyOptions" optionLabel="value" dataKey="value">
<template #option="slotProps">
<i :class="slotProps.option.icon"></i>
</template>
@ -267,7 +291,7 @@ export default {
{name: 'Option 3', value: 3}
]);
const justifyOptions = ref([
{icon: 'pi pi-align-left', value: 'left'},
{icon: 'pi pi-align-left', value: 'Left'},
{icon: 'pi pi-align-right', value: 'Right'},
{icon: 'pi pi-align-center', value: 'Center'},
{icon: 'pi pi-align-justify', value: 'Justify'}
@ -290,7 +314,7 @@ export default {
<p-selectbutton v-model="value2" :options="paymentOptions" option-label="name" multiple></p-selectbutton>
<h5>Custom Content</h5>
<p-selectbutton v-model="value3" :options="justifyOptions" data-key="value">
<p-selectbutton v-model="value3" :options="justifyOptions" option-label="value" data-key="value">
<template #option="slotProps">
<i :class="slotProps.option.icon"></i>
</template>
@ -312,7 +336,7 @@ export default {
{name: 'Option 3', value: 3}
]);
const justifyOptions = ref([
{icon: 'pi pi-align-left', value: 'left'},
{icon: 'pi pi-align-left', value: 'Left'},
{icon: 'pi pi-align-right', value: 'Right'},
{icon: 'pi pi-align-center', value: 'Center'},
{icon: 'pi pi-align-justify', value: 'Justify'}