Create radio button that works properly with screen reader

Reviewed with Max and Adam for implementation.
This commit is contained in:
bmauger 2021-11-15 09:57:59 -05:00
parent 6cb0bdee23
commit f0ebf8ca3b
6 changed files with 124 additions and 1 deletions

View file

@ -45,6 +45,31 @@
/> />
</div> </div>
</div> </div>
<div class="row">
<!-- The role="radiogroup" and aria-labelledby must be included in the parent component for the radio group -->
<div role="radiogroup" aria-labelledby="select-year-radio-group" class="col my-3 d-flex align-items-center flex-column">
<!-- The h3 and id must be included. The id must match the aria-labelledby of the parent div. -->
<h3 class="visually-hidden" id="select-year-radio-group">Select Vehicle Year</h3>
<radioList
groupName="demo"
ariaLabelBy="vehicle-year"
radioID="2021"
errorMessage="Test error message"
/>
<radioList
groupName="demo"
ariaLabelBy="vehicle-year"
radioID="2020"
errorMessage="Test error message"
/>
<radioList
groupName="demo"
ariaLabelBy="vehicle-year"
radioID="2019"
errorMessage="Test error message"
/>
</div>
</div>
<div class="row"> <div class="row">
<div class="col my-3 d-flex align-items-center"> <div class="col my-3 d-flex align-items-center">
<a href="#">Text Link</a> <a href="#">Text Link</a>
@ -95,13 +120,15 @@ import buttonPrimary from "@/uxComponents/buttonPrimary/buttonPrimary";
import buttonSecondary from "@/uxComponents/buttonSecondary/buttonSecondary"; import buttonSecondary from "@/uxComponents/buttonSecondary/buttonSecondary";
import radioCard from "@/uxComponents/radioCard/radioCard"; import radioCard from "@/uxComponents/radioCard/radioCard";
import listButton from "@/uxComponents/listButton/listButton"; import listButton from "@/uxComponents/listButton/listButton";
import radioList from "@/uxComponents/radioList/radioList";
export default { export default {
name: "App", name: "App",
components: { components: {
buttonPrimary, buttonPrimary,
buttonSecondary, buttonSecondary,
radioCard, radioCard,
listButton listButton,
radioList
}, },
}; };
</script> </script>

View file

@ -0,0 +1,59 @@
.radiogroup {
&.radio-list-button {
input[type="radio"] {
opacity: 0;
position: fixed;
width: 0;
&:focus-visible + label {
box-shadow: 0 0 0 2px $blue;
}
&:focus + label {
box-shadow: 0 0 0 2px $blue;
}
&:checked + label {
background: $blue-100;
box-shadow: 0 0 0 1px $blue;
}
}
label {
position: relative;
background: $white;
height: 3rem;
transition: all 150ms linear;
border-radius: $border-radius-lg;
border: 1px solid $gray-500;
width: 100%;
&:hover {
box-shadow: 0 0 0 4px $blue-100;
cursor: pointer;
}
+ p {
display: none;
}
&.error {
border: 1px solid $danger;
+ p {
display: flex;
color: $danger;
}
}
&.button-loader {
padding: 0 40px 0 12px;
&:after {
content: url(../../assets/img/icons/button-spinner-blue.svg);
position: absolute;
right: 14px;
width: 16px;
height: 16px;
margin-left: 12px;
animation: rotation 1s infinite linear;
@keyframes rotation {
100% {
transform:rotate(360deg);
}
}
}
}
}
}
}

View file

@ -0,0 +1 @@
test.todo('some test to be written in the future');

View file

@ -0,0 +1,34 @@
<template>
<div class="radiogroup radio-list-button d-flex flex-column w-100">
<input type="radio" v-bind:id="radioID" v-bind:name="groupName" v-bind:value="radioID">
<label role="radio" tabindex="0" aria-checked="false" v-bind:for="radioID" class="mb-2 d-flex align-items-center p-2"
v-on:click="showLoader()"
v-bind:class="[this.isLoading ? 'button-loader' : 'not-loading',this.isError ? 'error' : '']"
>{{radioID}}</label>
<p class="small">{{errorMessage}}</p>
</div>
</template>
<script>
export default {
name: "radioList",
props: [
"groupName",
"ariaLabelBy",
"radioID",
"errorMessage"
],
data() {
return {
isLoading: false,
isError: false
};
},
methods: {
showLoader() {
this.isLoading = true;
},
},
};
</script>

View file

@ -24,6 +24,7 @@ module.exports = {
@import "./node_modules/bootstrap/scss/bootstrap"; @import "./node_modules/bootstrap/scss/bootstrap";
@import "@/styles/commonStyles.scss"; @import "@/styles/commonStyles.scss";
@import "@/styles/commonButtonStyles.scss"; @import "@/styles/commonButtonStyles.scss";
@import "@/styles/commonRadioStyles.scss";
@import "@/styles/commonTypographyStyles.scss"; @import "@/styles/commonTypographyStyles.scss";
@import "@/styles/commonComponentStyles/ymmsCommonStyles.scss"; @import "@/styles/commonComponentStyles/ymmsCommonStyles.scss";
` `

View file

@ -14,6 +14,7 @@ module.exports = {
@import "./node_modules/bootstrap/scss/bootstrap"; @import "./node_modules/bootstrap/scss/bootstrap";
@import "@/styles/commonStyles.scss"; @import "@/styles/commonStyles.scss";
@import "@/styles/commonButtonStyles.scss"; @import "@/styles/commonButtonStyles.scss";
@import "@/styles/commonRadioStyles.scss";
@import "@/styles/commonTypographyStyles.scss"; @import "@/styles/commonTypographyStyles.scss";
@import "@/styles/commonComponentStyles/ymmsCommonStyles.scss"; @import "@/styles/commonComponentStyles/ymmsCommonStyles.scss";
` `