feat: supports specifying the position of the preference button (#4154)

This commit is contained in:
Vben
2024-08-14 23:02:39 +08:00
committed by GitHub
parent 9c6e059aac
commit 30223f18db
15 changed files with 121 additions and 21 deletions

View File

@@ -5,7 +5,12 @@ import { preferences, usePreferences } from '@vben/preferences';
import { useAccessStore } from '@vben/stores';
import { VbenFullScreen } from '@vben-core/shadcn-ui';
import { GlobalSearch, LanguageToggle, ThemeToggle } from '../../widgets';
import {
GlobalSearch,
LanguageToggle,
PreferencesButton,
ThemeToggle,
} from '../../widgets';
interface Props {
/**
@@ -26,34 +31,44 @@ const accessStore = useAccessStore();
const { globalSearchShortcutKey } = usePreferences();
const slots = useSlots();
const rightSlots = computed(() => {
const list = [{ index: 30, name: 'user-dropdown' }];
const list = [{ index: 100, name: 'user-dropdown' }];
if (preferences.widget.globalSearch) {
list.push({
index: 5,
name: 'global-search',
});
}
if (preferences.widget.themeToggle) {
if (
preferences.app.enablePreferences &&
preferences.app.preferencesButtonPosition === 'header'
) {
list.push({
index: 10,
name: 'preferences',
});
}
if (preferences.widget.themeToggle) {
list.push({
index: 15,
name: 'theme-toggle',
});
}
if (preferences.widget.languageToggle) {
list.push({
index: 15,
index: 20,
name: 'language-toggle',
});
}
if (preferences.widget.fullscreen) {
list.push({
index: 20,
index: 25,
name: 'fullscreen',
});
}
if (preferences.widget.notification) {
list.push({
index: 25,
index: 30,
name: 'notification',
});
}
@@ -66,6 +81,7 @@ const rightSlots = computed(() => {
});
return list.sort((a, b) => a.index - b.index);
});
const leftSlots = computed(() => {
const list: any[] = [];
@@ -108,8 +124,12 @@ const leftSlots = computed(() => {
class="mr-4"
/>
</template>
<template v-else-if="slot.name === 'preferences'">
<PreferencesButton class="mr-2" />
</template>
<template v-else-if="slot.name === 'theme-toggle'">
<ThemeToggle class="mr-2" />
<ThemeToggle class="mr-2 mt-[2px]" />
</template>
<template v-else-if="slot.name === 'language-toggle'">
<LanguageToggle class="mr-2" />

View File

@@ -320,8 +320,14 @@ const headerSlots = computed(() => {
<slot v-if="lockStore.isLockScreen" name="lock-screen"></slot>
</Transition>
<template v-if="preferences.app.enablePreferences">
<template
v-if="
preferences.app.enablePreferences &&
preferences.app.preferencesButtonPosition === 'fixed'
"
>
<Preferences
class="z-100 fixed bottom-20 right-0"
@clear-preferences-and-logout="clearPreferencesAndLogout"
/>
</template>

View File

@@ -54,9 +54,6 @@ const styleItems = computed((): SelectOption[] => [
<SwitchItem v-model="tabbarDragable" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.dragable') }}
</SwitchItem>
<SelectItem v-model="tabbarStyleType" :items="styleItems">
{{ $t('preferences.tabbar.styleType.title') }}
</SelectItem>
<SwitchItem v-model="tabbarShowIcon" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.icon') }}
</SwitchItem>
@@ -69,4 +66,7 @@ const styleItems = computed((): SelectOption[] => [
<SwitchItem v-model="tabbarShowMaximize" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.showMaximize') }}
</SwitchItem>
<SelectItem v-model="tabbarStyleType" :items="styleItems">
{{ $t('preferences.tabbar.styleType.title') }}
</SelectItem>
</template>

View File

@@ -1,6 +1,11 @@
<script setup lang="ts">
import type { SelectOption } from '@vben/types';
import { computed } from 'vue';
import { $t } from '@vben/locales';
import SelectItem from '../select-item.vue';
import SwitchItem from '../switch-item.vue';
defineOptions({
@@ -14,6 +19,20 @@ const widgetNotification = defineModel<boolean>('widgetNotification');
const widgetThemeToggle = defineModel<boolean>('widgetThemeToggle');
const widgetSidebarToggle = defineModel<boolean>('widgetSidebarToggle');
const widgetLockScreen = defineModel<boolean>('widgetLockScreen');
const appPreferencesButtonPosition = defineModel<string>(
'appPreferencesButtonPosition',
);
const positionItems = computed((): SelectOption[] => [
{
label: $t('preferences.position.header'),
value: 'header',
},
{
label: $t('preferences.position.fixed'),
value: 'fixed',
},
]);
</script>
<template>
@@ -38,4 +57,7 @@ const widgetLockScreen = defineModel<boolean>('widgetLockScreen');
<SwitchItem v-model="widgetSidebarToggle">
{{ $t('preferences.widget.sidebarToggle') }}
</SwitchItem>
<SelectItem v-model="appPreferencesButtonPosition" :items="positionItems">
{{ $t('preferences.position.title') }}
</SelectItem>
</template>

View File

@@ -1,2 +1,3 @@
export { default as Preferences } from './preferences.vue';
export { default as PreferencesButton } from './preferences-button.vue';
export * from './use-open-preferences';

View File

@@ -0,0 +1,13 @@
<script lang="ts" setup>
import { Settings } from '@vben/icons';
import { VbenIconButton } from '@vben-core/shadcn-ui';
import Preferences from './preferences.vue';
</script>
<template>
<Preferences>
<VbenIconButton>
<Settings class="size-4" />
</VbenIconButton>
</Preferences>
</template>

View File

@@ -7,13 +7,14 @@ import type {
LayoutHeaderModeType,
LayoutType,
NavigationStyleType,
PreferencesButtonPositionType,
ThemeModeType,
} from '@vben/types';
import type { SegmentedItem } from '@vben-core/shadcn-ui';
import { computed, ref } from 'vue';
import { Copy, RotateCw, Settings2 } from '@vben/icons';
import { Copy, RotateCw, Settings } from '@vben/icons';
import { $t, loadLocaleMessages } from '@vben/locales';
import {
clearPreferencesCache,
@@ -63,6 +64,9 @@ const appColorWeakMode = defineModel<boolean>('appColorWeakMode');
const appContentCompact = defineModel<ContentCompactType>('appContentCompact');
const appWatermark = defineModel<boolean>('appWatermark');
const appEnableCheckUpdates = defineModel<boolean>('appEnableCheckUpdates');
const appPreferencesButtonPosition = defineModel<PreferencesButtonPositionType>(
'appPreferencesButtonPosition',
);
const transitionProgress = defineModel<boolean>('transitionProgress');
const transitionName = defineModel<string>('transitionName');
@@ -220,19 +224,21 @@ async function handleReset() {
</script>
<template>
<div class="z-100 fixed right-0 top-1/2">
<div>
<VbenSheet
v-model:open="openPreferences"
:description="$t('preferences.subtitle')"
:title="$t('preferences.title')"
>
<template #trigger>
<VbenButton
:title="$t('preferences.title')"
class="bg-primary flex-col-center h-10 w-10 cursor-pointer rounded-l-lg rounded-r-none border-none"
>
<Settings2 class="size-5" />
</VbenButton>
<slot name="trigger">
<VbenButton
:title="$t('preferences.title')"
class="bg-primary flex-col-center size-10 cursor-pointer rounded-l-lg rounded-r-none border-none"
>
<Settings class="size-5" />
</VbenButton>
</slot>
</template>
<template #extra>
<div class="flex items-center">
@@ -358,6 +364,9 @@ async function handleReset() {
</Block>
<Block :title="$t('preferences.widget.title')">
<Widget
v-model:app-preferences-button-position="
appPreferencesButtonPosition
"
v-model:widget-fullscreen="widgetFullscreen"
v-model:widget-global-search="widgetGlobalSearch"
v-model:widget-language-toggle="widgetLanguageToggle"

View File

@@ -47,5 +47,9 @@ const listen = computed(() => {
});
</script>
<template>
<PreferencesSheet v-bind="attrs" v-on="listen" />
<PreferencesSheet v-bind="attrs" v-on="listen">
<template #trigger>
<slot></slot>
</template>
</PreferencesSheet>
</template>