How to tab past closed modal links? #a11y - javascript

General accessibility question here. I'm looking for general approach, but will also note that this is in a React app so statefulness is a consideration.
Take the following code example of a list of actions, which open corresponding modals. Ideally, you would be able to tab through the list of actions in sequence - but because the modals have links inside, the tabbing experience is not ideal. Basically, you hit 'action 1' and then tab 6 more times before hitting 'action 2' due to the 5 links contained in the modal.
<li class="list__item">
<!-- modal trigger -->
Action 1
<!-- modal containing links -->
<aside class="item__modal modal" id="modal-interview-1">
<a href="#>Sample 1</a>
<a href="#>Sample 2</a>
<a href="#>Sample 3</a>
<a href="#>Sample 4</a>
<a href="#>Sample 5</a>
</aside>
</li>
<li class="list__item">
<!-- modal trigger -->
Action 2
<!-- modal containing links -->
<aside class="item__modal modal" id="modal-interview-2">
<a href="#>Sample 1</a>
<a href="#>Sample 2</a>
<a href="#>Sample 3</a>
<a href="#>Sample 4</a>
<a href="#>Sample 5</a>
</aside>
</li>
The question on approach what is the best way to handle hiding the anchor tags from the DOM, or at least from tabbing and screen reading, when a tab is disabled? I've tried adding disabled to the anchors, and adding an aria-focusable="false" to the modal when it's inactive... but it's not giving me the desired effect of skipping the links.
Thanks for your help with this issue.

aria-focusable="false" is only for screen readers and not well supported, which is why you are struggling with that.
You have a couple of robust options:-
Use display: none on the item__modal modal and then when you add the modal--active override it to display: block (or whatever, flex etc.) - display: none on a parent element is robust and will always make it's children unfocusable. This will always work and is the best option.
Set a tabindex="-1" on each link (sadly you can't add it to the parent as it can still get overridden on some screen readers) and change it to tabindex="0" when the modal opens.
<aside class="item__modal modal modal--active" id="modal-interview-1">
Sample 1
Sample 2
Sample 3
Sample 4
Sample 5
</aside>
This will work consistently across all browsers.
It isn't just the tab key
The reason the above are the only robust options is because screen reader users rarely navigate by the tab key.
For example a NVDA user will use 1-6 to navigate by heading levels (H1 - H6) and K to navigate by links to get a feel for the page.
final option (not recommended)
You could intercept the tab key presses and manage focus, but you would need to then add aria-hidden="true" to each of the links for the same reason (and change it to aria-hidden="false" when the modal is active.
This last option does at least afford you the option of using opacity: 0 to hide the items etc. if you really need to.

I'm a big fan of the inert attribute. It's currently still in draft (I've heard that it's available in Chrome behind a flag). You can polyfill the attribute
In essence, you'd set inert as the element is hidden and all technologies would act as though the links aren't there. There's a really good demo on the polyfill page that will better illustrate the idea. I think it would solve your issue.

Related

How to prevent default click behavior of a routerlink in angular app?

Even though this is not angular specific in theory it needs to be solved in ng app and none of the examples work. I've seen all the answers in SO but none of those solutions seem to work in real life Angular7 app. For example none of the following work :
<!-- option 1 -->
<a class="nav-link" [routerLink]='["/properties", sessionId]'
(click)="$event.stopPropagation()">Properties
</a>
<!-- option 2 -->
<a class="nav-link" [routerLink]='["/properties", sessionId]'
(click)="$event.stopPropagation();false">Properties
</a>
<!-- option 3 -->
<a class="nav-link" [routerLink]='["/properties", sessionId]'
(click)="$event.preventDefault()">Properties
</a>
<!-- option 4 -->
<a class="nav-link" [routerLink]='["/properties", sessionId]'
(click)="$event.preventDefault();false">Properties
</a>
Creating a method for handler in component.ts and calling either function with or without returning false does not work either.
In addition, I don't want to disable link because it needs to be draggable / openable in other browser tab/window.
EDIT: Here is https://github.com/angular/angular/issues/21457 and I can make it to work by adding an element inside anchor and have the click for the inside element like this:
(click)="$event.stopPropagation();$event.preventDefault()"
My real world example has mat-icon inside anchor so I use that but in link above a span inside is suggested.
The reason routerLink does not respect preventDefault is described here.
The solution is to create inner element for anchor if there already isn't one (like icon). In the link above a span is created inside but I have icons inside anchors which I omitted from the question for clarity:
<a class="nav-link" [routerLink]='["/map", sessionId]'>
<mat-icon class="tab-nav-item-icon" (click)="$event.stopPropagation();$event.preventDefault()">map</mat-icon>
</a>

Change background element's background-color and text color when clicked on mobile

I have a header and a footer that work perfectly when the user is on a desktop and has a mouse and can hover over them and navigate everything that way.
The problem is on mobile when there is no mouse, I need everything to work as close to the same as it does on desktop. I was almost able to make the "PROJECTS" drop-down work to my liking when clicked as well as the "CONNECT" drop-up, but I'm having two issues.
The first problem I'm having is when "PROJECTS" or "CONNECT" drop-ups/drop-downs are clicked, when I click off them or I click them again, the drop-up/drop-down doesn't vanish. It becomes constantly displayed block and I need it to go back to display: none when the user clicks anywhere else or clicks "PROJECTS"/"CONNECT" a second time. I thought the "else" statement in the script I'm using would accomplish that, but apparently it is not working and I'm not sure why! What is the best way to make that work?
The second problem I'm having is when the user clicks on the li item "ONE" inside "PROJECTS" or any of the li items inside "CONNECT", I need the background of the clicked element to turn black and the text to turn white right before it loads the link (similar to how it looks on the desktop version using the :hover css). At this point, when they are clicked it just flashes the gray highlight color over the element for a split second. I tried adding the same type of css but changing "hover" to "focus" or "visited" and I couldn't get either to work. What is the best way to accomplish that?
Here is a JSFiddle of all the code: http://jsfiddle.net/xmdzg8vu/
If you view the JSFiddle on desktop, it will be hard to see the issues I'm having since you have a mouse and can hover... hopefully having the code will help with finding my errors though!
HTML:
<div id="background"></div>
<header id="header">
<div id="nav">
<ul>
<li id="projects" onclick="displayDropdown()">
PROJECTS
<ul>
<a href="/one" class="blocklink" target="_self">
<li id="one">ONE</li>
</a>
</ul>
</li>
</ul>
</div>
</header>
<footer id="footer">
<div id="footer-nav">
<ul>
<li id="connect" onclick="displayDropup()">
CONNECT
<ul>
<a href="https://www.instagram.com/" target="_blank" class="blocklink">
<li id="instagram">
INSTAGRAM
</li>
</a>
<a href="https://twitter.com/" target="_blank" class="blocklink">
<li id="twitter">
TWITTER
</li>
</a>
<a href="mailto:mail#mail.com" class="blocklink">
<li id="email">
EMAIL
</li>
</a>
</ul>
</li>
</ul>
</div>
</footer>
JS and CSS are seen in the JSFiddle.
Thank you so much!
UPDATE: I have updated my JSFiddle to remove extra script not applicable to this question. Hopefully that cleans it up a little!
For the second problem, have you tried the :active selector? For example, using part of your CSS code:
#one:focused, #one:visited, #one:hover, #one:active {
background-color: black;
color: white;
}
It looks like there are some issues in your markup. Normally we don't nest ul>a. We normally do ul>li>a.
For problem #1 you could add an onclick event handler to the submenu li to close the dropdown (/dropup) ul when a submenu item is clicked.
Let me know if that works. You might also want to use touch events for mobile (even thought click might work).

Show or hide a element by class when you click a specific link

I'm using WPBakery Page Builder for tabs. And I want to show a text block outside the tab section (on a diferent row) with a specific class when first tab with href #1521496635357-e8313acf-e8c2 is open and another text block when the secound tab with href #1521496635380-99d0c08b-67d8 is open (and the first text block to be hidden).
Can you give me a hint with CSS or JS?
Thank you!
<ul class="vc_tta-tabs-list">
<li class="vc_tta-tab vc_active" data-vc-tab="">
<a href="#1521496635357-e8313acf-e8c2" data-vc-tabs="" data-vc-container=".vc_tta">
<span class="vc_tta-title-text">PRIX STANDARD</span>
</a>
</li>
<li class="vc_tta-tab" data-vc-tab="">
<a href="#1521496635380-99d0c08b-67d8" data-vc-tabs="" data-vc-container=".vc_tta">
<span class="vc_tta-title-text">PRIX BUDGET</span>
</a>
</li>
</ul>
Your example is not entirely clear to me, but you should be able to add event listeners to your tabs:
<a href="#1521496635357-e8313acf-e8c2" data-vc-tabs="" data-vc-container=".vc_tta" onclick="doSomething()">
In your page javascript, you could have a function that does something:
function doSomething() {
document.getElementsByClassName("myclass")[0].style.display = "none";
document.getElementsByClassName("myotherclass")[0].style.display = "inline";
}
You could certainly handle this better by introducing jquery or another framework to simplify some of this handling, but depending on your situation that may or may not be feasible.

JavaScript; trying to fire a click within a <ul> and <li id> and <a href> but not till the <li id> is called

Sorry if this is such a 'newbe' question, been fighting this for a while...
Seeking to fire an <a href> from within a tag.
Found several ways to do it, however.. the entire script is with-in an <ul>, so script to "click" the <a href> occurs on load of index.html, not when the specific tag is called.
Sorry if confusing; here are some snippets of code that may help explain.
<ul id="menu">
<!-- several <li> to other parts of the site, then: -->
<li>
<a href="#!/WORKHISTORY" onclick="ga('send','event','Internal Links','Work History')">
<span class="over"></span>
<span class="txt1">Work History</span>
</a>
</li>
</ul>
Followed by:
an <article> and a <ul>
Within the <ul>, is a tag referencing the "workhistory" tag.
<li id="WORKHISTORY">
<div class="box">
<a id=wrkhst1 href="/gallery/1426894494/1426894576.jpg" rel="prettyPhoto[1426894494]">
<span class="over"></span>
</a>
</div>
</li>
I have tried to use <script>document.getElementById('wrkhst1').click();</script>
Which works, however it fires at the load of index.html, not with the click of the parent <li>, as it reads the main index page and loads it.
I tried the same script this in the and not using the tag, but same result.
You need to add an eventhandler, for the onclick-event, on the li element. There you simulate the click on the <a> tag.
In code it could look like:
document.querySelector('#WORKHISTORY').onclick = function(){
document.querySelector('#wrkhst1').click();
};
BUT there are very few scenarios where this is needed. I'm sure in your case it would be better to make the <a> display: block; and set it to the size of the <li>. So <a> can do for what it was made for, without any need of javascript.

How to preload html links from a menu and hide / show the content with javascript?

I have an html menu with links to other pages which have this menu included too. Very basic:
<div id="sidebar-nav">
<ul id="dashboard-menu">
<li class="active">
<div class="pointer">
<div class="arrow"></div>
<div class="arrow_border"></div>
</div>
<a href="index.html">
<i class="icon-dashboard"></i>
<span>Home</span>
</a>
</li>
<li>
<a href="1.html">
<i class="icon-signal"></i>
<span>1</span>
</a>
</li>
<li>
<a href="2.html">
<i class="icon-picture"></i>
<span>2</span>
</a>
</li>
<li>
<a href="3.html">
<i class="icon-calendar-empty"></i>
<span>3</span>
</a>
</li>
</ul>
</div>
So basically this menu helps navigate through content.
When I load the home of the menu I want a function to automatically load the other links too so it speeds up the navigation and of course I want the content of those links to show up only when the corresponding link in the menu is clicked.
What library / function should I look into to achieve that?
Which Library or Function to use
You can see, in my code everything is jQuery. So in my advice, jQuery will be the best for you! You can have it here:
api.jquery.com or even at their site www.jquery.com You can have a quick link at their footer tag.
Pages will be cached
Your page and some of its code is saved as a cache in the local storage, you can check them out using F12. Which will open Developer Tools, then in Network workspace, check out which are loaded from Server and which are loaded from local storage. Almost every browser will save some of your code, from .css files or your scripts so that it doesn't have to load it everytime. You can see the code 304 (correct me, if mistaken) in browser which would mean that the file was loaded from local machine. So don't worry about this. You can get other helpfull articles about speeding up and caching the sessions too.
Dynamically Creating the menu
To dynamically create the link navigation menu you can use:
Example
$('#dashboard-menu').html();
In the HTML of the code, you can write the list items. Which will be set so that you get them. You can call this function on page start as:
Code Example
$(document).ready(function () {
$('#dashboard-menu').html();
}
Techniques
If you don't know what would be the menu, for example you want to load the data from Database, you can use ajax requests too, this way you will write the result in the dashboard-menu. However, your site won't get fast just by removing the navigation menu and laoding it after the page load.
For example:
$.ajax({
url: "page_to_load.html"
success: function (data) {
$('#dashboard-menu').html(data);
}
});
Alternate way of using Ajax
Alternate way for this is load().
http://api.jquery.com/load/
To show only relative menu
To show the content you can use show(). Like this, lets take the example from your code
Snippet from your code
<li>
<a href="1.html">
<i class="icon-signal"></i>
<span>1</span>
</a>
</li>
Showing child
To show the a from this; since a is a child of li, you can use this:
$('li').click(function () {
$(this).find('a').show(); // or even use toggle()
}

Categories