Column visibility menu tabbing outside
Column visibility menu tabbing outside
When using the ColVis menu, I'm trying to get the tabbing to cycle through the menu. After the last tabbed element it goes to the next element underneath the menu. This would be confusing for users with screen readers. I have tried it on this example.
https://datatables.net/extensions/responsive/examples/column-control/column-visibility.html
I'd like to keep tabbing inside the menu. I was having a similar problem with Bootstrap modals but fixed this with <div class="modal" tabindex="-1">
. That traps the focus inside the modal until escaping or using a close button.
Another ColVis related question is could aria-labels be included on the toggled columns so visually impaired people know whether the column is shown or hidden? Is there a recommended way of achieving this? I wondered if maybe a different way of presenting this would work better. For example checkboxes.
Replies
Hi,
Thanks very much for this!
Is that a Bootstrap thing? MDN says about negative numbers for tabindex:
It would be really handy if that is something we could just add to the dropdown container, but I've just tried it, and it doesn't keep the tab focus inside the container.
Very nice idea. Would "Column {name} is currently visible/hidden. Toggle to hide/show." be suitable do you think? Quite a few language / i18n considerations there unfortunately.
Based on the
active
class on the button you could use a::before
pseudo element to display a checkbox if you like.Allan
Hi @allan. I initially added
tabindex="0"
to the modal title and some jQuery to automatically focus the title after a modal button click, but the focus still tabbed out. You are correct that the idea behindtabindex="-1"
is to skip an element from the tab index, but I found that applying it to the top level of the modal allows for focusing inside, and traps it too. From https://webaim.org/techniques/keyboard/tabindexI also tried
tabindex="-1"
on the ColVis menu without success, but wasn't sure if I'd applied it correctly. It might still be possible, but maybe it needs structuring in a different way, but it seems to me it is a type of modal too.Regarding the state of the ColVis toggle buttons... I think your suggestion does sound good, but maybe there is a quick way to fix this. What I've done to other buttons, for example one that clears the search box and dropdown filters is...
$(".dt-buttons .clear-filtering").prop("disabled", true);
which when read by a screen reader says the button aria-label and then says "dimmed". I would assume an aria-label wouldn't be necessary because the column name would be read out first.These are the 2 conditionals I use in that function.
I think this might be feasible, but you are the expert so I'll let you decide!
Hi @allan, I've been doing further work on this.
I've found a way for screen readers to know the toggle state of the ColVis buttons. I can't use aria-labels on the ColVis individual buttons, because that overrides the button name, so what is needed is the title attribute which reads out after the button name. I've included a one time function when clicking the ColVis menu button. It initially adds the same title attribute to all buttons. Obviously this only works if all DT columns are shown after initialisation. A function would be needed to get the current active buttons if some columns are off by default.
Then another function that only works on the individual ColVis buttons checks whether the button has the
active
class (or not), and changes the title attribute accordingly. I've done some testing and it appears to work, but more testing would be wise just in case!You asked whether the
tabindex="-1"
was a Bootstrap thing. It turns out it is and there is an example under "Live Demo"… https://getbootstrap.com/docs/4.0/components/modal/I've found a partial fix for the ColVis menu not trapping the focus, which is confusing for the visually impaired. I can't take credit for this because I've lifted it from here… https://uxdesign.cc/how-to-trap-focus-inside-modal-to-make-it-ada-compliant-6a50f9a70700 and it's also available as a gist https://gist.github.com/myogeshchavan97/d50d42aa9205573b811587d57c2e58a6#file-trap_focus-js
However, it works in Chrome and Safari, but the trap isn't working in Firefox, Edge and Opera, but that's better than nothing. All I've changed is
document.querySelector('.dt-button-collection');
.UPDATE: After a few attempts at hard refreshes, the focus trap now works in Firefox, Edge and Opera, in addition to Chrome and Safari.
Hi,
Many thanks for your replies and insight!
I'm a bit nervous about using the disabled state this way as a button can be active / inactive and enabled / disabled (any combination of the above). So using the disabled state to show inactive would probably lead to confusion somewhere down the line.
Using the title attribute sounds good though. You can set the title attribute to an initial state using the
titleAttr
option for a button, and then update it using a function as you are. If that can be generalised, I can look at including that in the library.Regarding the trap - I will look at getting that integrated for the next release. I think that is the right thing to do.
Allan
Hi @allan
I've not gone this deep with WCAG until now so a lot of it is new to me!
My first suggestion at "dimmed" disabled buttons was before I needed to think of another way for the ColVis toggle buttons which can't be disabled and need to show a state. In my implementation
disabled
works because of the button's function. In my case the button is for clearing filters and the search box, and runs a check to see if it needs to be active or not. Originally I just styled the button as greyed out, and removed the cursor interaction. I was told for screen readers I should notify that it's disabled. Adding a dynamic title or aria-label would be just as good.I also had a similar button for clearing the ColVis, but now I've discovered the "Restore column visibility" feature I've styled the menu buttons and used dynamic toggle titles. I originally disabled the Restore visibility button until it was needed, but like you said that could cause confusion. It also breaks the focus trap and it jumps back out! Instead I changed it to a dynamic aria-label.
The only minor problem I found with the trap focus code, was it does focus the 1st ColVis menu button
firstFocusableElement.focus();
but doesn't highlight it with an outline showing it has focus. Tabbing down makes the outline appear. I've tried a few things but couldn't fix it. That could be more of a browser issue though.I think a dynamic aria-label sounds like it might be the way to go here. I'll have a think about what we can do there - we do it for column headers already (to state what the action will do to sorting), so it isn't unreasonable to also do that there. It needs to be modular though so it can work with other dropdown types, not just ColVis. Or more generally apply to all buttons.
Really good point about disabled effecting the focus.
Allan
Hi @allan
I'm resurrecting this post because my question is related to ColVis. I realised that when users navigate with keys and use the enter key, there are problems. This impacts the focus trap and the restore visibility button. Using Tab + Space on ColVis is fine and works the same as filter dropdowns which don't allow selection with the enter key. I've tried to disable it, and the console shows my code does recognise the enter key, but then the ColVis fires up straight after. Do you know of a way to prevent this? I've worked on variations of this code...
@silkspin We're happy to take a look, but as per the forum rules, please link to a test case - a test case that replicates the issue will ensure you'll get a quick and accurate response. Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.
Cheers,
Colin
@Colin This is regarding code @allan already knows about. I don't have a demo because he implemented his own testing of the focus trap code. The problem is whatever I do to try and stop "enter" opening the ColVis menu, DT ignores it probably due to the core files.
You can see in the basic ColVis demo https://datatables.net/extensions/fixedcolumns/examples/initialisation/colvis.html how "space" and "enter" both open the menu. There must be a way of disabling "enter" because filter dropdowns in DT don't open on "enter". I just need the same behaviour. Otherwise the code Allan is incorporating into DT for the focus trap inside ColVis will not function as it should when people use the keyboard to navigate.
@Colin @allan I've just knocked up a test case that was showing the same behaviour as my local dev version. I've added a distinctive focus so you know you are on it. This simplified version is now working after I made a minor change the focus trap code.
I changed
$(document).on("click"
to$(document).on("keypress click"
and now it seems to work with "space" and "enter".http://live.datatables.net/tumodebo/1/edit
"space" was working with click but not "enter". If I just use "keypress" then the "space" doesn't work. So both triggers are needed.
However, unfortunately trying to get this working locally isn't working. If I add "keypress" to the "click" I get the error
Uncaught TypeError: Cannot read properties of null (reading 'querySelectorAll')
which points to the lineconst firstFocusableElement = modal.querySelectorAll(focusableElements)[0]; // get first element to be focused inside modal
.Can you offer any advice on this error, or back to me original question, can I disable the "enter' triggering the ColVis?
The error message suggests to me that
document.querySelector('.dt-button-collection');
isn't finding anything on your page for some reason. Without being able to see it, I'm not immediately sure what would cause that though.There is no option built in to do that I'm afraid. However you could use:
to disable the listener we add.
That said, with the return key, your demo seems to work really nicely - it is create to see that working so well.
Allan
Hi @allan I've been getting different results depending on which version of dataTables.buttons.min.js I use. I've tried all versions going back to 1.7.1 but at the moment I'm on 2.0.1 because it seems to function the best.
v2.2.2 was causing problems with other buttons like the filter clear. For example I changed the styles to show as enabled/disabled and mouse click and space bar press would clear the filters and switch the button style. The enter key however just cleared the filters, but didn't switch style. This also looks down to the event type. Click is being used the same as in 2.0.1. I can't find any events that could be conflicting in my custom js. If I add keypress to the click then the clear function doesn't work. It seems to be a reoccurring theme when multiple events are detected.
Regarding the other problem, in 2.0.1 I still get the
Uncaught TypeError: Cannot read properties of null (reading 'querySelectorAll')
error but only on a keypress or keydown event. It seems to me that keypress events run are too early and.dt-button-collection
isn't ready, but it is for clicks.Currently I've got it working by just using "click" with 2.0.1. The only downside now is that if selected by enter key, the modal menu opens up, but it's not just receiving focus like with the space and mouse click, it's also being selected which means the first column is hidden. I've tried to stop that but so far I've failed to find a solution.
Has the focus trap been published in Datatables? Maybe your implementation would mean I can ditch my version.
Also, where exactly should I put the
$(table.button(0).node()).off('keypress.dtb');
? I haven't managed to place it in the correct place so far.@allan I've got a little further, although not solved it, but you will have a better idea of what is happening. It turns out the ColVis opened via click with the enter key triggers twice. That's why the first column shows as off. If I hold down enter on a button inside the menu, it flashes on and off and depending on when it's released it can go to the other state, but one click just toggles once and returns to what it was before. I've tried to prevent default and prevent propagation with no luck.
It also turns out that the demo isn't trapping the focus if you follow these steps.
1. open ColVis
2. tab down menu and hit enter to turn off a column (all ok)
3. tab down menu and hit space to turn off a column (focus escapes)
http://live.datatables.net/tumodebo/1/edit
My local dev copy does actually handle this fine, but like I mentioned I am using 2.0.1. If I switch back to 2.2.2 then mouse click and space bar click and tabbing works fine, trapping the focus. In the enter key click scenario the ColVis button opens the modal menu but keeps the focus around the ColVis button. Even entering the menu with tab doesn't trap it. That was why I thought disabling the enter key might be an idea because you can still use tab + space to navigate. Also 2.2.2 still has an issue with the clear filter button when I use that and I've not found a workaround. The double firing enter key isn't a problem in 2.2.2 though.
After testing loads of combinations, I've found a simple fix. It doesn't seem to have impacted any other features as yet. It has fixed the double click that was being fired, and doesn't affect the clear filter button. I've edited dataTables.buttons.min.js 2.2.2 and changed both instances of…
with…
The focus trap can still escape in certain instances, especially when targeting the top or bottom buttons. I've added
$(this).focus();
to the last clicked button which now seems to hold it in the menu.Nice, thanks for reporting back,
Colin
Hi,
Thanks for all your insights into this!
I've just made a couple of commits for this:
Interested in your feedback if you give it a go! It will be in the nightly build shortly.
Allan
Thanks @allan. I've tested with mouse click and both space and enter selection. It all functions correctly and the focus doesn't escape.
There is just a minor problem, BUT that is down to the customisation I've implemented. I have styled the restore visibility button depending on whether it's active or not. I've just updated the test I did and there aren't any states in the default version, so it isn't something you need to worry about http://live.datatables.net/tumodebo/4/edit
It only affects my setup when using the enter key to select colvis buttons, and then it ignores the style on restore visibility button. It works fine for clicking and space. Shouldn't be too hard for me to fix that.
Sounds good. Give me a shout if you'd like me to look at the styling. I did notice that we didn't have
:focus
styling on the "active" buttons with our default CSS. I added that in with the above changes.Allan
Hello Allan,
The columnvis is not a modal dialog, it is a expand/collapse element in my view. For state change of button use aria-pressed or use checkboxes instead of buttons.
Coming to trapping focus in menu buttons, it is a terrible idea. We use tab & shift+tab to move between elements. In current implementation of buttons once the focus moves out of buttons the columnvis buttons collapse which is a design pattern accepted.
if keyboard focus is trapped then this fails WCAG 2.1.2 keyboard trap.
Check digitala11y.com header nav. The resources submenu will close as soon as keyboard focus moves out of the last element.
If we want to trap the columnvis buttons as a dialog & need to trap the focus then we need to use role=dialog, aria-modal attributes on the divv that has the buttons.
Ideally this approach is not great as it might cause multiple accessibility & usability problems. I prefer this button being a accordion with checkboxes or buttons with aria-pressed for state change. Do not use dynamic aria-labels.
That's really interesting - thank you. I'd actually considered a modal rather than a expand/collapse since it needs to be activated (click or return key) before any of its sub-elements are placed into the DOM. Also, there is a "blocker" element in the background disallowing interaction with the rest of the page, which is why it felt right to trap focus in there until dismissed.
Thanks for the link - it took me a little while to figure out how to show the sub-menu with just the keyboard, but that's probably just my inexperience.
I wonder if part of our ColVis dropdown issue is the
aria-haspopup
andaria-expanded
properties? Should they be removed if I were to treat it as a modal (it has other display modes which make it visually much more like a modal in the centre of the screen - although I'm not sure if that has an impact)?Allan
Hello Allan,
since the menu is hiding the content on page I believe everyone is thinking this as a modal dialog. if we move to modal dialog route then we make sure keyboard focus is trapped inside the modal until user closes the modal with a close or escape key.
I prefer the accordion button to expand/collapse elements & manage the visual aspect with CSS.
Here is thee modal dialog example, yes we remove the aria-expanded when mmodal is being triggered. aria-haspopup is optional.
https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html
Thanks!
I don't actually see
aria-expanded
in that example at all. I've just been reading the spec about it and although it doesn't explicitly say that it be used for a modal, it does sound like it can be.aria-haspopup
does explicitly say that it can be used for a dialog (which I take to also mean a modal).I've made a small change based on reading the spec to make the
aria-haspopup
bedialog
. Although it is optional, based on the spec it seems like a good idea to include it?I've also added
role=dialog
andaria-modal=true
to the popover element now.Allan
ok, can i see a demo, will be able to test with screen reader & then give feedback.
Here you go - you can see the changes on the colvis button.
Colin