feat: add logout menu to navbar

This commit is contained in:
shake 2026-06-22 16:09:09 +08:00
parent 59a70ebfa0
commit 651410e2b6
5 changed files with 161 additions and 42 deletions

View file

@ -27,6 +27,9 @@ home:
darkMode: 'Dark mode'
lightMode: 'Light mode'
mode: 'Toggle dark/light mode'
more: 'More'
themeTitle: 'Theme switch'
logout: 'Logout'
about:
content: >
# About IT-Tools

View file

@ -27,6 +27,9 @@ home:
darkMode: '深色模式'
lightMode: '浅色模式'
mode: '颜色模式'
more: '更多'
themeTitle: '主题切换'
logout: '退出'
about:
content: >
# 关于 IT-Tools

View file

@ -1,9 +1,5 @@
<script setup lang="ts">
import { IconBrandGithub, IconBrandX, IconInfoCircle, IconMoon, IconSun } from '@tabler/icons-vue';
import { useStyleStore } from '@/stores/style.store';
const styleStore = useStyleStore();
const { isDarkTheme } = toRefs(styleStore);
import { IconBrandGithub, IconBrandX, IconInfoCircle } from '@tabler/icons-vue';
</script>
<template>
@ -38,12 +34,6 @@ const { isDarkTheme } = toRefs(styleStore);
<n-icon size="25" :component="IconInfoCircle" />
</c-button>
</c-tooltip>
<c-tooltip :tooltip="isDarkTheme ? $t('home.nav.lightMode') : $t('home.nav.darkMode')" position="bottom">
<c-button circle variant="text" :aria-label="$t('home.nav.mode')" @click="() => styleStore.toggleDark()">
<n-icon v-if="isDarkTheme" size="25" :component="IconSun" />
<n-icon v-else size="25" :component="IconMoon" />
</c-button>
</c-tooltip>
</template>
<style lang="less" scoped>

View file

@ -0,0 +1,151 @@
<script setup lang="ts">
import { useThemeVars } from 'naive-ui';
import { storeToRefs } from 'pinia';
import { IconDotsVertical, IconLogout, IconMoon, IconSun } from '@tabler/icons-vue';
import { useStyleStore } from '@/stores/style.store';
const styleStore = useStyleStore();
const { isDarkTheme } = storeToRefs(styleStore);
const theme = useThemeVars();
const isOpen = ref(false);
const menuRef = ref<HTMLElement | null>(null);
function closeMenu() {
isOpen.value = false;
}
function toggleMenu() {
isOpen.value = !isOpen.value;
}
function setLightTheme() {
if (isDarkTheme.value) {
styleStore.toggleDark();
}
closeMenu();
}
function setDarkTheme() {
if (!isDarkTheme.value) {
styleStore.toggleDark();
}
closeMenu();
}
function logout() {
window.location.assign(new URL('/cdn-cgi/access/logout', window.location.origin).toString());
}
onClickOutside(menuRef, closeMenu);
</script>
<template>
<div ref="menuRef" class="navbar-more-menu" relative>
<c-tooltip :tooltip="$t('home.nav.more')" position="bottom">
<c-button
circle
variant="text"
:aria-label="$t('home.nav.more')"
@click="toggleMenu"
>
<n-icon size="25" :component="IconDotsVertical" />
</c-button>
</c-tooltip>
<transition name="fade">
<div v-if="isOpen" class="menu-panel">
<div class="menu-title">
{{ $t('home.nav.themeTitle') }}
</div>
<button class="menu-option" :class="{ active: !isDarkTheme }" type="button" @click="setLightTheme">
<n-icon size="20" :component="IconSun" />
<span>{{ $t('home.nav.lightMode') }}</span>
</button>
<button class="menu-option" :class="{ active: isDarkTheme }" type="button" @click="setDarkTheme">
<n-icon size="20" :component="IconMoon" />
<span>{{ $t('home.nav.darkMode') }}</span>
</button>
<div class="divider" />
<button class="menu-option logout" type="button" @click="logout">
<n-icon size="20" :component="IconLogout" />
<span>{{ $t('home.nav.logout') }}</span>
</button>
</div>
</transition>
</div>
</template>
<style lang="less" scoped>
.navbar-more-menu {
position: relative;
}
.menu-panel {
position: absolute;
top: calc(100% + 12px);
right: 0;
z-index: 30;
min-width: 220px;
padding: 18px 12px 14px;
border-radius: 28px;
background: v-bind('theme.bodyColor');
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18);
border: 1px solid rgba(127, 127, 127, 0.14);
}
.menu-title {
color: rgba(127, 127, 127, 0.95);
font-size: 18px;
font-weight: 600;
padding: 0 12px 10px;
}
.menu-option {
width: 100%;
display: flex;
align-items: center;
gap: 10px;
border: 0;
border-radius: 18px;
background: transparent;
color: inherit;
font-size: 20px;
font-weight: 600;
text-align: left;
padding: 14px 12px;
cursor: pointer;
&:hover,
&.active {
background: rgba(255, 217, 102, 0.18);
}
}
.logout {
color: #d9480f;
}
.divider {
height: 1px;
margin: 10px 8px 8px;
background: rgba(127, 127, 127, 0.18);
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.15s ease, transform 0.15s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateY(-6px);
}
</style>

