replace navmenu

This commit is contained in:
pa
2026-01-16 17:11:54 +09:00
committed by Natsumi
parent 9cde6c5bb0
commit 78f3bc512d
9 changed files with 383 additions and 907 deletions

View File

@@ -1,241 +1,210 @@
<template>
<div class="x-menu-container nav-menu-container" :class="{ 'is-collapsed': isCollapsed }">
<template v-if="navLayoutReady">
<div class="nav-menu-body mt-5">
<div v-if="pendingVRCXUpdate || pendingVRCXInstall" class="pending-update">
<Button
variant="ghost"
size="icon"
class="hover:bg-transparent"
style="font-size: 19px; height: 36px; margin: 10px"
@click="showVRCXUpdateDialog">
<span class="relative inline-flex items-center justify-center">
<i class="ri-arrow-down-circle-line text-muted-foreground text-[20px]"></i>
<span class="absolute top-0.5 -right-1 h-1.5 w-1.5 rounded-full bg-red-500"></span>
</span>
<span v-if="!isCollapsed" class="text-[13px] text-muted-foreground">{{
t('nav_menu.update_available')
}}</span>
</Button>
</div>
<Sidebar side="left" variant="sidebar" collapsible="icon">
<SidebarContent class="pt-4">
<div v-if="navLayoutReady" class="px-2">
<SidebarMenu>
<SidebarMenuItem v-if="pendingVRCXUpdate || pendingVRCXInstall">
<SidebarMenuButton
:tooltip="t('nav_menu.update_available')"
variant="default"
@click="showVRCXUpdateDialog">
<span class="relative inline-flex size-6 items-center justify-center">
<i class="ri-arrow-down-circle-line text-muted-foreground text-[20px]"></i>
<span class="absolute top-0.5 -right-1 h-1.5 w-1.5 rounded-full bg-red-500"></span>
</span>
<span v-show="!isCollapsed" class="text-[13px] text-muted-foreground">{{
t('nav_menu.update_available')
}}</span>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</div>
<el-menu ref="navMenuRef" class="nav-menu" :collapse="isCollapsed" :collapse-transition="false">
<template v-for="item in menuItems" :key="item.index">
<el-menu-item
v-if="!item.children?.length"
:index="item.index"
:class="{ notify: isNavItemNotified(item) }"
@click="handleMenuItemClick(item)">
<i :class="item.icon"></i>
<template #title>
<span>{{ item.titleIsCustom ? item.title : t(item.title || '') }}</span>
</template>
</el-menu-item>
<el-sub-menu v-else :index="item.index">
<template #title>
<div :class="{ notify: isNavItemNotified(item) }">
<i :class="item.icon"></i>
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu v-if="navLayoutReady">
<template v-for="item in menuItems" :key="item.index">
<SidebarMenuItem v-if="!item.children?.length">
<SidebarMenuButton
:is-active="activeMenuIndex === item.index"
:tooltip="item.titleIsCustom ? item.title : t(item.title || '')"
:class="isNavItemNotified(item) ? 'notify' : undefined"
@click="handleMenuItemClick(item)">
<i
:class="item.icon"
class="inline-flex size-6 items-center justify-center text-[19px]" />
<span v-show="!isCollapsed">{{
item.titleIsCustom ? item.title : t(item.title || '')
}}</span>
</div>
</template>
<el-menu-item
v-for="entry in item.children"
:key="entry.index"
:index="entry.index"
class="pl-9!"
:class="{ notify: isEntryNotified(entry) }"
@click="handleSubmenuClick(entry, item.index)">
<i v-show="entry.icon" :class="entry.icon"></i>
<template #title>
<span>{{ t(entry.label) }}</span>
</template>
</el-menu-item>
</el-sub-menu>
</template>
</el-menu>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
<div class="nav-menu-container-bottom mb-4">
<el-popover
v-model:visible="supportMenuVisible"
placement="right"
trigger="click"
popper-style="padding:4px;border-radius:8px;"
:offset="-10"
:show-arrow="false"
:width="200"
:hide-after="0">
<div class="nav-menu-support nav-menu-settings">
<div class="nav-menu-support__section">
<button type="button" class="nav-menu-settings__item" @click="showChangeLogDialog">
<span>{{ t('nav_menu.whats_new') }}</span>
</button>
</div>
<Separator />
<div class="nav-menu-support__section">
<span class="nav-menu-support__title">{{ t('nav_menu.resources') }}</span>
<button type="button" class="nav-menu-settings__item" @click="handleSupportLink('wiki')">
<span>{{ t('nav_menu.wiki') }}</span>
</button>
</div>
<Separator />
<div class="nav-menu-support__section">
<span class="nav-menu-support__title">{{ t('nav_menu.get_help') }}</span>
<button type="button" class="nav-menu-settings__item" @click="handleSupportLink('github')">
<span>{{ t('nav_menu.github') }}</span>
</button>
<button type="button" class="nav-menu-settings__item" @click="handleSupportLink('discord')">
<span>{{ t('nav_menu.discord') }}</span>
</button>
</div>
</div>
<template #reference>
<div>
<TooltipWrapper
:delay-duration="150"
:content="t('nav_tooltip.help_support')"
side="right"
:disabled="!isCollapsed">
<div class="bottom-button">
<i class="ri-question-line"></i>
<span v-show="!isCollapsed" class="bottom-button__label">{{
t('nav_tooltip.help_support')
}}</span>
</div>
</TooltipWrapper>
</div>
</template>
</el-popover>
<el-popover
v-model:visible="settingsMenuVisible"
placement="right"
trigger="click"
popper-style="padding:4px;border-radius:8px;"
:offset="6"
:show-arrow="false"
:width="200"
:hide-after="0">
<div class="nav-menu-settings">
<div class="nav-menu-settings__header">
<img class="nav-menu-settings__logo" :src="vrcxLogo" alt="VRCX" @click="openGithub" />
<div class="nav-menu-settings__meta">
<span class="nav-menu-settings__title" @click="openGithub"
>VRCX
<i class="ri-heart-3-fill nav-menu-settings__heart"></i>
</span>
<span class="nav-menu-settings__version">{{ version }}</span>
</div>
</div>
<Separator />
<button type="button" class="nav-menu-settings__item" @click="handleSettingsClick">
<span>{{ t('nav_tooltip.settings') }}</span>
</button>
<button type="button" class="nav-menu-settings__item" @click="handleOpenCustomNavDialog">
<span>{{ t('nav_menu.custom_nav.header') }}</span>
</button>
<el-popover
v-model:visible="themeMenuVisible"
placement="right-start"
trigger="hover"
popper-style="padding:4px;border-radius:8px;"
:offset="8"
:width="200"
:hide-after="0">
<div class="nav-menu-theme">
<button
v-for="theme in themes"
:key="theme"
type="button"
class="nav-menu-theme__item"
:class="{ 'is-active': themeMode === theme }"
@click="handleThemeSelect(theme)">
<span class="nav-menu-theme__label">{{ themeDisplayName(theme) }}</span>
<span v-if="themeMode === theme" class="nav-menu-theme__check"></span>
</button>
<Separator />
<el-popover
v-model:visible="themeColorMenuVisible"
placement="right-start"
trigger="hover"
popper-style="padding:4px;border-radius:8px;"
:offset="8"
:width="200"
:show-arrow="false"
:hide-after="0"
:teleported="false">
<div class="nav-menu-theme nav-menu-theme--colors">
<button
v-for="color in colorFamilies"
:key="color.name"
type="button"
class="nav-menu-theme__item"
:class="{ 'is-active': currentPrimary === color.base }"
:disabled="isApplyingPrimaryColor"
@click="handleThemeColorSelect(color)">
<span class="nav-menu-theme__label nav-menu-theme__label--swatch">
<span
class="nav-menu-theme__swatch"
:style="{ backgroundColor: color.base }"></span>
<span class="nav-menu-theme__label-text">{{ color.name }}</span>
</span>
<span v-if="currentPrimary === color.base" class="nav-menu-theme__check">
</span>
</button>
</div>
<template #reference>
<button type="button" class="nav-menu-theme__item" @click.prevent>
<span class="nav-menu-theme__label">{{
t('view.settings.appearance.theme_color.header')
}}</span>
<span class="nav-menu-settings__arrow"></span>
</button>
<SidebarMenuItem v-else>
<Collapsible
class="group/collapsible"
:default-open="activeMenuIndex && item.children?.some((e) => e.index === activeMenuIndex)">
<template #default="{ open }">
<CollapsibleTrigger as-child>
<SidebarMenuButton
:is-active="item.children?.some((e) => e.index === activeMenuIndex)"
:tooltip="item.titleIsCustom ? item.title : t(item.title || '')"
:class="isNavItemNotified(item) ? 'notify' : undefined">
<i
:class="item.icon"
class="inline-flex size-6 items-center justify-center text-[19px]" />
<span v-show="!isCollapsed">{{
item.titleIsCustom ? item.title : t(item.title || '')
}}</span>
<ChevronRight
v-show="!isCollapsed"
class="ml-auto transition-transform"
:class="open ? 'rotate-90' : ''" />
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
<SidebarMenuSubItem
v-for="entry in item.children"
:key="entry.index">
<SidebarMenuSubButton
:is-active="activeMenuIndex === entry.index"
@click="handleSubmenuClick(entry, item.index)">
<i
v-if="entry.icon"
:class="entry.icon"
class="inline-flex size-5 items-center justify-center text-[16px]" />
<span>{{ t(entry.label) }}</span>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
</SidebarMenuSub>
</CollapsibleContent>
</template>
</el-popover>
</Collapsible>
</SidebarMenuItem>
</template>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter class="p-2">
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<SidebarMenuButton :tooltip="t('nav_tooltip.help_support')">
<i class="ri-question-line inline-flex size-6 items-center justify-center text-[19px]" />
<span v-show="!isCollapsed">{{ t('nav_tooltip.help_support') }}</span>
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent side="right" align="start" class="w-56">
<DropdownMenuItem @click="showChangeLogDialog">
<span>{{ t('nav_menu.whats_new') }}</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>{{ t('nav_menu.resources') }}</DropdownMenuLabel>
<DropdownMenuItem @click="handleSupportLink('wiki')">
<span>{{ t('nav_menu.wiki') }}</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>{{ t('nav_menu.get_help') }}</DropdownMenuLabel>
<DropdownMenuItem @click="handleSupportLink('github')">
<span>{{ t('nav_menu.github') }}</span>
</DropdownMenuItem>
<DropdownMenuItem @click="handleSupportLink('discord')">
<span>{{ t('nav_menu.discord') }}</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<SidebarMenuButton :tooltip="t('nav_tooltip.manage')">
<i class="ri-settings-3-line inline-flex size-6 items-center justify-center text-[19px]" />
<span v-show="!isCollapsed">{{ t('nav_tooltip.manage') }}</span>
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent side="right" align="start" class="w-64">
<div class="flex items-center gap-2 px-2 py-1.5">
<img class="h-6 w-6 cursor-pointer" :src="vrcxLogo" alt="VRCX" @click="openGithub" />
<div class="flex min-w-0 flex-col">
<button
type="button"
class="text-left text-sm font-medium truncate"
@click="openGithub">
VRCX
</button>
<span class="text-xs text-muted-foreground">{{ version }}</span>
</div>
</div>
<template #reference>
<button type="button" class="nav-menu-settings__item" @click.prevent>
<DropdownMenuSeparator />
<DropdownMenuItem @click="handleSettingsClick">
<span>{{ t('nav_tooltip.settings') }}</span>
</DropdownMenuItem>
<DropdownMenuItem @click="handleOpenCustomNavDialog">
<span>{{ t('nav_menu.custom_nav.header') }}</span>
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<span>{{ t('view.settings.appearance.appearance.theme_mode') }}</span>
<span class="nav-menu-settings__arrow"></span>
</button>
</template>
</el-popover>
<button
type="button"
class="nav-menu-settings__item nav-menu-settings__item--danger"
@click="handleLogoutClick">
<span>{{ t('dialog.user.actions.logout') }}</span>
</button>
</div>
<template #reference>
<div class="bottom-button">
<i class="ri-settings-3-line"></i>
<span v-show="!isCollapsed" class="bottom-button__label">{{
t('nav_tooltip.manage')
}}</span>
</div>
</template>
</el-popover>
<TooltipWrapper
:delay-duration="150"
:content="t('nav_tooltip.expand_menu')"
:disabled="!isCollapsed"
side="right">
<div class="bottom-button" @click="toggleNavCollapse">
<i class="ri-side-bar-line"></i>
<span v-show="!isCollapsed" class="bottom-button__label">{{
t('nav_tooltip.collapse_menu')
}}</span>
</div>
</TooltipWrapper>
</div>
</template>
</div>
</DropdownMenuSubTrigger>
<DropdownMenuSubContent side="right" align="start" class="w-72">
<DropdownMenuItem
v-for="theme in themes"
:key="theme"
:class="themeMode === theme ? 'font-medium' : undefined"
@click="handleThemeSelect(theme)">
<span class="flex-1">{{ themeDisplayName(theme) }}</span>
<span v-if="themeMode === theme" class="text-muted-foreground">✓</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<span>{{ t('view.settings.appearance.theme_color.header') }}</span>
</DropdownMenuSubTrigger>
<DropdownMenuSubContent side="right" align="start" class="w-72 max-h-80 overflow-auto">
<DropdownMenuItem
v-for="color in colorFamilies"
:key="color.name"
:disabled="isApplyingPrimaryColor"
@click="handleThemeColorSelect(color)">
<span class="flex items-center gap-2 min-w-0 flex-1">
<span class="h-3 w-3 shrink-0 rounded-sm" :style="{ backgroundColor: color.base }" />
<span class="truncate">{{ color.name }}</span>
</span>
<span v-if="currentPrimary === color.base" class="text-muted-foreground">✓</span>
</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive" @click="handleLogoutClick">
<span>{{ t('dialog.user.actions.logout') }}</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
:tooltip="isCollapsed ? t('nav_tooltip.expand_menu') : t('nav_tooltip.collapse_menu')"
@click="toggleNavCollapse">
<i class="ri-side-bar-line inline-flex size-6 items-center justify-center text-[19px]" />
<span v-show="!isCollapsed">{{ t('nav_tooltip.collapse_menu') }}</span>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
<SidebarRail />
</Sidebar>
<CustomNavDialog
v-model:visible="customNavDialogVisible"
:layout="navLayout"
@@ -244,15 +213,41 @@
</template>
<script setup>
import { computed, defineAsyncComponent, onMounted, ref, watch } from 'vue';
import { ElMenu, ElMenuItem, ElPopover, ElSubMenu } from 'element-plus';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
import { dayjs } from 'element-plus';
import { computed, defineAsyncComponent, onMounted, ref } from 'vue';
import dayjs from 'dayjs';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import { ChevronRight } from 'lucide-vue-next';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu';
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarRail
} from '@/components/ui/sidebar';
import {
useAppearanceSettingsStore,
useAuthStore,
@@ -314,11 +309,6 @@
const { logout } = useAuthStore();
const appearanceSettingsStore = useAppearanceSettingsStore();
const { themeMode, isNavCollapsed: isCollapsed } = storeToRefs(appearanceSettingsStore);
const settingsMenuVisible = ref(false);
const themeMenuVisible = ref(false);
const themeColorMenuVisible = ref(false);
const supportMenuVisible = ref(false);
const navMenuRef = ref(null);
const navLayout = ref([]);
const navLayoutReady = ref(false);
@@ -407,16 +397,6 @@
selectPaletteColor
} = useThemePrimaryColor();
watch(
() => activeMenuIndex.value,
(value) => {
if (value) {
navMenuRef.value?.updateActiveIndex(value);
}
},
{ immediate: true }
);
watch(
() => locale.value,
() => {
@@ -504,28 +484,19 @@
};
const handleSettingsClick = () => {
themeMenuVisible.value = false;
supportMenuVisible.value = false;
settingsMenuVisible.value = false;
router.push({ name: 'settings' });
};
const handleLogoutClick = () => {
settingsMenuVisible.value = false;
logout();
};
const handleThemeSelect = (theme) => {
themeMenuVisible.value = false;
settingsMenuVisible.value = false;
appearanceSettingsStore.setThemeMode(theme);
};
const handleThemeColorSelect = async (colorFamily) => {
await selectPaletteColor(colorFamily);
themeColorMenuVisible.value = false;
themeMenuVisible.value = false;
settingsMenuVisible.value = false;
};
const openGithub = () => {
@@ -548,9 +519,6 @@
};
const handleOpenCustomNavDialog = () => {
themeMenuVisible.value = false;
supportMenuVisible.value = false;
settingsMenuVisible.value = false;
customNavDialogVisible.value = true;
};
@@ -602,7 +570,6 @@
};
const handleSupportLink = (id) => {
supportMenuVisible.value = false;
const target = links[id];
if (target) {
openExternalLink(target);
@@ -639,39 +606,23 @@
return false;
};
const closeNavFlyouts = () => {
settingsMenuVisible.value = false;
supportMenuVisible.value = false;
themeMenuVisible.value = false;
themeColorMenuVisible.value = false;
};
const triggerNavAction = (entry, navIndex = entry?.index) => {
if (!entry) {
return;
}
if (entry.action === 'direct-access') {
closeNavFlyouts();
directAccessPaste();
if (navIndex) {
navMenuRef.value?.updateActiveIndex(navIndex);
}
return;
}
if (entry.routeName) {
handleRouteChange(entry.routeName, navIndex);
closeNavFlyouts();
return;
}
if (entry.path) {
router.push(entry.path);
if (navIndex) {
navMenuRef.value?.updateActiveIndex(navIndex);
}
closeNavFlyouts();
}
};
@@ -680,26 +631,8 @@
return;
}
router.push({ name: routeName });
if (navIndex) {
navMenuRef.value?.updateActiveIndex(navIndex);
}
};
watch(settingsMenuVisible, (visible) => {
if (visible) {
supportMenuVisible.value = false;
} else {
themeMenuVisible.value = false;
themeColorMenuVisible.value = false;
}
});
watch(supportMenuVisible, (visible) => {
if (visible) {
settingsMenuVisible.value = false;
}
});
function getFirstNavRoute(layout) {
for (const entry of layout) {
if (entry.type === 'item') {
@@ -759,261 +692,6 @@
min-width: 64px;
height: 100%;
display: flex;
flex: 1 1 auto;
flex-direction: column;
align-items: stretch;
justify-content: flex-start;
background-color: var(--el-bg-color-page);
box-shadow: none;
backdrop-filter: blur(14px) saturate(130%);
}
.nav-menu-body {
display: flex;
flex-direction: column;
flex: 1;
overflow: hidden auto;
align-items: center;
}
.nav-menu {
background: transparent;
border: 0;
width: 100%;
}
.nav-menu :deep(.el-menu-item),
.nav-menu :deep(.el-sub-menu__title) {
height: 46px;
line-height: 46px;
display: flex;
align-items: center;
column-gap: 10px;
font-size: 13px;
padding: 0 20px !important;
}
.nav-menu :deep(.el-menu-item i[class*='ri-']),
.nav-menu :deep(.el-sub-menu__title i[class*='ri-']) {
font-size: 19px;
width: 24px;
height: 24px;
display: inline-flex;
align-items: center;
justify-content: center;
text-align: center;
vertical-align: middle;
line-height: 1;
flex-shrink: 0;
}
.nav-menu :deep(.el-sub-menu__title > div) {
display: inline-flex;
align-items: center;
gap: 10px;
}
.nav-menu :deep(.el-sub-menu__icon-arrow) {
right: 8px;
}
.bottom-button {
font-size: 19px;
width: 100%;
height: 46px;
display: inline-flex;
align-items: center;
justify-content: flex-start;
gap: 10px;
padding: 0 20px;
text-align: left;
vertical-align: middle;
cursor: pointer;
box-sizing: border-box;
& > span {
font-size: 13px;
}
}
.bottom-button i {
width: 24px;
height: 24px;
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 1;
}
.bottom-button__label {
font-size: 13px;
color: var(--el-text-color-regular);
white-space: nowrap;
}
.bottom-button:hover {
background-color: var(--el-menu-hover-bg-color);
transition:
border-color var(--el-transition-duration),
background-color var(--el-transition-duration),
color var(--el-transition-duration);
}
.nav-menu-container-bottom {
display: flex;
flex-direction: column;
}
.nav-menu-container.is-collapsed .nav-menu :deep(.el-menu-item),
.nav-menu-container.is-collapsed .nav-menu :deep(.el-sub-menu__title) {
column-gap: 0;
justify-content: center;
padding: 0;
}
.nav-menu-container.is-collapsed {
width: 100%;
}
.nav-menu-container.is-collapsed .nav-menu :deep(.el-sub-menu__title > div) {
gap: 0;
}
.nav-menu-container.is-collapsed .bottom-button {
width: 100%;
justify-content: center;
gap: 0;
padding: 0;
text-align: center;
}
:deep(.el-menu-item .el-menu-tooltip__trigger) {
justify-content: center;
}
:deep(.el-button.is-text:not(.is-disabled):hover) {
background-color: var(--el-menu-hover-bg-color);
}
.nav-menu-settings {
display: flex;
flex-direction: column;
gap: 2px;
.nav-menu-settings__header {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 8px 10px;
.nav-menu-settings__logo {
width: 24px;
height: 24px;
object-fit: contain;
cursor: pointer;
}
.nav-menu-settings__meta {
display: flex;
flex-direction: column;
gap: 2px;
color: var(--el-text-color-secondary);
font-size: 12px;
line-height: 1.2;
}
.nav-menu-settings__title {
display: flex;
align-items: center;
font-weight: 600;
font-size: 14px;
color: var(--el-text-color-regular);
cursor: pointer;
}
.nav-menu-settings__heart {
font-size: 14px;
color: var(--el-color-success);
}
.nav-menu-settings__version {
font-size: 11px;
}
}
.nav-menu-settings__item {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 8px 12px;
width: 100%;
border: none;
background: transparent;
color: var(--el-text-color-regular);
font-size: 13px;
border-radius: 4px;
transition: background-color var(--el-transition-duration);
cursor: pointer;
.nav-menu-settings__arrow {
margin-left: auto;
color: var(--el-text-color-secondary);
font-size: 12px;
}
}
.nav-menu-settings__item:hover {
background-color: var(--el-menu-hover-bg-color);
}
.nav-menu-settings__item--danger {
color: var(--el-color-danger);
}
.nav-menu-settings__item--danger:hover {
background-color: color-mix(in oklch, var(--el-color-danger) 18%, transparent);
}
}
.nav-menu-support {
display: flex;
flex-direction: column;
gap: 8px;
.nav-menu-support__section {
display: flex;
flex-direction: column;
gap: 4px;
}
.nav-menu-support__title {
padding: 0 12px;
font-size: 11px;
font-weight: 600;
color: var(--el-text-color-secondary);
text-transform: uppercase;
letter-spacing: 0.4px;
}
}
.nav-menu-theme {
display: flex;
flex-direction: column;
gap: 2px;
.nav-menu-theme__item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px 10px;
border: none;
background: transparent;
font-size: 13px;
border-radius: 6px;
transition: background-color var(--el-transition-duration);
cursor: pointer;
.nav-menu-theme__check {
font-size: 12px;
color: var(--el-color-primary);
margin-left: 10px;
}
}
.nav-menu-theme__item:hover,
.nav-menu-theme__item.is-active {
background-color: var(--el-menu-hover-bg-color);
}
.nav-menu-theme__label--swatch {
display: inline-flex;