<template>
<div>
<button type="button">外の要素</button>
<div id="tab">
<div
class="tablist"
aria-label="タブのリスト"
role="tablist">
<button
v-for="(tab, index) in tabs"
type="button"
ref="tab"
role="tab"
:id="`tab-${tab.id}`"
class="tab"
:tabIndex="tab.selected ? '0': '-1'"
:aria-controls="`tabpanel-${tab.id}`"
:aria-selected="tab.selected? 'true': 'false'"
@click="handleOnClick(index)"
@keydown.left="handleOnLeft(index)"
@keydown.right="handleOnRight(index)">
</button>
</div>
<div
v-for="tab in tabs"
role="tabpanel"
:id="`tabpanel-${tab.id}`"
:class="`tabpanel ${tab.selected ? '': 'hidden'}`"
:aria-labelledby="`tab-${tab.id}`"
tabindex="0"
>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
tabs: [
{
id: "tab1",
label: "Tab 1",
selected: true,
tabpanel: "Tab Panel 1",
},
{
id: "tab1",
label: "Tab 2",
selected: false,
tabpanel: "Tab Panel 2",
},
{
id: "tab1",
label: "Tab 3",
selected: false,
tabpanel: "Tab Panel 3",
},
]
};
},
methods: {
handleOnClick(index) {
this.tabs = this.tabs.map((v, vIndex) => ({
v,
selected: vIndex === index
}));
},
handleOnLeft(index) {
let nextIndex = index - 1;
if (index === 0) {
nextIndex = this.tabs.length - 1
}
this.$refs.tab[nextIndex].focus();
},
handleOnRight(index) {
let nextIndex = index + 1;
if (index === this.tabs.length - 1) {
nextIndex = 0
}
this.$refs.tab[nextIndex].focus();
}
}
};
</script>
<style lang="scss">
.tablist {
display: flex;
gap: 4px;
}
button.tab {
width: 200px;
padding: 16px 0;
background: #ddd;
border: solid 4px #ddd;
border-radius: 4px 4px 0 0;
font-size: 24px;
&[aria-selected="true"] {
position: relative;
color: #FF7A00;
font-weight: bold;
background: #fff;
&:before {
position: absolute;
left: 0;
bottom: -4px;
content: "";
width: 100%;
height: 4px;
background: #fff;
}
}
}
.tabpanel {
display: grid;
place-items: center;
height: 300px;
margin-top: -4px;
border: solid 4px #ddd;
border-radius: 0 4px 4px 4px;
&.hidden {
display: none;
}
}
</style>
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.