Accessible Tabs Element

A fully accecible tabs element

HTML

    <div class="tabs">
        <ul role="tablist" class="tablist">
                <li role="presentation">
                        <a
                                class="tab"
                                id="tab1"
                                href="#section1"
                                role="tab"
                                aria-controls="section1"
                                aria-selected="true"
                                >Tab One</a
                        >
                </li>

                <li role="presentation">
                        <a
                                class="tab"
                                id="tab2"
                                href="#section2"
                                role="tab"
                                aria-controls="section2"
                                >Tab two</a
                        >
                </li>

                <li role="presentation">
                        <a
                                class="tab"
                                id="tab3"
                                href="#section3"
                                role="tab"
                                aria-controls="section3"
                                >Tab Three</a
                        >
                </li>
        </ul>
        <div class="tab-section">
                <section
                        class="tabpanel"
                        id="section1"
                        role="tabpanel"
                        aria-labelledby="tab1"
                        tabindex="0"
                >
                        Section 1
                </section>

                <section
                        class="tabpanel"
                        id="section2"
                        role="tabpanel"
                        aria-labelledby="tab2"
                        tabindex="0"
                        hidden
                >
                        Section 2
                </section>

                <section
                        class="tabpanel"
                        id="section3"
                        role="tabpanel"
                        aria-labelledby="tab3"
                        tabindex="0"
                        hidden
                >
                        Section 3
                </section>
        </div>
    </div>

CSS

    .tabpanel:not(:target):not(.visible) {
            display: none;
    }

        .tab:focus-visible {
                background-color: royalblue;
                color: whitesmoke;
                outline: 0.2em solid royalblue;
        }

    .tab[aria-selected='true'] {
            background-color: var(--selected-tab, pink);
            color: black;
    }

JavaScript

    const tablist = document.querySelector('.tablist');
    const tabs = [...tablist.querySelectorAll('.tab')];
    const tabpannels = [...document.querySelectorAll('.tabpanel')];

    // Hide all panels except the current tab
    const showActivePanel = (element) => {
            const selectedId = element.id;
            tabpannels.forEach((tabPanel) => {
                    tabPanel.hidden = 'true';
            });
            const activePanel = document.querySelector(
                    `[aria-labelledby="${selectedId}"]`
            );
            activePanel.removeAttribute('hidden');
    };

    const setSelectedTab = (element) => {
            const selectedId = element.id;
            tabpannels[0].classList.remove('visible');

            tabs.forEach((tab) => {
                    const id = tab.getAttribute('id');
                    if (id === selectedId) {
                            tab.removeAttribute('tabindex', '0');
                            tab.setAttribute('aria-selected', 'true');
                    } else {
                            tab.setAttribute('tabindex', '-1');
                            tab.setAttribute('aria-selected', 'false');
                    }
            });
    };

    const handleOnKeyboardArrows = () => {
            const firstTab = tabs[0];
            const lastTab = tabs[tabs.length - 1];

            tabs.forEach((element) => {
                    element.addEventListener('keydown', function (e) {
                            // If arrow up or arrow left
                            if (
                                    (e.keyCode || e.which) === 38 ||
                                    (e.keyCode || e.which) === 37
                            ) {
                                    // If it is the first tab go to last tab
                                    if (element == firstTab) {
                                            e.preventDefault();
                                            lastTab.focus();
                                    }
                                    // Otherwise focus previus tab
                                    else {
                                            e.preventDefault();
                                            const focusableElement = tabs.indexOf(element) - 1;
                                            tabs[focusableElement].focus();
                                    }
                            }
                            // If arrow down or arrow right
                            else if (
                                    (e.keyCode || e.which) === 40 ||
                                    (e.keyCode || e.which) === 39
                            ) {
                                    // If it is the last tab, go back to the first one
                                    if (element == lastTab) {
                                            e.preventDefault();
                                            firstTab.focus();
                                    }
                                    // Otherwise focus next
                                    else {
                                            e.preventDefault();
                                            const focusableElement = tabs.indexOf(element) + 1;
                                            tabs[focusableElement].focus();
                                    }
                            }
                    });
            });
    };

    // If the panel section has focusable elementss inside, make the panel section focusable
    const determinePanelTabindex = () => {
            tabpannels.forEach((tabpanel) => {
                    const focusableElements = tabpanel.querySelectorAll(
                            'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled]), details:not([disabled]), summary:not(:disabled)'
                    ).length;

                    focusableElements
                            ? tabpanel.setAttribute('tabindex', '-1')
                            : tabpanel.setAttribute('tabindex', '0');
            });
    };

    const handleOnClick = () => {
            tabs.forEach((tab) => {
                    tab.addEventListener('click', function () {
                            setSelectedTab(tab);
                            showActivePanel(tab);
                    });

                    tab.addEventListener('keydown', function (e) {
                            // on space key (almost like hitting enter)
                            if ((e.keyCode || e.which) === 32) {
                                    setSelectedTab(tab);
                                    showActivePanel(tab);
                                    tab.click();
                            }
                    });
            });
    };

    const activateFirstPanel = () => {
            tabs[0].setAttribute('tabindex', '0');
            tabs[0].setAttribute('aria-selected', 'true');
            tabpannels[0].classList.add('visible');
    };

    const checkInitialSelectedTab = () => {
            const targetedTabPanel = document
                    .querySelector('.tabpanel:target')
                    .getAttribute('aria-labelledby');
            const selectedTab = document.querySelector(`#${targetedTabPanel}`);
            selectedTab.setAttribute('aria-selected', 'true');
            selectedTab.removeAttribute('tabindex');
    };

    const handleInitialState = () => {
            tabs.forEach((tab) => {
                    tab.setAttribute('tabindex', '-1');
                    tab.setAttribute('aria-selected', 'false');
            });

            // If no other panel is selected, the default to the first one on load
            window.location.href.indexOf('#panel') === -1
                    ? activateFirstPanel()
                    : checkInitialSelectedTab();

            determinePanelTabindex();
    };

    handleOnClick();
    handleOnKeyboardArrows();

    window.onload = handleInitialState;

Here is a great Post about accesible tabs.