Accessibility dropdown menu - accessibility

I have the following menu and I am not be able to access the options because when I navigate through them, it immediately goes to the first link, as if I am selecting it. How can I access with the tab key the next options? I want to select the option with enter, so that it goes to the link.
<select role="menu" name="select-rates-jump-to-page-1" class="select js-jump-to-page">
<option role="menuitem" value="" selected="">Select a product</option>
<option role="menuitem" value="http://www.google.com">Rice</option>
<option role="menuitem" value="http://yahoo.com">Chicken</option>
<option role="menuitem" value="htpp://www.bing.com">Salad</option>
</select>

A <select> menu is not really used for selecting a list of links. It's main purpose is to select an option that will be given to the sever after a form submission.
If you want a dropdown menu of links that will navigate to a page, I suggest the patterned defined in Inclusive Components for an accessible drop down menu of links.
var navButton = document.querySelector('nav button');
navButton.addEventListener('click', function() {
let expanded = this.getAttribute('aria-expanded') === 'true' || false;
this.setAttribute('aria-expanded', !expanded);
let menu = this.nextElementSibling;
menu.hidden = !menu.hidden;
});
nav ul {
list-style: none;
padding: 1em;
box-shadow: 0 2px 6px 0 hsla(0, 0%, 0%, 0.2);
border-radius: 4px;
margin: 0;
max-width: 10em;
}
<nav id="navigation">
<button aria-expanded="false" aria-controls="menu-list">Select a product</button>
<ul id="menu-list" hidden>
<li>Rice</li>
<li>Chicken</li>
<li>Salad</li>
</ul>
</nav>

Related

mat-nav-list: routerLinkActive class applied after click

