feat: header menu align support (#5256)

* feat: header menu align support

* fix: typo
This commit is contained in:
Netfan 2024-12-28 16:16:48 +08:00 committed by GitHub
parent 15fe82c62f
commit ec2c6eff6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 73 additions and 4 deletions

View File

@ -38,6 +38,7 @@ type BuiltinThemeType =
type ContentCompactType = 'compact' | 'wide'; type ContentCompactType = 'compact' | 'wide';
type LayoutHeaderModeType = 'auto' | 'auto-scroll' | 'fixed' | 'static'; type LayoutHeaderModeType = 'auto' | 'auto-scroll' | 'fixed' | 'static';
type LayoutHeaderMenuAlignType = 'center' | 'end' | 'start';
/** /**
* *
@ -95,6 +96,7 @@ export type {
BreadcrumbStyleType, BreadcrumbStyleType,
BuiltinThemeType, BuiltinThemeType,
ContentCompactType, ContentCompactType,
LayoutHeaderMenuAlignType,
LayoutHeaderModeType, LayoutHeaderModeType,
LayoutType, LayoutType,
LoginExpiredModeType, LoginExpiredModeType,

View File

@ -46,6 +46,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj
"header": { "header": {
"enable": true, "enable": true,
"hidden": false, "hidden": false,
"menuAlign": "start",
"mode": "fixed", "mode": "fixed",
}, },
"logo": { "logo": {

View File

@ -46,6 +46,7 @@ const defaultPreferences: Preferences = {
header: { header: {
enable: true, enable: true,
hidden: false, hidden: false,
menuAlign: 'start',
mode: 'fixed', mode: 'fixed',
}, },
logo: { logo: {

View File

@ -5,6 +5,7 @@ import type {
BuiltinThemeType, BuiltinThemeType,
ContentCompactType, ContentCompactType,
DeepPartial, DeepPartial,
LayoutHeaderMenuAlignType,
LayoutHeaderModeType, LayoutHeaderModeType,
LayoutType, LayoutType,
LoginExpiredModeType, LoginExpiredModeType,
@ -104,6 +105,8 @@ interface HeaderPreferences {
enable: boolean; enable: boolean;
/** 顶栏是否隐藏,css-隐藏 */ /** 顶栏是否隐藏,css-隐藏 */
hidden: boolean; hidden: boolean;
/** 顶栏菜单位置 */
menuAlign: LayoutHeaderMenuAlignType;
/** header显示模式 */ /** header显示模式 */
mode: LayoutHeaderModeType; mode: LayoutHeaderModeType;
} }

View File

@ -332,6 +332,7 @@ function removeMenuItem(item: MenuItemRegistered) {
is(theme, true), is(theme, true),
is('rounded', rounded), is('rounded', rounded),
is('collapse', collapse), is('collapse', collapse),
is('menu-align', mode === 'horizontal'),
]" ]"
:style="menuStyle" :style="menuStyle"
role="menu" role="menu"
@ -423,6 +424,10 @@ $namespace: vben;
opacity: 1; opacity: 1;
} }
.is-menu-align {
justify-content: var(--menu-align, start);
}
.#{$namespace}-menu__popup-container, .#{$namespace}-menu__popup-container,
.#{$namespace}-menu { .#{$namespace}-menu {
--menu-title-width: 140px; --menu-title-width: 140px;

View File

@ -133,7 +133,10 @@ function clearPreferencesAndLogout() {
> >
<slot :name="slot.name"></slot> <slot :name="slot.name"></slot>
</template> </template>
<div class="flex h-full min-w-0 flex-1 items-center"> <div
:class="`menu-align-${preferences.header.menuAlign}`"
class="flex h-full min-w-0 flex-1 items-center"
>
<slot name="menu"></slot> <slot name="menu"></slot>
</div> </div>
<div class="flex h-full min-w-0 flex-shrink-0 items-center"> <div class="flex h-full min-w-0 flex-shrink-0 items-center">
@ -166,3 +169,16 @@ function clearPreferencesAndLogout() {
</template> </template>
</div> </div>
</template> </template>
<style lang="scss" scoped>
.menu-align-start {
--menu-align: start;
}
.menu-align-center {
--menu-align: center;
}
.menu-align-end {
--menu-align: end;
}
</style>

View File

@ -1,15 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import type { LayoutHeaderModeType, SelectOption } from '@vben/types'; import type {
LayoutHeaderMenuAlignType,
LayoutHeaderModeType,
SelectOption,
} from '@vben/types';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import SelectItem from '../select-item.vue'; import SelectItem from '../select-item.vue';
import SwitchItem from '../switch-item.vue'; import SwitchItem from '../switch-item.vue';
import ToggleItem from '../toggle-item.vue';
defineProps<{ disabled: boolean }>(); defineProps<{ disabled: boolean }>();
const headerEnable = defineModel<boolean>('headerEnable'); const headerEnable = defineModel<boolean>('headerEnable');
const headerMode = defineModel<LayoutHeaderModeType>('headerMode'); const headerMode = defineModel<LayoutHeaderModeType>('headerMode');
const headerMenuAlign =
defineModel<LayoutHeaderMenuAlignType>('headerMenuAlign');
const localeItems: SelectOption[] = [ const localeItems: SelectOption[] = [
{ {
@ -29,6 +36,21 @@ const localeItems: SelectOption[] = [
value: 'auto-scroll', value: 'auto-scroll',
}, },
]; ];
const headerMenuAlignItems: SelectOption[] = [
{
label: $t('preferences.header.menuAlignStart'),
value: 'start',
},
{
label: $t('preferences.header.menuAlignCenter'),
value: 'center',
},
{
label: $t('preferences.header.menuAlignEnd'),
value: 'end',
},
];
</script> </script>
<template> <template>
@ -42,4 +64,11 @@ const localeItems: SelectOption[] = [
> >
{{ $t('preferences.mode') }} {{ $t('preferences.mode') }}
</SelectItem> </SelectItem>
<ToggleItem
v-model="headerMenuAlign"
:disabled="!headerEnable"
:items="headerMenuAlignItems"
>
{{ $t('preferences.header.menuAlign') }}
</ToggleItem>
</template> </template>

View File

@ -4,6 +4,7 @@ import type {
BreadcrumbStyleType, BreadcrumbStyleType,
BuiltinThemeType, BuiltinThemeType,
ContentCompactType, ContentCompactType,
LayoutHeaderMenuAlignType,
LayoutHeaderModeType, LayoutHeaderModeType,
LayoutType, LayoutType,
NavigationStyleType, NavigationStyleType,
@ -94,6 +95,8 @@ const SidebarExpandOnHover = defineModel<boolean>('sidebarExpandOnHover');
const headerEnable = defineModel<boolean>('headerEnable'); const headerEnable = defineModel<boolean>('headerEnable');
const headerMode = defineModel<LayoutHeaderModeType>('headerMode'); const headerMode = defineModel<LayoutHeaderModeType>('headerMode');
const headerMenuAlign =
defineModel<LayoutHeaderMenuAlignType>('headerMenuAlign');
const breadcrumbEnable = defineModel<boolean>('breadcrumbEnable'); const breadcrumbEnable = defineModel<boolean>('breadcrumbEnable');
const breadcrumbShowIcon = defineModel<boolean>('breadcrumbShowIcon'); const breadcrumbShowIcon = defineModel<boolean>('breadcrumbShowIcon');
@ -317,6 +320,7 @@ async function handleReset() {
<Block :title="$t('preferences.header.title')"> <Block :title="$t('preferences.header.title')">
<Header <Header
v-model:header-enable="headerEnable" v-model:header-enable="headerEnable"
v-model:header-menu-align="headerMenuAlign"
v-model:header-mode="headerMode" v-model:header-mode="headerMode"
:disabled="isFullContent" :disabled="isFullContent"
/> />

View File

@ -138,7 +138,11 @@
"modeStatic": "Static", "modeStatic": "Static",
"modeFixed": "Fixed", "modeFixed": "Fixed",
"modeAuto": "Auto hide & Show", "modeAuto": "Auto hide & Show",
"modeAutoScroll": "Scroll to Hide & Show" "modeAutoScroll": "Scroll to Hide & Show",
"menuAlign": "Menu Align",
"menuAlignStart": "Start",
"menuAlignEnd": "End",
"menuAlignCenter": "Center"
}, },
"footer": { "footer": {
"title": "Footer", "title": "Footer",

View File

@ -138,7 +138,11 @@
"modeFixed": "固定", "modeFixed": "固定",
"modeAuto": "自动隐藏和显示", "modeAuto": "自动隐藏和显示",
"modeAutoScroll": "滚动隐藏和显示", "modeAutoScroll": "滚动隐藏和显示",
"visible": "显示顶栏" "visible": "显示顶栏",
"menuAlign": "菜单位置",
"menuAlignStart": "左侧",
"menuAlignEnd": "右侧",
"menuAlignCenter": "居中"
}, },
"footer": { "footer": {
"title": "底栏", "title": "底栏",