Skip to content

Commit

Permalink
优化下拉框的用户体验 (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
admin8756 authored Apr 26, 2024
1 parent 7311db1 commit 2075090
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 141 deletions.
1 change: 1 addition & 0 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export {}

declare module 'vue' {
export interface GlobalComponents {
DropdownView: typeof import('./components/DropdownView.vue')['default']
MessageBox: typeof import('./components/MsgBox/MessageBox.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Expand Down
34 changes: 34 additions & 0 deletions src/components/DropdownView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 下拉菜单
<script setup>
import { computed } from "vue";
const props = defineProps({
// 下拉的列表
list: {
type: Array,
default: () => [],
},
// 标题
title: { type: String, default: "" },
// 弹框的位置
position: { type: String, default: "end" },
// 打开方式
openType: { type: String, default: "click" },
});
// 计算属性
const hover = computed(() => props.openType === "hover");
</script>
<template>
<!-- <div class="dropdown dropdown-end" :class="{ 'dropdown-open': show }" @click="tabState"> -->
<div class="dropdown dropdown-end" :class="{ 'dropdown-hover': hover }">
<slot name="title" tabindex="0"></slot>
<div v-if="title" tabindex="0" role="button" class="btn m-1">{{ title }}</div>
<ul
tabindex="0"
class="dropdown-content bg-base-200 text-base-content rounded-box top-px mt-16 max-h-[calc(100vh-10rem)] w-56 overflow-y-auto border border-white/5 shadow-2xl outline outline-1 outline-black/5 menu menu-sm gap-1"
>
<li v-for="(item, index) in list" :key="index">
<slot :item="item"></slot>
</li>
</ul>
</div>
</template>
52 changes: 38 additions & 14 deletions src/layouts/components/navbar/NavBar.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script setup>
import { name } from '../../../../package.json';
import router, { routesList } from '@/router/index.js';
import { name } from "../../../../package.json";
import router, { routesList } from "@/router/index.js";
import LanguageBtn from './modules/LanguageBtn.vue';
import ThemeBtn from './modules/ThemeBtn.vue';
import MineBtn from './modules/MineBtn.vue';
import LanguageBtn from "./modules/LanguageBtn.vue";
import ThemeBtn from "./modules/ThemeBtn.vue";
import MineBtn from "./modules/MineBtn.vue";
// 设置语言
Expand All @@ -26,12 +26,30 @@ const pageTo = (to) => {
<div class="navbar-start">
<div class="dropdown">
<div tabindex="0" role="button" class="btn btn-ghost lg:hidden">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h8m-8 6h16" />
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h8m-8 6h16"
/>
</svg>
</div>
<ul tabindex="0" class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow bg-base-100 rounded-box w-52">
<li v-for="(item, index) in routesList" :key="index" :class="isActive(item.path) ? 'active' : ''">
<ul
tabindex="0"
class="dropdown-content menu menu-sm mt-3 z-[1] p-2 shadow bg-base-100 rounded-box w-52"
>
<li
v-for="(item, index) in routesList"
:key="index"
:class="isActive(item.path) ? 'active' : ''"
>
<a @click="pageTo(item.path || '/')">{{ item.meta.title }}</a>
<ul class="p-2">
<li v-for="(subItem, subIndex) in item.children" :key="subIndex">
Expand All @@ -46,12 +64,18 @@ const pageTo = (to) => {
<!-- pc端布局 -->
<div class="navbar-center hidden lg:flex">
<ul class="menu menu-horizontal px-1">
<li v-for="(item, index) in routesList" :key="index" :class="isActive(item.path) ? 'active' : ''">
<a @click="pageTo(item.path || '/')" v-if="!item.children">{{ item.meta.title }}</a>
<li
v-for="(item, index) in routesList"
:key="index"
:class="isActive(item.path) ? 'active' : ''"
>
<a @click="pageTo(item.path || '/')" v-if="!item.children">{{
item.meta.title
}}</a>
<details v-else>
<summary tabindex="0">{{ item.meta.title }}</summary>
<ul class="p-2 w-40">
<li tabindex="0" v-for="(subItem, subIndex) in item.children" :key="subIndex">
<summary tabindex="0" role="button">{{ item.meta.title }}</summary>
<ul tabindex="0" class="p-2 w-40">
<li v-for="(subItem, subIndex) in item.children" :key="subIndex">
<a @click="pageTo(subItem.path || '/')">{{ subItem.meta.title }}</a>
</li>
</ul>
Expand Down
52 changes: 24 additions & 28 deletions src/layouts/components/navbar/modules/LanguageBtn.vue
Original file line number Diff line number Diff line change
@@ -1,42 +1,38 @@
<script setup>
import { useI18n } from 'vue-i18n';
import { useI18n } from "vue-i18n";
import DropdownView from "@/components/DropdownView.vue";
const { t, locale } = useI18n();
const locList = [
{
code: 'EN',
lang: 'English',
loc: 'en',
code: "EN",
lang: "English",
loc: "en",
},
{
code: 'ZH',
lang: '中文',
loc: 'zh-CN',
code: "ZH",
lang: "中文",
loc: "zh-CN",
},
];
const setLanguage = (lang) => {
locale.value = lang;
};
</script>
<template>
<div class="dropdown dropdown-end">
<div tabindex="0" role="button" class="btn m-1">{{ t('nav-bar.tab-lang') }}</div>
<div
tabindex="0"
class="dropdown-content bg-base-200 text-base-content rounded-box top-px mt-16 max-h-[calc(100vh-10rem)] w-56 overflow-y-auto border border-white/5 shadow-2xl outline outline-1 outline-black/5"
>
<ul class="menu menu-sm gap-1">
<li v-for="(item, index) in locList" :key="index">
<button class="btn glass flex justify-between w-full" @click="setLanguage(item.loc)">
<span
class="badge badge-sm badge-outline !pl-1.5 !pr-1 pt-px font-mono !text-[.6rem] font-bold tracking-widest opacity-50"
:class="{ 'badge-primary': item.loc === locale }"
>
{{ item.code }}
</span>
<span class="font-[sans-serif]">{{ item.lang }}</span>
</button>
</li>
</ul>
</div>
</div>
<DropdownView :list="locList" :title="t('nav-bar.tab-lang')">
<template #default="{ item }">
<button
class="btn glass flex justify-between w-full"
@click="setLanguage(item.loc)"
>
<span
class="badge badge-sm badge-outline !pl-1.5 !pr-1 pt-px font-mono !text-[.6rem] font-bold tracking-widest opacity-50"
:class="{ 'badge-primary': item.loc === locale }"
>
{{ item.code }}
</span>
<span class="font-[sans-serif]">{{ item.lang }}</span>
</button>
</template>
</DropdownView>
</template>
120 changes: 56 additions & 64 deletions src/layouts/components/navbar/modules/ThemeBtn.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script setup>
import { THEME_LIST, THEME_DEFAULT } from '../../../../../enums/theme.js';
import { themeChange } from 'theme-change';
import { useI18n } from 'vue-i18n';
import { ref } from 'vue';
import { THEME_LIST, THEME_DEFAULT } from "../../../../../enums/theme.js";
import { themeChange } from "theme-change";
import { useI18n } from "vue-i18n";
import { ref } from "vue";
import DropdownView from "@/components/DropdownView.vue";
const { t } = useI18n();
// 传入主题名,返回style对象
const getThemeStyle = (themeName) => {
Expand All @@ -12,9 +12,9 @@ const getThemeStyle = (themeName) => {
return {};
} else {
return {
background: themeDetail['base-100'],
color: themeDetail['color-scheme'] === 'light' ? '#000' : '#fff',
borderRadius: themeDetail['--rounded-btn'] || '0px',
background: themeDetail["base-100"],
color: themeDetail["color-scheme"] === "light" ? "#000" : "#fff",
borderRadius: themeDetail["--rounded-btn"] || "0px",
};
}
};
Expand All @@ -29,67 +29,59 @@ const getThemeColor = (themeName) => {
}
};
// 获取当前主题
const nowTheme = ref(localStorage.getItem('theme') || 'light');
const nowTheme = ref(localStorage.getItem("theme") || "light");
const saveTheme = (themeName) => {
themeChange(themeName);
nowTheme.value = themeName;
};
</script>
<template>
<div class="dropdown dropdown-end">
<div tabindex="0" role="button" class="btn m-1">{{ t('nav-bar.tab-theme') }}</div>
<div
class="dropdown-content bg-base-200 text-base-content rounded-box top-px h-[24rem] max-h-[calc(100vh-10rem)] w-56 overflow-y-auto border border-white/5 shadow-2xl outline outline-1 outline-black/5 mt-16"
>
<div class="grid grid-cols-1 gap-3 p-3">
<button
class="outline-base-content text-start flex items-center outline-offset-4 btn glass"
v-for="theme in THEME_LIST"
:style="getThemeStyle(theme)"
:key="theme"
data-choose-theme
data-key="theme"
:data-set-theme="theme"
@click="saveTheme(theme)"
>
<div class="flex items-center justify-between w-full">
<div class="flex items-center">
<svg
v-if="theme === nowTheme"
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
/>
</svg>
<svg
v-else
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
</svg>
<p class="ml-1">{{ theme }}</p>
</div>
<div class="flex">
<span
class="w-3 h-3 bg-red-500 rounded-full mr-1"
v-for="(color, idx) in getThemeColor(theme)"
:key="idx"
:style="{ 'background-color': color }"
></span>
</div>
<DropdownView :list="THEME_LIST" :title="t('nav-bar.tab-theme')">
<template #default="{ item }">
<button
class="outline-base-content text-start flex items-center outline-offset-4 btn glass mt-2"
:style="getThemeStyle(item)"
data-choose-theme
data-key="theme"
:data-set-theme="item"
@click="saveTheme(item)"
>
<div class="flex items-center justify-between w-full">
<div class="flex items-center">
<svg
v-if="item === nowTheme"
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
/>
</svg>
<svg
v-else
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
></svg>
<p class="ml-1">{{ item }}</p>
</div>
</button>
</div>
</div>
</div>
<div class="flex">
<span
class="w-3 h-3 bg-red-500 rounded-full mr-1"
v-for="(color, idx) in getThemeColor(item)"
:key="idx"
:style="{ 'background-color': color }"
></span>
</div>
</div>
</button>
</template>
</DropdownView>
</template>
Loading

1 comment on commit 2075090

@vercel
Copy link

@vercel vercel bot commented on 2075090 Apr 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.