55 lines
No EOL
1.3 KiB
Vue
55 lines
No EOL
1.3 KiB
Vue
<template>
|
|
<div class="h-full relative flex flex-col">
|
|
<nav class="mx-auto p-4 flex gap-4 overflow-x-auto max-w-full">
|
|
<div class="flex-shrink-0 flex items-center rounded-lg bg-dark-400 overflow-hidden">
|
|
<button
|
|
v-for="tab in tabs"
|
|
:key="tab.id"
|
|
class="px-4 py-2 bg-gray-700"
|
|
:class="activeTabId !== tab.id && 'bg-opacity-0'"
|
|
@click="activeTabId = tab.id"
|
|
>
|
|
{{ tab.label }}
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
<main class="flex-grow">
|
|
<transition name="fade" mode="out-in">
|
|
<component
|
|
:is="tabs.find(t => t.id === activeTabId)!.content"
|
|
@switch-screen="(id: string) => (activeTabId = id)"
|
|
/>
|
|
</transition>
|
|
</main>
|
|
</div>
|
|
</template>
|
|
|
|
<style module lang="scss">
|
|
|
|
</style>
|
|
|
|
<script lang="ts">
|
|
import type { Component } from "vue"
|
|
|
|
export interface Tab {
|
|
id: string
|
|
label: string
|
|
content: Component
|
|
}
|
|
</script>
|
|
|
|
<script setup lang="ts">
|
|
import { useVModel } from "@vueuse/core"
|
|
|
|
const props = defineProps<{
|
|
tabs: Tab[]
|
|
activeTabId: string
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
"update:activeTabId": [string]
|
|
[k: `content:${string}`]: [unknown]
|
|
}>()
|
|
|
|
const activeTabId = useVModel(props, "activeTabId", emit)
|
|
</script> |