27 暗黑主题样式优化 - udo-bit/naive_admin_pro GitHub Wiki
完成暗黑主题样式的优化
上节课我们完成了动态暗黑主题的切换,但是还存在一些bug,当我们切到亮色的时候,发现我们的内容布局部分还是暗黑模式。 我们切到stores/app.ts中监听我们布局样式的变化,根据样式变化动态处理我们的布局
watch(() => layout.layoutStyle, () => {
if (layout.layoutStyle === 'dark')
toggleDark(true)
else
toggleDark(false)
})
接下来我们来添加一下切换暗黑主题的功能。 我们切到setting-drawer中的checkbox-layout.vue中,添加dark属性:
const props = withDefaults(defineProps<{
layout?: 'mix' | 'side' | 'top'
inverted?: boolean
checked?: boolean
title?: string | (() => VNodeChild)
dark?: boolean
}>(), {
layout: 'top',
inverted: false,
checked: false,
})
如果主题是dark模式的话,我们就让顶部和侧边栏都为反色。
const headerClass = computed(() => {
+ if (props.layout === 'mix' || props.layout === 'top' || props.dark) {
return [
'bg-[var(--inverted-color)]',
]
}
if (props.layout === 'side') {
return [
'bg-[var(--base-color)]',
]
}
return []
})
const siderClass = computed(() => {
if (props.layout === 'mix') {
return [
'bg-[var(--base-color)]',
'h-75%',
'bottom-0',
]
}
if (props.layout === 'side') {
return [
'h-100%',
+ `bg-[var(--${(props.inverted || props.dark) ? 'inverted' : 'base'}-color)]`,
]
}
return []
})
在index.vue中添加支持dark模式:
<template>
<Container v-if="layoutStyleList" title="布局风格配置">
<n-space size="large">
<template v-for="item in layoutStyleList" :key="item.id">
<CheckboxLayout
:title="item.title"
:layout="item.key"
+ :dark="item.dark"
:inverted="item.inverted"
:checked="item.id === layoutStyle"
@click="() => $emit('update:layoutStyle', item.id)"
/>
</template>
</n-space>
</Container>
</template>
在config/layout-theme.ts中添加对暗黑主题的类型支持
export interface LayoutType {
id: string
key: 'mix' | 'side' | 'top'
title: string
inverted?: boolean
+ dark?:boolean
}
在stores/app.ts中添加暗黑模式主题:
const layoutStyleList = computed<LayoutType[]>(() => {
const list: LayoutType[] = [
{
id: 'light',
key: 'side',
title: '亮色风格',
},
]
if (layout.layout !== 'mix') {
list.push({
id: 'inverted',
key: 'side',
inverted: true,
title: '反转色风格',
})
}
else {
if (layout.layoutStyle !== 'dark')
updateLayoutStyle('light')
}
list.push({
id: 'dark',
key: 'side',
title: '暗色风格',
dark:true
})
return list
})
接下来我们看到当我们切换到暗黑模式的时候,整个的布局风格都变成了一样的格式和样子,但这不是我们想要的,所以接下来我们优化一下整个的样式。 首先我们再config中创建一个pro-theme.ts的文件用于存放我们的全局样式,然后直接复制我们这一部分的样式代码。
import { merge } from 'lodash-es'
import type { GlobalTheme } from 'naive-ui'
import {
cardDark,
drawerDark,
elementDark,
layoutDark,
listDark,
menuDark,
darkTheme as naiveDarkTheme,
} from 'naive-ui'
const commonColor: Record<string, any> = {
bgColor: '#242525',
}
export const darkTheme: GlobalTheme = merge({}, naiveDarkTheme, {
common: {
baseColor: '#2A2C2C',
},
Layout: {
...layoutDark,
self(_vars) {
return {
...layoutDark.self?.(_vars),
color: commonColor.bgColor,
headerColor: commonColor.bgColor,
siderColor: commonColor.bgColor,
footerColor: commonColor.bgColor,
}
},
},
Card: {
...cardDark,
self(_vars) {
return {
...cardDark.self?.(_vars),
color: commonColor.bgColor,
}
},
},
Drawer: {
...drawerDark,
self(_vars) {
return {
...drawerDark.self?.(_vars),
color: commonColor.bgColor,
}
},
},
Menu: {
...menuDark,
self(_vars) {
return {
...menuDark.self?.(_vars),
color: commonColor.bgColor,
}
},
},
List: {
...listDark,
self(_vars) {
return {
...listDark.self?.(_vars),
color: commonColor.bgColor,
}
},
},
Element: {
...elementDark,
common: {
...elementDark.common,
baseColor: commonColor.bgColor,
},
},
} as Partial<GlobalTheme>)
export const layoutDarkTheme = darkTheme.Layout
export const elementDarkTheme = darkTheme.Element
由于文件中引入了lodash-es我们先来安装一下
pnpm add @types/lodash-es lodash-es -D
替换暗黑主题在stores/app.ts
import { darkTheme } from '~/config/pro-theme'
const layoutTheme = computed(() => {
if (layout.layoutStyle === 'dark')
return darkTheme
return undefined
})
我们可以看到,当我们在切换主题的时候,就保证了我们的样式的问题,接下里我们再来优化一下我们的侧边栏阴影和顶部的阴影。 我们在styles/vars.css中添加对应的阴影css变量
html{
--pro-admin-layout-content-bg: #f0f2f5;
--pro-admin-layout-box-shadow: 0 1px 3px 0 rgba(0,0,0,.18);
+ --pro-admin-layout-shadow-sider: 2px 0 8px 0 rgb(29 35 41 / 5%);
+ --pro-admin-layout-shadow-header: 0 1px 4px rgb(0 21 41 / 8%);
}
html.dark{
--pro-admin-layout-content-bg: #2A2C2C;
--pro-admin-layout-box-shadow: 0 1px 3px 0 rgba(13,13,13,.18);
+ --pro-admin-layout-shadow-sider: rgba(13, 13, 13, 0.65) 0px 2px 8px 0px;
+ --pro-admin-layout-shadow-header: rgb(13 13 13 / 65%) 0px 2px 8px 0px;
}
然后创建一个自定义css样式文件custom.css:
.pro-admin-layout-header{
box-shadow: var(--pro-admin-layout-shadow-header);
}
.pro-admin-layout-sider{
box-shadow: var(--pro-admin-layout-shadow-sider);
}
然后再index.css中导入:
@import "vars.css";
+ @import "custom.css";
然后我们在布局中添加我们的类: 在layouts中的mix-layout:
<n-layout-header
inverted
+ class="pro-admin-layout-header pro-admin-mix-layout-header flex justify-between items-center px-4">
<div class="flex items-center">
<Logo :src="logo" />
<Title :title="title" />
</div>
<slot name="headerRight">
<div>
右侧
</div>
</slot>
</n-layout-header>
在 mobile-layout中:
<n-layout-header
:inverted="headerInverted"
class="pro-admin-layout-header pro-admin-mix-layout-header flex justify-between items-center px-4"
>
// ...
</h-layout-header>
在side-layout中:
<n-layout-header class="pro-admin-mix-layout-header flex justify-between items-center px-4">
// ...
</n-layout-header>
在top-layout中:
<n-layout-header
:inverted="inverted"
+ class="pro-admin-layout-header pro-admin-mix-layout-header flex justify-between items-center px-4"
>
/// ...
</n-layout-header>
在 common/layout-sider中
<template>
+ <n-layout-sider class="pro-admin-layout-sider" collapse-mode="width">
<slot />
</n-layout-sider>
</template>
测试效果