running-tools

A collection of tools for runners and their coaches
git clone https://git.ashermorgan.net/running-tools/
Log | Files | Refs | README

commit c5be4968fa9ae8d6317ffeecce1bcca29518a9b2
parent 632974cc3a691b9823bbb35641bd5e4e5dcdc163
Author: ashermorgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Thu, 28 Dec 2023 17:05:18 -0800

Improve accessibility

Diffstat:
Msrc/App.vue | 2+-
Msrc/components/TargetEditor.vue | 23++++++++++++-----------
Msrc/components/TargetSetSelector.vue | 11++++++-----
Msrc/components/TimeInput.vue | 14+++++++++++---
Msrc/views/AboutPage.vue | 6+++---
Msrc/views/PaceCalculator.vue | 6+++---
Msrc/views/RaceCalculator.vue | 10+++++-----
Msrc/views/SplitCalculator.vue | 3++-
Msrc/views/UnitCalculator.vue | 14+++++++-------
9 files changed, 50 insertions(+), 39 deletions(-)

diff --git a/src/App.vue b/src/App.vue @@ -7,7 +7,7 @@ import VueFeather from 'vue-feather'; <header> <router-link :to="{ name: $route.meta.back }" v-if="$route.meta.back" class="icon" title="Back"> - <vue-feather type="chevron-left"/> + <vue-feather type="chevron-left" aria-hidden="true"/> </router-link> <h1 v-if="$route.meta.title"> diff --git a/src/components/TargetEditor.vue b/src/components/TargetEditor.vue @@ -4,16 +4,17 @@ <tr> <th> Edit - <input v-model="internalValue.name" placeholder="Target set label"/> - <button class="icon" :title="isCustomSet ? 'Delete Target Set' : 'Revert Target Set'" + <input v-model="internalValue.name" placeholder="Target set label" + aria-label="Target set label"/> + <button class="icon" :title="isCustomSet ? 'Delete target set' : 'Revert target set'" @click="revert"> - <vue-feather :type="isCustomSet ? 'trash-2' : 'rotate-ccw'"/> + <vue-feather :type="isCustomSet ? 'trash-2' : 'rotate-ccw'" aria-hidden="true"/> </button> </th> <th> <button class="icon" title="Close" @click="close"> - <vue-feather type="x"/> + <vue-feather type="x" aria-hidden="true"/> </button> </th> </tr> @@ -22,9 +23,9 @@ <tbody> <tr v-for="(item, index) in internalValue.targets" :key="index"> <td v-if="item.result === 'time'"> - <decimal-input v-model="item.distanceValue" aria-label="Distance Value" + <decimal-input v-model="item.distanceValue" aria-label="Target distance value" :min="0" :digits="2"/> - <select v-model="item.distanceUnit" aria-label="Distance Unit"> + <select v-model="item.distanceUnit" aria-label="Target distance unit"> <option v-for="(value, key) in distanceUnits" :key="key" :value="key"> {{ value.name }} </option> @@ -32,12 +33,12 @@ </td> <td v-else> - <time-input v-model="item.time" aria-label="Time"/> + <time-input v-model="item.time" label="Target duration"/> </td> <td> - <button class="icon" title="Remove Target" @click="removeTarget(index)"> - <vue-feather type="trash-2"/> + <button class="icon" title="Remove target" @click="removeTarget(index)"> + <vue-feather type="trash-2" aria-hidden="true"/> </button> </td> </tr> @@ -52,10 +53,10 @@ <tfoot> <tr> <td colspan="2"> - <button title="Add Distance Target" @click="addDistanceTarget"> + <button title="Add distance target" @click="addDistanceTarget"> Add distance target </button> - <button v-if="timeTargets" title="Add Time Target" @click="addTimeTarget"> + <button v-if="timeTargets" title="Add time target" @click="addTimeTarget"> Add time target </button> <br/> diff --git a/src/components/TargetSetSelector.vue b/src/components/TargetSetSelector.vue @@ -1,19 +1,19 @@ <template> <span class="target-set-selector"> - <select v-model="internalValue"> + <select v-model="internalValue" aria-label="Selected target set"> <option v-for="(item, index) in targetSets" :key="index" :value="index"> {{ item.name }} </option> <option value="_new">[ Create New Target Set ]</option> </select> - <button class="icon" title="Edit Target Set" @click="$refs.dialog.showModal()"> - <vue-feather type="edit"/> + <button class="icon" title="Edit target set" @click="$refs.dialog.showModal()"> + <vue-feather type="edit" aria-hidden="true"/> </button> - <dialog ref="dialog" class="target-set-editor-dialog"> + <dialog ref="dialog" class="target-set-editor-dialog" aria-label="Edit target set"> <target-editor @close="$refs.dialog.close()" v-model="targetSets[internalValue]" - @revert="revertTargetSet(); $refs.dialog.close()" + @revert="revertTargetSet" :isCustomSet="!internalValue.startsWith('_')"/> </dialog> </span> @@ -128,6 +128,7 @@ export default { // Remove custom set delete this.targetSets[this.internalValue]; this.internalValue = [...Object.keys(this.targetSets), '_new'][0]; + if (this.$refs.dialog.close) this.$refs.dialog.close(); } }, }, diff --git a/src/components/TimeInput.vue b/src/components/TimeInput.vue @@ -1,14 +1,14 @@ <template> <div class="time-input"> - <integer-input class="hours" aria-label="hours" v-if="showHours" + <integer-input class="hours" :aria-label="label + ' hours'" v-if="showHours" :min="0" :max="99" :padding="1" v-model="hours" :arrow-keys="false" @keydown="onkeydown($event, 3600)"/> <span v-if="showHours">:</span> - <integer-input class="minutes" aria-label="minutes" + <integer-input class="minutes" :aria-label="label + ' minutes'" :min="0" :max="59" :padding="2" v-model="minutes" :arrow-keys="false" @keydown="onkeydown($event, 60)"/> <span>:</span> - <decimal-input class="seconds" aria-label="seconds" + <decimal-input class="seconds" :aria-label="label + ' seconds'" :min="0" :max="59.99" :padding="2" :digits="2" v-model="seconds" :arrow-keys="false" @keydown="onkeydown($event, 1)"/> </div> @@ -45,6 +45,14 @@ export default { type: Boolean, default: true, }, + + /** + * The prefix for each field's aria-label + */ + label: { + type: String, + default: '', + }, }, data() { diff --git a/src/views/AboutPage.vue b/src/views/AboutPage.vue @@ -10,10 +10,10 @@ <p> Running Tools can be installed as a progressive web app so it works offline: <ul> - <li>On iOS devices, open Running Tools in Safari, press <vue-feather type="share"/>, and - select Add to Home Screen</li> + <li>On iOS devices, open Running Tools in Safari, press <span aria-label="Share"> + <vue-feather type="share" aria-hidden="true"/></span>, and select Add to Home Screen</li> <li>On all other platforms, open Running Tools in Chrome and click Install - <img src="@/assets/chrome-install.png" height="24" class="chrome-install" alt="Install"/> + <img src="@/assets/chrome-install.png" height="24" class="chrome-install" alt=""/> </li> </ul> </p> diff --git a/src/views/PaceCalculator.vue b/src/views/PaceCalculator.vue @@ -4,9 +4,9 @@ <div class="input"> <div> Distance: - <decimal-input v-model="inputDistance" aria-label="distance value" + <decimal-input v-model="inputDistance" aria-label="Input distance value" :min="0" :digits="2"/> - <select v-model="inputUnit" aria-label="distance unit"> + <select v-model="inputUnit" aria-label="Input distance unit"> <option v-for="(value, key) in distanceUnits" :key="key" :value="key"> {{ value.name }} </option> @@ -14,7 +14,7 @@ </div> <div> Time: - <time-input v-model="inputTime"/> + <time-input v-model="inputTime" label="Input duration"/> </div> </div> diff --git a/src/views/RaceCalculator.vue b/src/views/RaceCalculator.vue @@ -4,8 +4,8 @@ <div class="input"> <div> Distance: - <decimal-input v-model="inputDistance" aria-label="Distance value" :min="0" :digits="2"/> - <select v-model="inputUnit" aria-label="Distance unit"> + <decimal-input v-model="inputDistance" aria-label="Input distance value" :min="0" :digits="2"/> + <select v-model="inputUnit" aria-label="Input distance unit"> <option v-for="(value, key) in distanceUnits" :key="key" :value="key"> {{ value.name }} </option> @@ -13,7 +13,7 @@ </div> <div> Time: - <time-input v-model="inputTime"/> + <time-input v-model="inputTime" label="Input race duration"/> </div> </div> @@ -26,7 +26,7 @@ <div class="advanced-options" v-show="showAdvancedOptions"> <div> Prediction Model: - <select v-model="model" aria-label="Prediction Model"> + <select v-model="model" aria-label="Prediction model"> <option value="AverageModel">Average</option> <option value="PurdyPointsModel">Purdy Points Model</option> <option value="VO2MaxModel">V&#775;O&#8322; Max Model</option> @@ -36,7 +36,7 @@ </div> <div> Riegel Exponent: - <decimal-input v-model="riegelExponent" aria-label="Riegel Exponent" :min="1" :max="1.3" + <decimal-input v-model="riegelExponent" aria-label="Riegel exponent" :min="1" :max="1.3" :digits="2" :step="0.01"/> (default: 1.06) </div> diff --git a/src/views/SplitCalculator.vue b/src/views/SplitCalculator.vue @@ -34,7 +34,8 @@ </td> <td v-if="targetSets[selectedTargetSet]"> - <time-input v-model="targetSets[selectedTargetSet].targets[index].split" :showHours="false"/> + <time-input v-model="targetSets[selectedTargetSet].targets[index].split" + label="Split duration" :showHours="false"/> </td> <td> diff --git a/src/views/UnitCalculator.vue b/src/views/UnitCalculator.vue @@ -1,17 +1,17 @@ <template> <div class="unit-calculator"> - <select class="category" v-model="category"> + <select class="category" v-model="category" aria-label="Selected unit category"> <option value="distance">Distance</option> <option value="time">Time</option> <option value="speed_and_pace">Speed &amp; Pace</option> </select> <time-input v-if="getUnitType(inputUnit) === 'time'" class="input-value" - v-model="inputValue"/> - <decimal-input v-else class="input-value" aria-label="input value" + label="Input time" v-model="inputValue"/> + <decimal-input v-else class="input-value" aria-label="Input value" v-model="inputValue" :min="0" :digits="2"/> - <select v-model="inputUnit" class="input-units" aria-label="input units"> + <select v-model="inputUnit" class="input-units" aria-label="Input units"> <option v-for="(value, key) in units" :key="key" :value="key"> {{ value.name }} </option> @@ -19,14 +19,14 @@ <span class="equals"> = </span> - <span v-if="getUnitType(outputUnit) === 'time'" class="output-value"> + <span v-if="getUnitType(outputUnit) === 'time'" class="output-value" aria-label="Output value"> {{ formatDuration(outputValue, 6, 3, true) }} </span> - <span v-else class="output-value"> + <span v-else class="output-value" aria-label="Output value"> {{ formatNumber(outputValue, 0, 3, true) }} </span> - <select v-model="outputUnit" class="output-units" aria-label="output units"> + <select v-model="outputUnit" class="output-units" aria-label="Output units"> <option v-for="(value, key) in units" :key="key" :value="key"> {{ value.name }} </option>