This commit is contained in:
2026-10-14 23:39:17 +07:00
parent 1218f1112c
commit 414513803c
18 changed files with 2285 additions and 2 deletions
+93
View File
@@ -0,0 +1,93 @@
<script setup lang="ts">
import { darkTheme, NButton, NConfigProvider } from 'naive-ui'
import { nextTick, ref } from 'vue'
import ComponentDesignCatalog from '@/components/ComponentDesignCatalog.vue'
import GameDesignPreview from '@/components/GameDesignPreview.vue'
import SiteDesignPreview from '@/components/SiteDesignPreview.vue'
const tabs = [
{ name: 'site', label: 'Сайт' },
{ name: 'game', label: 'Игра' },
{ name: 'components', label: 'Компоненты' },
] as const
const activeTab = ref<(typeof tabs)[number]['name']>('site')
const tabList = ref<HTMLElement | null>(null)
async function handleTabKey(event: KeyboardEvent) {
if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return
event.preventDefault()
const index = tabs.findIndex((tab) => tab.name === activeTab.value)
const nextIndex =
event.key === 'Home'
? 0
: event.key === 'End'
? tabs.length - 1
: (index + (event.key === 'ArrowRight' ? 1 : -1) + tabs.length) % tabs.length
activeTab.value = tabs[nextIndex]!.name
await nextTick()
tabList.value?.querySelector<HTMLButtonElement>('[aria-selected="true"]')?.focus()
}
</script>
<template>
<n-config-provider :theme="darkTheme">
<header class="design-header">Вечерний детектив · Дизайн-система</header>
<main class="center-block-custom design-scroll">
<div
ref="tabList"
class="design-tabs"
role="tablist"
aria-label="Стили оформления"
@keydown="handleTabKey"
>
<n-button
v-for="tab in tabs"
:id="`tab-${tab.name}`"
:key="tab.name"
role="tab"
:aria-selected="activeTab === tab.name"
:aria-controls="`panel-${tab.name}`"
:tabindex="activeTab === tab.name ? 0 : -1"
:type="activeTab === tab.name ? 'primary' : 'default'"
@click="activeTab = tab.name"
>{{ tab.label }}</n-button
>
</div>
<div
:id="`panel-${activeTab}`"
role="tabpanel"
:aria-labelledby="`tab-${activeTab}`"
tabindex="0"
>
<SiteDesignPreview v-if="activeTab === 'site'" />
<GameDesignPreview v-else-if="activeTab === 'game'" />
<ComponentDesignCatalog v-else />
</div>
</main>
</n-config-provider>
</template>
<style scoped>
.design-header {
align-items: center;
background: var(--brand-background);
color: var(--brand-text);
display: flex;
font-size: 16px;
height: 70px;
left: 0;
padding: 0 16px;
position: fixed;
right: 0;
top: 0;
}
.design-scroll {
background: var(--brand-background);
}
.design-tabs {
display: flex;
gap: 12px;
padding: 16px;
}
</style>