Semantic way to handle a button group - html

I have a list of audio streams that is hidden or shown depending on whether a user clicks on a a div element with class 'btn-group'. My mark up is similar to twitter bootstrap's button group, like so:
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
Expand
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<!-- dropdown menu links -->
</ul>
</div>
That's fine, but it seems unfortunate that this important bit of functionality is hidden in a div element rather than something more meaningful. Is there an aria-role that would make sense? Is there some other approach folks would recommend?

A decent solution could be to give the aria landmark role for button to the btn-group div like this:
<div class="btn-group" role="button">
That way, screen readers will understand the nature of the group.

Related

How can I fix a toggle switch with a dropdown box in a header?

<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="false">Contacts
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Email</li>
<li><a rel="noopener" href="#" target="_blank">LinkedIn</a></li>
<li><a rel="noopener" href="#">Github</a></li>
<li><a rel="noopener" href="#" target="_blank">Stackoverflow</a></li>
</ul>
</li>
I am having an issue with a dropdown box in my header. I have been looking all over on the bootstrap website and w3schools and I have found stuff but it seems like nothing has worked so I wanted to see if anyone else had this problem and if there was a solution.
What is happening is when I select the dropdown it does not want to toggle. I even made sure to have the toggle class. When I type in it will stay stuck open, so something is wrong with the toggle but I have not been able to find the solution.
one of bootstrap 5 changes is using data-bs-... instead of data-... attributes, so try data-bs-toggle="dropdown" attribute
It is going to look stupid but, please if you have this problem, make sure to include the bootstrap script at the bottom of the body. It will make your life much easier lol.

Should Screen Reader reads "Home, Link, Menu Item" or "Home, Menu Item"

If the menu items are links, should the screen reader read it as "home, link, menu item" or "home, menu item"?
Currently the screen reader is reading it as "home, link, menu item" but I am getting mixed information about it. Some information says it should be "home, link, menu item" because we want users to know the button is a link. However, some say that it should just be announced as "home, menu item"
Here's my code:
<ul role="menu">
<li role="menuitem">
<a aria-label="Home" href="/en-us/">
<span class="">Home</span>
</a>
</li>
<li role="menuitem">
<a aria-label="Search" href="/en-us/">
<span class="">Search</span>
</a>
</li>
</ul>
I was wondering which version is correct?
If your html is correct, then don't worry about how the screen reader announces it. JAWS, NVDA, VoiceOver, Talkback, Narrator, ChromeVox, etc may all announce it slightly different and that's ok. As long as the code is correct, then you're good.
As a side note, if you use the menu roles, then you are committing to implementing arrow key navigation. That is, think of the menu role as an old school desktop app menu where you can press alt to get to the top menu (such as file, edit, view) and then left/right arrows to navigate through the menu and up/down arrows to navigate through the submenu. It's fine to do that on a web application but it makes the code more complicated. I rarely use the menu roles and just rely on basic tabbing to navigate through a list of links.
Just for anyone who stumbles across this, aria-role="menu" and aria-role="menu-item" are not for site navigation (as appears to be the case here).
They are designed for application menus (such as drop downs with commands).
For site navigation the correct (and much simpler) mark-up is to simply use the <nav> element with a nested <ul> (unless you are supporting HTML4...and even then the <ul> would probably be enough!).
Additionally there is no real need for an aria-label in the above given examples as the aria-label is the same as the programatically determinable text (a web browser can work out that the "Home" text is within the <a> element and so will present that information to a screen reader via the accessibility tree).
As such for site navigation the following is all that is needed:
<nav>
<ul>
<li>
<a href="/en-us/">
<span class="">Home</span>
</a>
</li>
<li>
<a href="/en-us/">
<span class="">Search</span>
</a>
</li>
</ul>
</nav>
Don't use WAI-ARIA unless you have explored every other option or you need to support ancient browsers!
Additional
With aria-role="menu" you don't only have to implement arrow key navigation. You also should have functionality added that ensure that:-
the menu can be closed with Esc key.
you can skip to options using letters (so d might skip to "details", the next press of d might skip to "delete" if those were menu options).
Home should jump to the start of the list
End should jump to the last item in the list
Finally
If this is indeed a drop down menu and you have implemented all the above, your mark-up isn't quite right anyway.
The <li> should have role="presentation none" (use both "presentation" and "none" as per guidance) to remove semantic meaning and the role="menu-item" should be on the anchor itself.
<ul role="menu" id="some-menu">
<li role="presentation none">
<a role="menuitem" aria-label="Home" href="/en-us/">
<span class="">Home</span>
</a>
</li>
<li role="presentation none">
<a role="menuitem" aria-label="Search" href="/en-us/">
<span class="">Search</span>
</a>
</li>
</ul>
Also don't forget that you need to associate the <button> that opened the menu with the menu itself, so you must have an ID on the role="menu", and finally don't forget that when the menu is closed you have to return focus to the button that opened it.
<button aria-haspopup="true" aria-controls="some-menu"><!--same ID as the menu above for aria-controls-->
Open Menu
</button>

