Files
Website/resources/js/components/SMTabGroup.vue
2023-07-10 16:05:00 +10:00

135 lines
3.3 KiB
Vue

<template>
<div class="tab-group">
<ul class="flex">
<li
v-for="tab in tabs"
:key="tab.id"
:class="[
'p-4',
'-mb-0.2',
'border-1',
'rounded-t-2',
'border-gray',
selectedTab == tab.id
? ['border-b-white']
: [
'border-x-white',
'border-t-white',
'hover:border-x-gray-3',
'hover:border-t-gray-3',
],
]"
@click="selectedTab = tab.id">
{{ tab.label }}
</li>
</ul>
<slot></slot>
</div>
</template>
<script setup lang="ts">
import { provide, ref, useSlots, watch } from "vue";
const props = defineProps({
modelValue: {
type: String,
default: "",
required: false,
},
});
const emits = defineEmits(["tabChanged", "update:modelValue"]);
const slots = useSlots();
const tabs = ref(
slots
.default()
.map((tab) => {
const { label, id, hide } = tab.props;
if (hide !== true) {
return {
label,
id,
};
}
})
.filter(Boolean),
);
const selectedTab = ref(
props.modelValue.length == 0 ? tabs.value[0].id : props.modelValue,
);
if (props.modelValue.length == 0) {
emits("update:modelValue", selectedTab.value);
}
watch(
() => selectedTab.value,
(newValue) => {
emits("tabChanged", newValue);
emits("update:modelValue", newValue);
},
);
watch(
() => props.modelValue,
(newValue) => {
selectedTab.value = newValue;
},
);
provide("selectedTab", selectedTab);
</script>
<style lang="scss">
.tab-group {
margin-bottom: 32px;
.tab-header {
list-style-type: none;
margin: 0;
padding: 0;
border-bottom: 1px solid var(--tab-color-border);
}
.tab-item {
display: inline-block;
padding: 8px 16px;
border: 1px solid transparent;
margin-bottom: -1px;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
color: var(--primary-color);
position: relative;
&.selected {
color: var(--tab-color-text);
background-color: var(--tab-color);
border-top: 1px solid var(--tab-color-border);
border-left: 1px solid var(--tab-color-border);
border-bottom: 1px solid var(--tab-color);
border-right: 1px solid var(--tab-color-border);
&::after {
display: block;
content: "";
position: absolute;
bottom: -2px;
height: 4px;
left: 0px;
right: 0px;
border-bottom: 3px solid var(--tab-color);
pointer-events: none;
}
}
&:hover:not(.selected) {
color: var(--primary-color);
background-color: var(--tab-color-hover);
border-bottom: 1px solid var(--tab-color-border);
}
}
}
</style>