JSFiddle - React, Tailwind, and code Playground
by seulbiLee
HTML
<div class="wrap-tab-container" data-role="tab">
<ul class="wrap-tab-list" role="tablist">
<li class="tab-list active">
<button id="tab-01" class="tab-button" role="tab" aria-selected="true" aria-controls="tab-panel-01">tablist 01</button>
</li>
<li class="tab-list">
<button id="tab-02" class="tab-button" role="tab" aria-selected="false" aria-controls="tab-panel-02" tabindex="-1">tablist 02</button>
</li>
<li class="tab-list">
<button id="tab-03" class="tab-button" role="tab" aria-selected="false" aria-controls="tab-panel-03" tabindex="-1">tablist 03</button>
</li>
</ul>
<div class="wrap-tab-contents">
<div id="tab-panel-01" class="tab-contents" role="tabpanel" aria-labelledby="tab-01" tabindex="0">
<p>tab contents 01</p>
<div class="wrap-tab-container" data-role="tab">
<ul class="wrap-tab-list" role="tablist">
<li class="tab-list active">
<button id="tab-01-01" class="tab-button" role="tab" aria-selected="true" aria-controls="tab-panel-01-01">tablist 01</button>
</li>
<li class="tab-list">
<button id="tab-02-01" class="tab-button" role="tab" aria-selected="false" aria-controls="tab-panel-02-01" tabindex="-1">tablist 02</button>
</li>
<li class="tab-list">
<button id="tab-03-01" class="tab-button" role="tab" aria-selected="false" aria-controls="tab-panel-03-01" tabindex="-1">tablist 03</button>
</li>
</ul>
<div class="wrap-tab-contents">
<div id="tab-panel-01-01" class="tab-contents" role="tabpanel" aria-labelledby="tab-01-01" tabindex="0">
<p>tab contents 01</p>
</div>
<div id="tab-panel-02-01" class="tab-contents" role="tabpanel" aria-labelledby="tab-02-01" tabindex="0" hidden="true">
<p>tab contents 02</p>
</div>
<div id="tab-panel-03-01" class="tab-contents" role="tabpanel" aria-labelledby="tab-03-01"...
SCSS
ul, li {
list-style: none;
padding: 0;
margin: 0;
}
button {cursor: pointer;}
.wrap-tab-list {
position: relative;
z-index: 0;
font-size: 0;
line-height: 0;
.tab-list {
& + .tab-list {
margin-left: -1px;
}
&.active {
border-color: orange;
border-bottom: 1px solid #fff;
z-index: 10;
.tab-button {
font-weight: bold;
}
}
display: inline-block;
position: relative;
z-index: 0;
border: 1px solid #ccc;
border-bottom: 0;
.tab-button {
display: block;
height: 40px;
padding: 0 10px;
font-size: 16px;
border: 0;
background-color: #fff;
}
}
}
.wrap-tab-contents {
max-width: 500px;
width: 100%;
border: 1px solid orange;
margin-top: -1px;
.tab-contents {
width: 100%;
padding: 10px;
box-sizing: border-box;
}
}
.wrap-tab-container {
& + .wrap-tab-container {
margin-top: 30px;
}
}
JavaScript
const tabGroups = document.querySelectorAll('[data-role="tab"]');
if (tabGroups) {
let currentTarget, targetTabWrap, targetTabListWrap, targetPanelWrap;
// 이벤트 타겟 변수 설정
const init = (e) => {
currentTarget = e.target.tagName;
currentTarget === 'BUTTON' || 'A' ? currentTarget = e.target : currentTarget = e.target.closest('button') || e.target.closest('a');
targetTabWrap = currentTarget.closest('[data-role="tab"]');
targetTabListWrap = targetTabWrap.querySelector('[role="tablist"]');
targetPanelWrap = targetTabWrap.querySelector('.wrap-tab-contents');
};
// 클릭 이벤트
const tabClickEvt = (e) => {
init(e);
if (currentTarget.ariaSelected === 'false') {
// 미선택된 탭 속성 false 상태로 만들기
tabRemoveEvt(targetTabListWrap, targetPanelWrap);
// 선택 된 탭 속성 true 상태로 만들기
tabAddEvt(currentTarget, targetTabWrap);
};
};
// 키보드 접근 이벤트
const tabKeyUpEvt = (e) => {
init(e);
const targetBtnWrap = currentTarget.parentElement;
if (e.key == 'ArrowRight') {
// 키보드 -> 화살표를 눌렀을 때
if (targetBtnWrap.nextElementSibling) {
targetBtnWrap.nextElementSibling.children[0].focus();
tabRemoveEvt(targetTabListWrap, targetPanelWrap);
tabAddEvt(targetBtnWrap.nextElementSibling.children[0], targetTabWrap);
}
else homeKeyEvt(targetTabListWrap, targetTabWrap, targetPanelWrap);
} else if (e.key == 'ArrowLeft') {
// 키보드 <- 화살표를 눌렀을 때
if (targetBtnWrap.previousElementSibling) {
targetBtnWrap.previousElementSibling.children[0].focus();
tabRemoveEvt(targetTabListWrap, targetPanelWrap);
tabAddEvt(targetBtnWrap.previousElementSibling.children[0], targetTabWrap);
} else endKeyEvt(targetTabListWrap, targetTabWrap, targetPanelWrap);
}
// 키보드 End 키 눌렀을 때
else if (e.key == 'End') endKeyEvt(targetTabListWrap, targetTabWrap, targetPanelWrap);
// 키보드 Home 키 눌렀을 때
else if (e.key == 'Home') homeKeyEvt(targetTabListWrap, targetTabWrap,...