How to apply keyboard accessibility when dropdown items are span tags?

I'm having a hard time with a custom dropdown menu I made. I'm trying to make it keyboard accessible, but I'm not having much luck with the listbox option. I'm following the instructions I find under WCAG pages, but I'm not having any luck. Here's one of the dropdowns on my page:
<ul class="custom__options dropdown story-selector" id="storyFilter">
<li class="custom__option selected" data-type="all" tabindex="0">All</li>
<li class="custom__option" data-type="news" tabindex="0">News and media</li>
<li class="custom__option" data-type="analysis" tabindex="0">Analysis</li>
<li class="custom__option" data-type="press" tabindex="0">Press releases</li>
</ul>
Here's a working Codepen to play with.
Your Codepen example uses WAI-ARIA attributes but have missing roles and expected keyboard behaviours.
In order to be accessible, all elements must have a minimum of a role and a name.
Your role sets a promise to the user of what kind of element the thing is and sets an expectation of how that thing will behave. Consider a role of "slider". In that single word, you've conveyed a lot of information to the user as to what that component is and how it would behave.
The name helps the user to understand the purpose of the element. The name of a volume slide would be "Volume".
Related attributes and properties are typically applied to one element, or are implied through coded relationships (using aria-labelledby for example). You would not do the following in HTML, for example:
<span alt="My image's text alternative">
<img src="image.png">
</span>
Yet I see things like this often for ARIA menubar implementations:
<li role="menuitem">
Home
</li>
There are options here, but with similar markup, the following would be more appropriate for the interactive menuitem:
<li role="none">
<button role="menuitem" aria-haspopup="true">Home</button>
</li>
It's best to use HTML elements with the closest semantics to what you are hoping to achieve, hence using the <button> element above. A lot of accessibility comes for free when you take this approach, since browsers add many (or all) of the behaviours expected by the user.
If you were to do the above using <div> and <span> elements, you need to enable appropriate keyboard focus and handle both mouse and keyboard events.
<div role="menuitem" aria-haspopup="true" tabindex="0">Home</div>
The W3C's WAI-ARIA Authoring Practices details approaches and expectations for common design patterns. For example, if you have several top-level items to choose from, you would want to use a Navigation Menubar.
Based on the Codepen example, what you are looking for is probably something like a Menu Button (or this alternative Menu Buttons tutorial), since you only requite a single dropdown menu rather than a whole menubar. This would produce something like the following:
<button aria-expanded="false" aria-haspopup="true">Story type</button>
<div role="menu">
<button role="menuitem">Home</button>
<button role="menuitem">All</button>
<button role="menuitem">News and media</button>
<button role="menuitem">Analysis</button>
<button role="menuitem">Press releases</button>
</div>

Semantic HTML5 for sequence of menu or UI choices [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
When writing HTML5 condent describing to the reader how to navigate through a UI selection path (things like menus, tabs, and dialogs, where there are multiple choices at each step) like:
Options ▸ Configure… ▸ Keyboard Shortcuts
What kind of elements should the labels be?
What kind of elements are the separators, if any? (Or should they be inserted with CSS?)
What kind of element should the entire sequence be contained in?
Note that this is not a question about formatting, nor about interactive elements. It is purely about semantically correct markup in a static descriptive text.
Some things are still going to depend on the actual use cases but basically, you're using a <nav> and then a bunch of <ul><li>.
The toggles to open/close a part of the menu should be <button> with aria-expanded set to "true" or "false" for the open and close states.
The end items should either be <a> if they redirect to a different screen, or <button aria-pressed="true"> if they are just on/off toggles (with the aria-pressed changing depending on the state).
if the whole menu takes focus and/or visibility away from the rest of the app (kind of like a pop-in), you might want to wrap it inside <div role="dialog" aria-modal="true" aria-label="Menu"> <div role="document"> and add a "close" button as the first child.
Here's an example of what the full markup might look like:
<nav role="navigation" aria-label="Full menu">
<!--
the following is useful if the entire menu is behind a single button,
otherwise, you can start directly at the <ul>
-->
<button type="button" aria-expanded="true">
<span>Menu</span>
</button>
<!-- end of "single entry point" -->
<!--
the following is in case you're making a "pop-in" that obscures the rest of the page,
otherwise you can skip them
-->
<div role="dialog" aria-modal="true" aria-label="Menu">
<div role="document">
<button type="button" aria-label="Close menu">
<span>Close</span>
</button>
<!-- end of "pop-in" wrapper -->
<ul>
<li>
<button type="button" aria-expanded="true">
<span>Options</span>
</button>
<ul>
<li>
<button type="button" aria-expanded="true">
<span>Config</span>
</button>
<ul>
<li>
<!-- use <a> if you're redirecting to somewhere -->
keyboard
<!-- use <button> if it's just a toggle -->
<button type="button" aria-pressed="true">toggle Off</button>
</li>
<!-- other Options > Config > * -->
</ul>
</li>
<!-- other Options > * -->
</ul>
</li>
<li>
<button type="button" aria-expanded="false">
<span>Tools</span>
</button>
<ul>
<!-- all Tools > * menu items -->
</ul>
</li>
<!-- other menu categories -->
</ul>
</div>
</div>
</nav>
Tbh, depending on how you need it to look, it might be a pain to style because for it to be properly semantic, you need to have this "recursive" structure of <ul><li> and the <button aria-expanded> should be directly followed by the <ul> they are expanding.
Bonus issue: you can't use the CSS display: contents otherwise the browsers will lose the semantics.
To strictly answer your questions:
What kind of elements should the labels be?
Basically, <button type="button"> with the proper aria attributes. Sometimes <a> for the end items if they redirect the user to another page.
What kind of elements are the separators, if any? (Or should they be inserted with CSS?)
CSS is probably best, the DOM will be separation enough from a semantics point of view. If you need your separators in the markup, try and add aria-hidden="true" if they contain some "readable" elements (span, svg, img, ...).
What kind of element should the entire sequence be contained in?
It should be a <nav role="navigation"> even though the specs state that nav shouldn't have a role attribute because it's intrinsically navigation, but not all browsers implement that properly.

JAWS does not read aria-label for link within a link inside li with role="tab"

The below is my code for aria accessibility in html.It's working fine with ChromeVox but when running with JAWS all the aria-labels are read when focus is on link Menu1.But aria-label of link options should be read when focus goes on it.
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style>
#div1{
padding : 12px;
}
</style>
</head>
<body>
<div class="container">
<ul role="tablist" class="nav nav-tabs">
<li role="tab">
<div id="div1">
<a tabindex="0" aria-label="first menuitem" class="active">Menu1
<a class="dropdown-toggle" tabindex="0" data-toggle="dropdown" aria-label="Press spacebar to use options menu" tabindex="0">options</a>
<ul class="dropdown-menu" role="menu">
<li role="presentation"><a tabindex="0" role="menuitem">Properties</a></li>
<li role="presentation"><a tabindex="0" role="menuitem">Edit Properties</a></li>
</ul>
</a>
</div>
</li>
<li role="tab">
Menu2
</li>
</ul>
</div>
</body>
What I want is the aria-label of each link should be read only when the focus goes on particular link, not when the focus is on link Menu1, which is the current behaviour.
Any help will be appreciated.
The first issue at play here is that you have a link within a link. Not only is it invalid to nest an <a href> within an <a href> (or any interactive content), but that also means screen readers may do unexpected things when they encounter nested interactive controls. Things which cannot be considered wrong.
This means you cannot convert the second link to a <button> and expect things to be ok as you will still have nested interactive controls.
A second issue that will come into play later is any instructions to use specific keys unless those keys are mapped. For example, your instructional text says to "Press spacebar to use options menu" but that menu appears to be in a link. The space bar does not activate a link when it has focus, it will scroll the page.
The WAI-ARIA Authoring Practices 1.1 for a tab control details the keyboard controls that it will need to support.
Finally, since <a href> is already interactive content and is keyboard accessible, you do not need tabindex="0" at all. You can (and should, IMO) remove it.
Do not nest any interactive elements. If when you click on those anchor tags it redirects the user to another page than they should have a href attribute. I am assuming you are handling the redirection with some sort of click event, if that is the case, try adding
href="#"
Do not use tabindexes unless extremely necessary, adding the href attribute should be sufficient to add those links to the tab order.
I have no idea how your design looks like, but I would suggest the following approach
<ul role="tablist">
<li role="tab">
Menu1
<div id="submenu" aria-hidden="true" style="display:none">
options
</div>
</li>
</ul>
I added aria-hidden="true" style="display:none" because I am assuming you are going to add some kind of mouse-over and focus event on the menu tab that will then show the submenu div.