Merge pull request #13259 from rak-phillip/task/12817-a11y-switch

Add WAI-ARIA Roles, States, and Properties to ToggleSwitch
This commit is contained in:
Phillip Rak 2025-02-06 07:57:50 -07:00 committed by GitHub
commit 879059c521
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 39 additions and 2 deletions

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent, onMounted, onBeforeUnmount, useTemplateRef } from 'vue';
type StateType = boolean | 'true' | 'false' | undefined; type StateType = boolean | 'true' | 'false' | undefined;
@ -33,6 +33,29 @@ export default defineComponent({
emits: ['update:value'], emits: ['update:value'],
setup() {
const switchChrome = useTemplateRef<HTMLElement>('switchChrome');
const focus = () => {
switchChrome.value?.classList.add('focus');
};
const blur = () => {
switchChrome.value?.classList.remove('focus');
};
const switchInput = useTemplateRef<HTMLInputElement>('switchInput');
onMounted(() => {
switchInput.value?.addEventListener('focus', focus);
switchInput.value?.addEventListener('blur', blur);
});
onBeforeUnmount(() => {
switchInput.value?.removeEventListener('focus', focus);
switchInput.value?.removeEventListener('blur', blur);
});
},
data() { data() {
return { state: false as StateType }; return { state: false as StateType };
}, },
@ -64,11 +87,18 @@ export default defineComponent({
>{{ offLabel }}</span> >{{ offLabel }}</span>
<label class="switch hand"> <label class="switch hand">
<input <input
ref="switchInput"
type="checkbox" type="checkbox"
role="switch"
:checked="state" :checked="state"
:aria-label="onLabel"
@input="toggle(null)" @input="toggle(null)"
@keydown.enter="toggle(null)"
> >
<span class="slider round" /> <span
ref="switchChrome"
class="slider round"
/>
</label> </label>
<span <span
class="label no-select hand" class="label no-select hand"
@ -118,6 +148,13 @@ $toggle-height: 16px;
background-color: var(--checkbox-disabled-bg); background-color: var(--checkbox-disabled-bg);
-webkit-transition: .4s; -webkit-transition: .4s;
transition: .4s; transition: .4s;
&.focus {
@include focus-outline;
outline-offset: 2px;
-webkit-transition: 0s;
transition: 0s;
}
} }
.slider:before { .slider:before {