Tabs and accordions are the bread-and-butter of UI work โ and building them accessibly is a hiring signal.
Tabs โ the accessible pattern
<div class="tabs" role="tablist"> <button role="tab" aria-selected="true" data-panel="p1">GPA</button> <button role="tab" aria-selected="false" data-panel="p2">CGPA</button> </div> <div id="p1" role="tabpanel">...</div> <div id="p2" role="tabpanel" hidden>...</div>
tablist.addEventListener("click", (e) => {
const tab = e.target.closest("[role=tab]");
if (!tab) return;
tabs.forEach(t => t.setAttribute("aria-selected", t === tab));
panels.forEach(p => p.hidden = p.id !== tab.dataset.panel);
});
// arrow-key navigation โ the part everyone skips
tablist.addEventListener("keydown", (e) => {
if (!["ArrowLeft", "ArrowRight"].includes(e.key)) return;
const arr = [...tabs], i = arr.indexOf(document.activeElement);
const next = arr[(i + (e.key === "ArrowRight" ? 1 : -1) + arr.length) % arr.length];
next.focus(); next.click();
});Accordion โ you already have it
Native <details>/<summary> IS an accessible accordion (full guide) โ including exclusive groups via the name attribute. Only hand-build when you need animated height, and even then animate a wrapper, not the details itself.
Our CGPA calculator uses this exact tab pattern โ inspect it live.