I have a mat-nav-list in my application that displays the menu on the left. I have added routerLinkActive="selected-item" to it to highlight the currently selected menu item.
Whenever a menu item is clicked, the class is not applied. It gets applied only after I click somewhere else in the page.
Below is the snippet of my code:
<mat-nav-list (click)="menuItemClicked()" class="menu-list">
<a *ngFor="let menuItem of menuItems" mat-list-item
[routerLink]="menuItem.routerLink" routerLinkActive="selected-item">
<mat-icon [svgIcon]="menuItem.icon" matListIcon></mat-icon>
<span>{{ menuItem.label }}</span>
</a>
</mat-nav-list>
.selected-item {
border-top-left-radius: 7px;
border-bottom-left-radius: 7px;
background-color: #f47431;
}
Here's a Stackblitz which reproduces the issue: https://stackblitz.com/edit/angular-wuabhz?file=src/app/list-single-selection-example.html
Select one of the boot items and click somewhere else and you'll see the class selected-item gets applied.
Is there a way to overcome this issue or am I missing something?
#prerak-sola
I noticed the same.
The reason for this is that the item still have ':focus' until you click somewhere else.
You could
1. use the same color on the 'item-active' as mat-list-item:focus
(if you don't have a need for a darker shade or different color)
.active-link {
background-color: rgba(0,0,0,0.1);
}
.mat-nav-list .mat-list-item:focus{
/* default bg color */
background-color: rgba(0,0,0,0.87);
/* ovrride bg color to match your item-active*/
background-color: rgba(0,0,0,0.1);
}
<!-- list item is '<a mat-list-item>' -->
'a mat-list-item'
<mat-nav-list>
<a mat-list-item *ngFor="let link of links" [routerLink]="link.path" routerLinkActive="active-link">{{ link.name }}</a>
</mat-nav-list>
2. Or probably better wrap your list-item in a <mat-list-item>
note that the 'routerLinkActive' is placed in the <mat-list-item>
this will override the 'background-color' from .mat-list-item:focus
<!-- list item is '<mat-list-item>' -->
'a mat-list-item'
<mat-nav-list>
<mat-list-item *ngFor="let link of links" routerLinkActive="active-link">
<a matLine [routerLink]="link.path" style="width: 100%;">{{ link.name }}</a>
<button mat-icon-button>
<mat-icon>info</mat-icon>
</button>
</mat-list-item>
</mat-nav-list>
.active-link {
background-color: rgba(0,0,0,0.1);
}
// .mat-nav-list .mat-list-item:focus{
// background-color: rgba(0,0,0,0.1);
// }

Pure CSS Checkbox button with no label (jQuery is a possible solution)

I'm trying to replace a checkbox and make it into a button. I've done this before, but for this site I'm using Easy Digital Downloads Front End Submissions. I've searched and searched, also gone through multiple posts here on the site.
I don't know how this was made, but I can't seem to wrap my head around it as the label seems to come before the class. It has this selectit class I've been trying to mess around with, but whatever I do I can't make a button.
When I try something like input[type=checkbox] + label it doesn't actually affect anything.
Other examples would be .selectit input[type=checkbox]:before This one works.
As well as .selectit input:checked:after
But again, I can't add anything with + label it seems.
Well I can make one that has a hover, but not one with a checked state and a color change for example.
I should note that I cannot change any HTML. The way the checkbox is built, I have to stick with, so I'm trying to make a pure CSS solution. But I can add jquery into the page
Here's the HTML for the checkboxes. I only really want the parent checkbox to be affected by the hover and checked state.
<ul class="fes-category-checklist">
<li id="download_category-156" data-open="false" style="display: list-item;"><label class="selectit"><input value="156" type="checkbox" name="download_category[]" id="in-download_category-156"> 2D Assets</label>
<ul class="children">
<li id="download_category-183" data-open="false"><label class="selectit"><input value="183" type="checkbox" name="download_category[]" id="in-download_category-183"> Motion Graphics</label></li>
<li id="download_category-163" data-open="false"><label class="selectit"><input value="163" type="checkbox" name="download_category[]" id="in-download_category-163"> HDRI</label></li>
<li id="download_category-162" data-open="false"><label class="selectit"><input value="162" type="checkbox" name="download_category[]" id="in-download_category-162"> Materials</label></li>
<li id="download_category-161" data-open="false"><label class="selectit"><input value="161" type="checkbox" name="download_category[]" id="in-download_category-161"> Textures</label></li>
</ul>
</li>
</ul>
I hope someone has some answers
Thanks!
EDIT
I was advised to update my question, because I can insert jquery into the page. Although, this is not something I have much experience with myself.
Original, no javascript, crazy answer
Your problem is that you can't select a parent of an element, and so you can't say "if this box is checked, make its parent label change color." Sadly, the :has CSS selector isn't supported by anything, or that could save you.
However. If you're insane, and you hate it when things look nice, you can do some crazy stuff with outlines and margins. This is mucho janky but it sort of works. Kinda.
You can play around with it in this codepen: https://codepen.io/anon/pen/WPQJgw
Follow-up, non-crazy, uses jQuery answer
Okay your edit says you can use javascript or jQuery. Let's assume you already have jQuery loaded on the page, since that makes for short code.
Codepen here: https://codepen.io/tobyinternet/pen/daYqJq
I'll explain what's up here.
You can't change the HTML, but (with javascript) you CAN assign classes to elements. So first, we create classes that modify the existing elements.
Strip bullets off list items
Hide the actual checkboxes
Make the labels into block elements and give them colors and hover states
Create a style to indicate when a "button" is "checked"
Then we use javascript to first apply button styles on page load, then apply appropriate checked/unchecked style when an element is clicked.
The purpose of doing it this way is that if a user can't (or doesn't want to) use javascript, they just see checkboxes. Still totally usable, good for accessibility. If they do have javascript installed, then ta-da! Buttons.
$(document).ready(function(){
$('.fes-category-checklist, .fes-category-checklist .children').addClass('nolist');
$('.selectit').addClass('checkbutton');
$('.checkbutton').click(function(){
if( $(this).children('input:checkbox').is(':checked') ) {
$(this).addClass('ischecked');
} else {
$(this).removeClass('ischecked');
}
});
});
.nolist {
list-style: none;
}
.nolist li {
margin: 20px 0;
}
.checkbutton {
padding: 8px 20px;
text-align: center;
display: block;
width: 140px;
height: 30px;
line-height: 30px;
margin-right: -130px;
border: 1px solid black;
border-radius: 6px;
background-color: yellow;
transition: all .2s;
box-shadow: 0px 3px 8px rgba(50,50,50,.5);
}
.checkbutton:hover {
background-color: #CCCC00;
}
.checkbutton:active {
box-shadow: 0px 1px 2px rgba(50,50,50,.5);
}
.checkbutton input[type="checkbox"] {
position: absolute;
left: -99999px;
}
.ischecked {
background-color: blue;
color: white;
}
.ischecked:hover {
background-color: lightblue;
color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="fes-category-checklist">
<li id="download_category-156" data-open="false" style="display: list-item;"><label class="selectit"><input value="156" type="checkbox" name="download_category[]" id="in-download_category-156"> 2D Assets</label>
<ul class="children">
<li id="download_category-183" data-open="false"><label class="selectit"><input value="183" type="checkbox" name="download_category[]" id="in-download_category-183"> Motion Graphics</label></li>
<li id="download_category-163" data-open="false"><label class="selectit"><input value="163" type="checkbox" name="download_category[]" id="in-download_category-163"> HDRI</label></li>
<li id="download_category-162" data-open="false"><label class="selectit"><input value="162" type="checkbox" name="download_category[]" id="in-download_category-162"> Materials</label></li>
<li id="download_category-161" data-open="false"><label class="selectit"><input value="161" type="checkbox" name="download_category[]" id="in-download_category-161"> Textures</label></li>
</ul>
</li>
</ul>

Aria-live doesn't say label after updates

I have this piece of HTML which is updated dynamically with JS. The screen reader only reads out the new value when they get updated. It doesn't say the label of the input who was updated.
<ul class="points-transfer-detail-points-calculation clearfix">
<li>
<label for="points-to-transfer">{{{ pointsToTransferLabel }}}</label>
<input id="points-to-transfer" type="text" aria-controls="brand-points points-left-after-transfer" placeholder="XXX,XXX" {{#if disabled }}disabled{{/if}}>
<p id="points-to-transfer-error" class="points-transfer-detail-form-error" aria-hidden="true" role="alert">{{{ pointsToTransferErrorMessage }}}</p>
</li>
<li>
<label for="brand-points">{{{ brandPointsLabel }}}</label>
<input id="brand-points" type="text" aria-live="polite" aria-atomic="true" disabled>
</li>
<li>
<label for="points-left-after-transfer">{{{ pointsLeftLabel }}}</label>
<input id="points-left-after-transfer" type="text" aria-live="polite" aria-atomic="true" disabled>
</li>
</ul>
I have tried to use aria-labelledby, aria-describedby, role="alert" and aria-label but no results, only the value of the input and never his label.
From all my research on Google and StackOverflow, I didn't manage to found a proper answer.
I'm using NVDA in Firefox as a screen reader.
Thank you for your help.
The only time a label should be read by a screen-reader is when focus is placed on its corresponding field.
Your input fields are all disabled. Therefore the labels wouldn't be read since you can't focus into the fields.
Remove your aria-live and aria-atomic from your input fields. They are unusable on input fields. Aria-live is triggered on DOM change within the container it's assigned to. An input field is not a container. Also, labels shouldn't be announced that way anyway.
If you want to announce a change to the DOM I would suggest injecting content into an empty aria-live div at the bottom of your page and hide it accessibly.
Here is a working example with one static label and 3 dynamic labels. One uses the "disabled" attribute, and one uses aria-disabled so that it can still receive focus. An announcement about the rendering of the new labels is also featured using an accessibly-hidden aria-live container.
This has been tested in NVDA in FF, JAWS in IE, and VO in Safari.
(function () {
function populateLabels () {
document.querySelector('[for="dogsName"]').appendChild(document.createTextNode('Dog\'s Name'));
document.querySelector('[for="catsName"]').appendChild(document.createTextNode('Cat\'s Name'));
document.querySelector('[for="lastName"]').appendChild(document.createTextNode('Last Name'));
}
function announceChange () {
var announcement = "Some new labels have appeared. They are Last Name, Dog's Name, and Cat's Name.",
ariaLiveContainer = document.querySelector('[aria-live]');
ariaLiveContainer.appendChild(document.createTextNode(announcement));
setTimeout(function () {
ariaLiveContainer.innerHTML("");
}, 2000);
}
setTimeout(function () {
populateLabels();
announceChange();
}, 3000);
}());
input {
border: 1px solid black;
}
[disabled],
[aria-disabled="true"] {
border: 1px solid #ccc;
background-color: #eee;
}
.acc-hidden { /* Hide only visually, but have it available for screenreaders */
position: absolute !important;
display: block;
visibility: visible;
overflow: hidden;
width: 1px;
height: 1px;
margin: -1px;
border: 0;
padding: 0;
clip: rect(0 0 0 0);
}
<p>The first label is there on DOM load. The other three labels come in 3 seconds after DOM load. An announcement is made about the updated labels.</p>
<form action="">
<ul>
<li>
<label for="firstName">First Name</label>
<input type="text" name="first-name" id="firstName" />
</li>
<li>
<label for="lastName"></label>
<input type="text" name="last-name" id="lastName" />
</li>
<li>
<label for="dogsName"></label>
<input type="text" name="dogs-name" id="dogsName" disabled /> (uses the disabled attribute -- doesn't receive focus)
</li>
<li>
<label for="catsName"></label>
<input type="text" name="cats-name" id="catsName" aria-disabled="true" /> (uses the aria-disabled="true" attribute -- can receive focus)
</li>
</ul>
</form>
<div class="acc-hidden" aria-live="polite"></div>

CSS navigation using "input:checked" doesn't fire inner link href when using secondary labels to uncheck original input

I have created a nice CSS menu for the app I'm working on, which is activated by using a checkbox and sibling selector.
Problem: clicking on a link doesn't close the menu (it's a single page app, so no page reloads)
Attempted solution: tried to create labels inside or around the menu links, with a "for" attribute pointing to the original menu button. This closes the menu on each link click (unchecks the checkbox), but then the link open doesn't fire.
<label for="btn">menu btn</label>
<input id="btn" type="checkbox"/>
<ul>
<li>
<a href="http://google.com/" target="_blank">
<label for="btn">link 1</label>
</a>
</li>
<li>
<a href="http://google.com/" target="_blank">
<label for="btn">link 2</label>
</a>
</li>
</ul>
<style>
/* important styles */
ul {
opacity: 0;
}
#btn:checked + ul {
opacity: 1;
}
</style>
Fiddle here:
http://jsfiddle.net/gebi/4nzLa9yh/
Any ideas?
I hope this will help, if you open link in same tab.
Menu Btn
<ul id="ul">
<li>
link 1
</li>
<li>
link 2
</li>
</ul>
<style>
ul {
display: none;
}
#ul:target {
display: block;
}
</style>

MVC DropDownList Arrow style with css

In my razor file, I am building a form.
The form controls need to reflect the modelType of the razor page I have declared, in this case, "Case" is the name of the model.
I have a Html helper DropDownList on the page for a property of case called PSCStatusID with this line:
#Html.DropDownListFor(s => s.PSCStatusID, (SelectList)ViewBag.PSCStatusList, "<--Select One-->", new { #class = "form-control" })
This works perfectly for me with of course the validation kicking in from my POCO attributes.
Notice I am sprinkling in Bootstrap css styles. Actually the creative dept. handed off the HTML to me and I am trying to get it exact.
But their version of my one liner HTML helper above is the following:
<div class="input-group">
#Html.TextBoxFor(c => c.PSCStatusID, null, new { #class = "form-control" })
<div class="input-group-btn">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-nrsa-psc dropdown-menu-right" role="menu">
#foreach (PSCStatus item in ViewBag.PSCStatusList)
{
<li>
<a href="#" onclick="document.getElementById('PSCStatusID').value = this.text;">
#item.StatusCode - #item.StatusTextDesc
</a>
</li>
}
</ul>
</div>
</div>
So I know this is a common way these days for HTML people to display a custom dropdown and make that give that button mimicking the DropDown Arrow some bootstrap classes like class="btn btn-primary".
But this is really messing me up.
It doesn't work well with MVC.
If I now name the textbox which mimicks the dropdown selectedText PSCStatusID, it contains the actual text and not the id.
The list items aren't like select options with both text and a value.
I would have to jump through a lot of hoops to make this work.
All I really need to do is change that drop down arrow from the default to my own button looking drop down.
I've come across a lot of css like:
select::ms-expand {display: none;}
That would make the arrow disappear in IE.
And something like this:
select:after {
content: "▼"; /* Current arrow I would like to change */
position: absolute;
top: 0;
right: 0;
bottom: 0;
font-size: 60%;
line-height: 30px;
padding: 0 7px;
background: #000;
color: black;
}
That shows an arrow but not in the select box.
I just can't quite get it.
Does anyone have any suggestions on how to do this?
Here is what I have currently
Notice my validation working out-of-the-box:)
But this is what I need to get:
If any MVC/CSS gurus out there have an idea how to make this happen in my one liner HTML Helper verison of the drop down rather then the custom way please let me know.
Actually this is the code they handed off to me. The version I have above is where I swapped out some MVC controls for HTML:
<div class="form-group">
<label for="nrsa-psc" class="col-sm-4 control-label">*NRSA PSC Status</label>
<div class="col-sm-8">
<div class="input-group">
<input type="text" class="form-control" id="nrsa-psc">
<div class="input-group-btn">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-nrsa-psc dropdown-menu-right" role="menu">
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
<li>Option 4</li>
</ul>
</div><!-- /btn-group -->
</div>
</div>
</div>
So got a little closer:
I added the selectpicker class to the dropdown:
#Html.DropDownListFor(s => s.PSCStatusID, (SelectList)ViewBag.PSCStatusList, "<--Select One-->", new { #class = "form-control selectpicker" })
Then brought bootstrap select picker css and js from github.
Then added:
.form-control.bootstrap-select.input-validation-error > button { border: 1px solid #f00; background-color: #fee; }
after:
.input-validation-error { border: 1px solid #f00; background-color: #fee; }
to get MVC validation working with the bootstrap select version of the drop down.
And added:
span.caret{color: blue;}
By the way: why is it so hard to get lines to show up as code on this site.
I hit four space all day long and it still shows up as regular text. They should make this easier - very annoying when trying to be a good citizen and post an answer.

Categories

Resources