View file

@ -2,17 +2,17 @@
import { NIcon, useThemeVars } from 'naive-ui';
import { RouterLink } from 'vue-router';
import { Heart, Home2, Menu2 } from '@vicons/tabler';
import { Home2, Menu2 } from '@vicons/tabler';
import { storeToRefs } from 'pinia';
import HeroGradient from '../assets/hero-gradient.svg?component';
import MenuLayout from '../components/MenuLayout.vue';
import NavbarButtons from '../components/NavbarButtons.vue';
import NavbarMoreMenu from '../components/NavbarMoreMenu.vue';
import { useStyleStore } from '@/stores/style.store';
import { config } from '@/config';
import type { ToolCategory } from '@/tools/tools.types';
import { useToolStore } from '@/tools/tools.store';
import { useTracker } from '@/modules/tracker/tracker.services';
import CollapsibleToolMenu from '@/components/CollapsibleToolMenu.vue';
const themeVars = useThemeVars();
@ -20,7 +20,6 @@ const styleStore = useStyleStore();
const version = config.app.version;
const commitSha = config.app.lastCommitSha.slice(0, 7);
const { tracker } = useTracker();
const { t } = useI18n();
const toolStore = useToolStore();
@ -119,21 +118,7 @@ const tools = computed<ToolCategory[]>(() => [
<div>
<NavbarButtons v-if="!styleStore.isSmallScreen" />
</div>
<c-tooltip position="bottom" :tooltip="$t('home.support')">
<c-button
round
href="https://www.buymeacoffee.com/cthmsst"
rel="noopener"
target="_blank"
class="support-button"
:bordered="false"
@click="() => tracker.trackEvent({ eventName: 'Support button clicked' })"
>
{{ $t('home.buyMeACoffee') }}
<NIcon v-if="!styleStore.isSmallScreen" :component="Heart" ml-2 />
</c-button>
</c-tooltip>
<NavbarMoreMenu />
</div>
<slot />
</template>
@ -152,19 +137,6 @@ const tools = computed<ToolCategory[]>(() => [
// background-size: @size @size;
// }
.support-button {
background: rgb(37, 99, 108);
background: linear-gradient(48deg, rgba(37, 99, 108, 1) 0%, rgba(59, 149, 111, 1) 60%, rgba(20, 160, 88, 1) 100%);
color: #fff !important;
transition: padding ease 0.2s !important;
&:hover {
color: #fff;
padding-left: 30px;
padding-right: 30px;
}
}
.footer {
text-align: center;
color: #838587;