feat: 新增侧边栏颜色切换 (#681)

* fix: 修复Header元素偏移的问题

* fix: 修复i18n未引用的问题

* feat: 新增侧边栏颜色模式

* chore: 移除侧边栏模式跟随系统

* feat: 换种展示方式
This commit is contained in:
悠静萝莉 2024-02-14 22:51:15 +08:00 committed by GitHub
parent b9095ce939
commit ce97b04d79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 67 additions and 16 deletions

View File

@ -5,6 +5,7 @@ export default {
mode: 'light', mode: 'light',
layout: 'side', layout: 'side',
splitMenu: false, splitMenu: false,
sideMode: 'light',
isFooterAside: false, isFooterAside: false,
isSidebarFixed: true, isSidebarFixed: true,
isHeaderFixed: true, isHeaderFixed: true,

View File

@ -238,7 +238,6 @@ const navToHelper = () => {
display: flex; display: flex;
align-items: normal; align-items: normal;
line-height: 0; line-height: 0;
padding-left: var(--td-comp-margin-xl);
} }
.header-logo-container { .header-logo-container {

View File

@ -5,7 +5,7 @@
:layout="settingStore.layout" :layout="settingStore.layout"
:is-fixed="settingStore.isSidebarFixed" :is-fixed="settingStore.isSidebarFixed"
:menu="sideMenu" :menu="sideMenu"
:theme="settingStore.displayMode" :theme="settingStore.displaySideMode"
:is-compact="settingStore.isSidebarCompact" :is-compact="settingStore.isSidebarCompact"
/> />
</template> </template>

View File

@ -3,12 +3,12 @@
<t-menu :class="menuCls" :theme="theme" :value="active" :collapsed="collapsed" :default-expanded="defaultExpanded"> <t-menu :class="menuCls" :theme="theme" :value="active" :collapsed="collapsed" :default-expanded="defaultExpanded">
<template #logo> <template #logo>
<span v-if="showLogo" :class="`${prefix}-side-nav-logo-wrapper`" @click="goHome"> <span v-if="showLogo" :class="`${prefix}-side-nav-logo-wrapper`" @click="goHome">
<component :is="getLogo()" :class="`${prefix}-side-nav-logo-${collapsed ? 't' : 'tdesign'}-logo`" /> <component :is="getLogo()" :class="logoCls" />
</span> </span>
</template> </template>
<menu-content :nav-data="menu" /> <menu-content :nav-data="menu" />
<template #operations> <template #operations>
<span class="version-container"> {{ !collapsed ? 'TDesign Starter' : '' }} {{ pgk.version }} </span> <span :class="versionCls"> {{ !collapsed ? 'TDesign Starter' : '' }} {{ pgk.version }} </span>
</template> </template>
</t-menu> </t-menu>
<div :class="`${prefix}-side-nav-placeholder${collapsed ? '-hidden' : ''}`"></div> <div :class="`${prefix}-side-nav-placeholder${collapsed ? '-hidden' : ''}`"></div>
@ -75,6 +75,10 @@ const defaultExpanded = computed(() => {
return union(expanded, parentPath === '' ? [] : [parentPath]); return union(expanded, parentPath === '' ? [] : [parentPath]);
}); });
const sideMode = computed(() => {
const { theme } = props;
return theme === 'dark';
});
const sideNavCls = computed(() => { const sideNavCls = computed(() => {
const { isCompact } = props; const { isCompact } = props;
return [ return [
@ -84,7 +88,22 @@ const sideNavCls = computed(() => {
}, },
]; ];
}); });
const logoCls = computed(() => {
return [
`${prefix}-side-nav-logo-${collapsed.value ? 't' : 'tdesign'}-logo`,
{
[`${prefix}-side-nav-dark`]: sideMode.value,
},
];
});
const versionCls = computed(() => {
return [
`version-container`,
{
[`${prefix}-side-nav-dark`]: sideMode.value,
},
];
});
const menuCls = computed(() => { const menuCls = computed(() => {
const { showLogo, isFixed, layout } = props; const { showLogo, isFixed, layout } = props;
return [ return [

View File

@ -52,7 +52,6 @@
</t-popup> </t-popup>
</div> </div>
</t-radio-group> </t-radio-group>
<div class="setting-group-title">{{ $t('layout.setting.navigationLayout') }}</div> <div class="setting-group-title">{{ $t('layout.setting.navigationLayout') }}</div>
<t-radio-group v-model="formData.layout"> <t-radio-group v-model="formData.layout">
<div v-for="(item, index) in LAYOUT_OPTION" :key="index" class="setting-layout-drawer"> <div v-for="(item, index) in LAYOUT_OPTION" :key="index" class="setting-layout-drawer">
@ -62,15 +61,24 @@
</div> </div>
</t-radio-group> </t-radio-group>
<t-form-item v-show="formData.layout === 'mix'" label="分割菜单(混合模式下有效)" name="splitMenu"> <t-form-item v-show="formData.layout === 'mix'" :label="$t('layout.setting.splitMenu')" name="splitMenu">
<t-switch v-model="formData.splitMenu" /> <t-switch v-model="formData.splitMenu" />
</t-form-item> </t-form-item>
<t-form-item
<t-form-item v-show="formData.layout === 'mix'" label="固定 Sidebar" name="isSidebarFixed"> v-show="formData.layout === 'mix'"
:label="$t('layout.setting.fixedSidebar')"
name="isSidebarFixed"
>
<t-switch v-model="formData.isSidebarFixed" /> <t-switch v-model="formData.isSidebarFixed" />
</t-form-item> </t-form-item>
<div class="setting-group-title">{{ $t('layout.setting.element.title') }}</div> <div class="setting-group-title">{{ $t('layout.setting.element.title') }}</div>
<t-form-item :label="$t('layout.setting.sideMode')" name="sideMode">
<t-radio-group v-model="formData.sideMode" class="side-mode-radio">
<t-radio-button key="light" value="light" :label="$t('layout.setting.theme.options.light')" />
<t-radio-button key="dark" value="dark" :label="$t('layout.setting.theme.options.dark')" />
</t-radio-group>
</t-form-item>
<t-form-item <t-form-item
v-show="formData.layout === 'side'" v-show="formData.layout === 'side'"
:label="$t('layout.setting.element.showHeader')" :label="$t('layout.setting.element.showHeader')"
@ -295,6 +303,10 @@ watchEffect(() => {
width: 100%; width: 100%;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
&.side-mode-radio {
justify-content: end;
}
} }
.t-radio-group.t-size-m .t-radio-button { .t-radio-group.t-size-m .t-radio-button {

View File

@ -33,6 +33,7 @@ export default {
}, },
}, },
navigationLayout: 'Navigation Layout', navigationLayout: 'Navigation Layout',
sideMode: 'Side Menu Mode',
splitMenu: 'Split MenuOnly Mix mode', splitMenu: 'Split MenuOnly Mix mode',
fixedSidebar: 'Fixed Sidebar', fixedSidebar: 'Fixed Sidebar',
element: { element: {

View File

@ -33,6 +33,7 @@ export default {
}, },
}, },
navigationLayout: '导航布局', navigationLayout: '导航布局',
sideMode: '侧边栏模式',
splitMenu: '分割菜单(混合模式下有效)', splitMenu: '分割菜单(混合模式下有效)',
fixedSidebar: '固定侧边栏', fixedSidebar: '固定侧边栏',
element: { element: {

View File

@ -33,18 +33,16 @@ export const useSettingStore = defineStore('setting', {
} }
return state.mode as 'dark' | 'light'; return state.mode as 'dark' | 'light';
}, },
displaySideMode: (state): 'dark' | 'light' => {
return state.sideMode as 'dark' | 'light';
},
}, },
actions: { actions: {
async changeMode(mode: 'dark' | 'light' | 'auto') { async changeMode(mode: 'dark' | 'light' | 'auto') {
let theme = mode; let theme = mode;
if (mode === 'auto') { if (mode === 'auto') {
const media = window.matchMedia('(prefers-color-scheme:dark)'); theme = this.getMediaColor();
if (media.matches) {
theme = 'dark';
} else {
theme = 'light';
}
} }
const isDarkMode = theme === 'dark'; const isDarkMode = theme === 'dark';
@ -52,6 +50,19 @@ export const useSettingStore = defineStore('setting', {
this.chartColors = isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS; this.chartColors = isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS;
}, },
async changeSideMode(mode: 'dark' | 'light') {
const isDarkMode = mode === 'dark';
document.documentElement.setAttribute('side-mode', isDarkMode ? 'dark' : '');
},
getMediaColor() {
const media = window.matchMedia('(prefers-color-scheme:dark)');
if (media.matches) {
return 'dark';
}
return 'light';
},
changeBrandTheme(brandTheme: string) { changeBrandTheme(brandTheme: string) {
const mode = this.displayMode; const mode = this.displayMode;
// 以主题色加显示模式作为键 // 以主题色加显示模式作为键
@ -79,6 +90,9 @@ export const useSettingStore = defineStore('setting', {
if (key === 'mode') { if (key === 'mode') {
this.changeMode(payload[key]); this.changeMode(payload[key]);
} }
if (key === 'sideMode') {
this.changeSideMode(payload[key]);
}
if (key === 'brandTheme') { if (key === 'brandTheme') {
this.changeBrandTheme(payload[key]); this.changeBrandTheme(payload[key]);
} }

View File

@ -163,7 +163,7 @@
} }
&-logo-tdesign-logo { &-logo-tdesign-logo {
padding: 0 var(--td-comp-paddingLR-xl); margin-right: var(--td-comp-margin-xxxl);
height: var(--td-comp-size-s); height: var(--td-comp-size-s);
width: 100%; width: 100%;
color: var(--td-text-color-primary); color: var(--td-text-color-primary);
@ -176,6 +176,10 @@
} }
} }
&-side-nav-dark {
color: var(--td-font-white-1) !important;
}
&-side-nav-placeholder { &-side-nav-placeholder {
flex: 1 1 232px; flex: 1 1 232px;
min-width: 232px; min-width: 232px;