I need to create a switch element in the header of an internal application that lets you switch between two user roles. The rest of the content is rendered based on the selected role — e.g. there are different navigation items and actions available for Role A and for Role B. It is also important to note that changing the role makes the page reload.
So far I wasn't able to find an accessible solution using only an input (checkbox/radio) or a button, so I combined both ideas into following (please ignore the styling of the button, it's only for demo purposes):
var button = document.querySelector('button');
var inputRoleA = document.getElementById("role-A");
var inputRoleB = document.getElementById("role-B");
button.addEventListener('click', function(event) {
if (inputRoleA.checked) {
inputRoleA.checked = false;
inputRoleB.checked = true;
button.innerText = 'Role B';
button.classList.remove('selected-role-A');
button.classList.add('selected-role-B');
// AJAX call to server and page reload
} else {
inputRoleA.checked = true;
inputRoleB.checked = false;
button.innerText = 'Role A';
button.classList.add('selected-role-A');
button.classList.remove('selected-role-B');
// AJAX call to server and page reload
}
});
fieldset {
border: none;
}
.sr-only {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
input:focus ~ button {
outline: 2px solid blue;
}
button {
width: 120px;
padding: 4px 2px;
background: #4a6a9e;
border: 1px solid white;
border-radius: 16px;
color: white;
font-size: 18px;
cursor: pointer;
}
.selected-role-A {
text-align: left;
}
.selected-role-B {
text-align: right;
}
.selected-role-A::before,
.selected-role-B::after {
content: "";
display: inline-block;
width: 22px;
height: 22px;
margin: 0 4px;
background: white;
border-radius: 50%;
}
<fieldset>
<legend class="sr-only">Choose role (reloads the page):</legend>
<input class="sr-only" id="role-A" name="roles" type="radio" value="Role A" checked>
<label class="sr-only" for="role-1">Role A</label>
<input class="sr-only" id="role-B" name="roles" type="radio" value="Role B">
<label class="sr-only" for="role-B">Role B</label>
<button tabindex="-1" aria-hidden="true" class="switch selected-role-A">
Role A
</button>
</fieldset>
So basically I show a fieldset with the two options as radio inputs for screen-reader users and a switch-alike button in the browser.
Regarding the page reload — WCAG technique G13 requires to inform the user what will happen if a change on a form element leads to change of the context (like a reload in our case). Unfortunately, I can't put a visual information around the button because of design requirements, so I only added it in the fieldset for screen-readers. However, as far I understand it, this shouldn't be a problem if the page is a intranet application and the users are going to be trained (like in our case).
Are there any other accessibility problems with my solution? Does anyone know how to achieve this without using two separate elements? Thanks in advance.
EDIT: Solved tabbing problem.