Create radio button that works properly with screen reader
Reviewed with Max and Adam for implementation.
This commit is contained in:
parent
6cb0bdee23
commit
f0ebf8ca3b
6 changed files with 124 additions and 1 deletions
|
|
@ -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>
|
||||||
|
|
|
||||||
59
src/styles/commonRadioStyles.scss
Normal file
59
src/styles/commonRadioStyles.scss
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/uxComponents/radioList/radioList.spec.js
Normal file
1
src/uxComponents/radioList/radioList.spec.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
test.todo('some test to be written in the future');
|
||||||
34
src/uxComponents/radioList/radioList.vue
Normal file
34
src/uxComponents/radioList/radioList.vue
Normal 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>
|
||||||
|
|
@ -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";
|
||||||
`
|
`
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
`
|
`
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue