How do I make Nestable Tabs fully accessible?

I have placed Nestable Tabs in a Mega Menu. I thought everything placed inside a nav menu should be automatically accessible, but currently when I use the TAB key to navigate through the site, the tabs within the mega menu are skipped and it jumps directly to the opened default tab, then on to the next menu item (after the tabs). I tried adding different html tags to the tab but nothing seems to work properly. When I added a custom “a” tag to the tab title, it broke the layout and added unwanted styling. How do I achieve this? Thanks!

Hi @monadic, I’m not sure if this will make them fully accessible but I’ve made script to make them accessible by keyboard.
First you need to add custom attribute to the divs in tab navigation (the div, not the text), set attribute name to tabindex and value to 0. Then add this script in the footer of the website:

<script>
    let tabs = document.querySelectorAll('.tab-title');
    let contents = document.querySelectorAll('.tab-pane');
    
    tabs.forEach(function(tab, index) {
        tab.addEventListener('keydown', function(e) {
            // Check if the key pressed was Enter
            if (e.keyCode === 13) {
                // Remove "brx-open" class from all tabs and contents
                tabs.forEach(function(innerTab) {
                    innerTab.classList.remove('brx-open');
                });
                contents.forEach(function(content) {
                    content.classList.remove('brx-open');
                });

                // Add "brx-open" class to the currently focused tab and its content
                this.classList.add('brx-open');
                contents[index].classList.add('brx-open');
            }
        });
    });
</script>

This will work for any nested tabs on the whole site

2 Likes

Awesome! Thank you for that.
It works great, except: currently when opening a tab with Enter and then tabbing to go through the links, it will go through the remaining tab titles first and only then will go into the opened tab pane. Meaning if someone wanted to check the links in tab 1 and then move onto tab 2, they would need to start at the beginning of the page again. Is that due to a misconfiguration on my part?
Thanks again!

I don’t fully understand, I’m not using tabs in navigation but on a page.
Can you please record a video showing example and share a link? I can have look and maybe come up with something :slight_smile:

1 Like

Thank you! :slight_smile:

Here’s a video: Bildschirmaufnahme 2023-07-19 um 12.28.46.mov

And here’s the page Style Guide – ThetaConnection – Sabine Diedrich

Thanks for the video and link.
I have tried to get the focus on tab content automatically after the enter key is pressed, here is the code:

let tabs = document.querySelectorAll('.tab-title');
    let contents = document.querySelectorAll('.tab-pane');
    
    tabs.forEach(function(tab, index) {
        tab.addEventListener('keydown', function(e) {
            // Check if the key pressed was Enter
            if (e.keyCode === 13) {
                // Remove "brx-open" class from all tabs and contents
                tabs.forEach(function(innerTab) {
                    innerTab.classList.remove('brx-open');
                });
                contents.forEach(function(content) {
                    content.classList.remove('brx-open');
                });

                // Add "brx-open" class to the currently focused tab and its content
                this.classList.add('brx-open');
                contents[index].classList.add('brx-open');

                // Focus on the first focusable element in the active content pane
                let firstFocusableElement = contents[index].querySelector('a, button, input, [tabindex]');
                if (firstFocusableElement) {
                    firstFocusableElement.focus();
                }
            }
        });
    });

It didn’t “feel right”, changing the focus without the user requesting it.

Then I’ve tried to prevent the default action on TAB key press and instead move the focus to the first element of the content tab. Only when single TAB key is pressed, so combination of Shift+TAB for going back will work, as well as others:

let tabs = document.querySelectorAll('.tab-title');
    let contents = document.querySelectorAll('.tab-pane');
    
    tabs.forEach(function(tab, index) {
        tab.addEventListener('keydown', function(e) {
            // Check if the key pressed was Enter
            if (e.keyCode === 13) {
                e.preventDefault();  // Stop the default Enter key behavior

                // Remove "brx-open" class from all tabs and contents
                tabs.forEach(function(innerTab) {
                    innerTab.classList.remove('brx-open');
                });
                contents.forEach(function(content) {
                    content.classList.remove('brx-open');
                });

                // Add "brx-open" class to the currently focused tab and its content
                this.classList.add('brx-open');
                contents[index].classList.add('brx-open');

                let firstFocusableElement = contents[index].querySelector('a, button, input, [tabindex]');

                // Add a one-time event listener for the next keydown event
                this.addEventListener('keydown', function(e) {
                    // Check if the key pressed was Tab without Shift
                    if (e.keyCode === 9 && !e.shiftKey && firstFocusableElement) {
                        e.preventDefault();  // Stop the default Tab key behavior
                        firstFocusableElement.focus();  // Focus on the first focusable element in the active content pane
                        this.removeEventListener('keydown', arguments.callee);  // Remove this event listener after it has been triggered
                    }
                });
            }
        });
    });

I wasn’t sure about the best practices of changing the default behaviour so I’ve asked Chat GPT for help and this is what it came up with:

In terms of accessibility, it is generally better to avoid moving the focus automatically. This is because when the focus moves unexpectedly, it can be disorienting and confusing for keyboard-only users and users of assistive technology.

Therefore, the best practice is to allow the Tab key to function as it naturally would, which is to move focus to the next focusable element in the DOM order. This means that after a tab has been activated, pressing the Tab key should move focus to the next tab, not directly to the content associated with the activated tab.

In the context of your tab interface, this means that a user would first Tab through all the tab headings. Once a desired tab heading is focused, the user can press Enter to activate it (which might visually reveal its associated tab panel). The user can then continue pressing Tab to move focus through the remaining tab headings and eventually into the active tab panel.

If the number of tabs is large and you want to provide a shortcut to the active tab content, consider providing instructions (like a tooltip or some other visible instruction) to the user that they can press a specific key combination (like Alt + Down arrow) to move directly to the content.

So, in conclusion, not moving the focus automatically is more predictable and thus often provides a better user experience for keyboard users and users of assistive technologies.

Feel free to test the scripts and use them, but personally I think that the default behaviour (DOM order) shouldn’t be altered / ignored.

1 Like

Thanks for this! I am still undecided, but you (and ChatGPT, haha) make a great point. I guess having the focus and tabs behave in the way that people with screen readers expect it to behave makes the most sense. After all that is why I am trying to implement it: accessibility. :slight_smile:

You are welcome :slight_smile: I’m glad to see another accessibility focused person :slight_smile:

I see you went away from the tabs in your site… did this not work out for you?

Thank you so much, this was very helpful.