Skip to content

Instantly share code, notes, and snippets.

@H-ymt
Last active September 7, 2024 13:26
Show Gist options
  • Save H-ymt/67f967775ec0439b639baeeb2036a69c to your computer and use it in GitHub Desktop.
Save H-ymt/67f967775ec0439b639baeeb2036a69c to your computer and use it in GitHub Desktop.
アクセシビリティを考慮したタブUI
<div class="tabs-container">
<div class="tabs-list" role="tablist" aria-label="サンプルタブ">
<button class="tab" role="tab" aria-selected="true" aria-controls="panel-1" id="tab-1" tabindex="0">
タブ1
</button>
<button class="tab" role="tab" aria-selected="false" aria-controls="panel-2" id="tab-2" tabindex="-1">
タブ2
</button>
<button class="tab" role="tab" aria-selected="false" aria-controls="panel-3" id="tab-3" tabindex="-1">
タブ3
</button>
</div>
<div id="panel-1" class="tab-panel" role="tabpanel" aria-labelledby="tab-1">
<h2>タブ1の内容</h2>
<p>これはタブ1のコンテンツ</p>
</div>
<div id="panel-2" class="tab-panel is-hidden" role="tabpanel" aria-labelledby="tab-2">
<h2>タブ2の内容</h2>
<p>これはタブ2のコンテンツ</p>
</div>
<div id="panel-3" class="tab-panel is-hidden" role="tabpanel" aria-labelledby="tab-3">
<h2>タブ3の内容</h2>
<p>これはタブ3のコンテンツ</p>
</div>
</div>
.tab-panel.is-hidden {
display: none;
}
window.addEventListener("DOMContentLoaded", () => {
const tabInterface = {
tabs: document.querySelectorAll('[role="tab"]'),
tabLists: document.querySelectorAll('[role="tablist"]'),
tabPanels: document.querySelectorAll('[role="tabpanel"]'),
init() {
this.tabs.forEach((tab) => {
tab.addEventListener("click", this.changeTabs.bind(this));
});
this.tabLists.forEach(this.setupKeyboardNavigation.bind(this));
const initialTab = document.querySelector('[aria-selected="true"]');
if (initialTab) {
this.activateTab(initialTab);
}
},
changeTabs(e) {
const target = e.currentTarget; // e.targetからe.currentTargetに変更
this.activateTab(target);
},
activateTab(tab) {
const allTabs = document.querySelectorAll('[role="tab"]');
const allTabPanels = document.querySelectorAll('[role="tabpanel"]');
allTabs.forEach((t) => {
t.setAttribute("aria-selected", "false");
t.setAttribute("tabindex", "-1");
});
tab.setAttribute("aria-selected", "true");
tab.setAttribute("tabindex", "0");
allTabPanels.forEach((p) => p.classList.add("is-hidden"));
const targetPanel = document.getElementById(
tab.getAttribute("aria-controls")
);
if (targetPanel) targetPanel.classList.remove("is-hidden");
},
setupKeyboardNavigation(tabList) {
let tabFocus = 0;
const tabs = tabList.querySelectorAll('[role="tab"]');
tabList.addEventListener("keydown", (e) => {
if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
tabs[tabFocus].setAttribute("tabindex", "-1");
if (e.key === "ArrowLeft") {
tabFocus = (tabFocus - 1 + tabs.length) % tabs.length;
} else {
tabFocus = (tabFocus + 1) % tabs.length;
}
tabs[tabFocus].setAttribute("tabindex", "0");
tabs[tabFocus].focus();
}
});
},
};
tabInterface.init();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment