feat: support custom theme color and dark mode

perf: replace css variables to theme variables
This commit is contained in:
tiny-craft 2023-07-13 15:46:12 +08:00
parent 73f637a9f8
commit 29f87f75c1
13 changed files with 193 additions and 120 deletions

View File

@ -11,18 +11,30 @@ import AddFieldsDialog from './components/dialogs/AddFieldsDialog.vue'
import AppContent from './AppContent.vue' import AppContent from './AppContent.vue'
import GroupDialog from './components/dialogs/GroupDialog.vue' import GroupDialog from './components/dialogs/GroupDialog.vue'
import DeleteKeyDialog from './components/dialogs/DeleteKeyDialog.vue' import DeleteKeyDialog from './components/dialogs/DeleteKeyDialog.vue'
import { computed, onBeforeMount, ref } from 'vue'
import { get } from 'lodash'
import usePreferencesStore from './stores/preferences.js'
import useConnectionStore from './stores/connections.js'
import { useI18n } from 'vue-i18n'
import { darkTheme, lightTheme, useOsTheme } from 'naive-ui'
hljs.registerLanguage('json', json) hljs.registerLanguage('json', json)
hljs.registerLanguage('plaintext', plaintext) hljs.registerLanguage('plaintext', plaintext)
/**
*
* @type import('naive-ui').GlobalThemeOverrides
*/
const themeOverrides = { const themeOverrides = {
common: { common: {
// primaryColor: '#409EFF', primaryColor: '#D33A31',
primaryColorHover: '#FF6B6B',
primaryColorPressed: '#D5271C',
primaryColorSuppl: '#FF6B6B',
borderRadius: '4px', borderRadius: '4px',
borderRadiusSmall: '3px', borderRadiusSmall: '3px',
fontFamily: `"Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue"`,
lineHeight: 1.5, lineHeight: 1.5,
scrollbarWidth: '8px',
}, },
Tag: { Tag: {
// borderRadius: '3px' // borderRadius: '3px'
@ -33,13 +45,52 @@ const themeOverrides = {
tabGapLargeCard: '1px', tabGapLargeCard: '1px',
}, },
} }
const prefStore = usePreferencesStore()
const connectionStore = useConnectionStore()
const i18n = useI18n()
const initializing = ref(false)
onBeforeMount(async () => {
try {
initializing.value = true
await prefStore.loadPreferences()
i18n.locale.value = get(prefStore.general, 'language', 'en')
await prefStore.loadFontList()
await connectionStore.initConnections()
} finally {
initializing.value = false
}
})
const osTheme = useOsTheme()
const theme = computed(() => {
if (prefStore.general.theme === 'auto') {
if (osTheme.value === 'dark') {
return darkTheme
}
} else if (prefStore.general.theme === 'dark') {
return darkTheme
}
return lightTheme
})
</script> </script>
<template> <template>
<n-config-provider :hljs="hljs" :inline-theme-disabled="true" :theme-overrides="themeOverrides" class="fill-height"> <n-config-provider
:hljs="hljs"
:inline-theme-disabled="true"
:theme="theme"
:theme-overrides="themeOverrides"
class="fill-height"
>
<n-global-style />
<n-message-provider> <n-message-provider>
<n-dialog-provider> <n-dialog-provider>
<app-content /> <n-spin v-show="initializing" :theme-overrides="{ opacitySpinning: 0 }">
<template #description>{{ $t('launching') }}</template>
<div id="launch-container" />
</n-spin>
<app-content v-if="!initializing" />
<!-- top modal dialogs --> <!-- top modal dialogs -->
<connection-dialog /> <connection-dialog />
@ -55,4 +106,9 @@ const themeOverrides = {
</n-config-provider> </n-config-provider>
</template> </template>
<style lang="scss"></style> <style lang="scss">
#launch-container {
width: 100vw;
height: 100vh;
}
</style>

View File

@ -1,8 +1,7 @@
<script setup> <script setup>
import ContentPane from './components/content/ContentPane.vue' import ContentPane from './components/content/ContentPane.vue'
import BrowserPane from './components/sidebar/BrowserPane.vue' import BrowserPane from './components/sidebar/BrowserPane.vue'
import { computed, nextTick, onBeforeMount, onMounted, reactive, watch } from 'vue' import { computed, reactive } from 'vue'
import { useI18n } from 'vue-i18n'
import { debounce, get } from 'lodash' import { debounce, get } from 'lodash'
import { useThemeVars } from 'naive-ui' import { useThemeVars } from 'naive-ui'
import NavMenu from './components/sidebar/NavMenu.vue' import NavMenu from './components/sidebar/NavMenu.vue'
@ -26,24 +25,11 @@ const prefStore = usePreferencesStore()
const connectionStore = useConnectionStore() const connectionStore = useConnectionStore()
// const preferences = ref({}) // const preferences = ref({})
// provide('preferences', preferences) // provide('preferences', preferences)
const i18n = useI18n()
onBeforeMount(async () => {
try {
data.initializing = true
await prefStore.loadPreferences()
i18n.locale.value = get(prefStore.general, 'language', 'en')
await prefStore.loadFontList()
await connectionStore.initConnections()
} finally {
data.initializing = false
}
})
const saveWidth = debounce(prefStore.savePreferences, 1000, { trailing: true }) const saveWidth = debounce(prefStore.savePreferences, 1000, { trailing: true })
const handleResize = (evt) => { const handleResize = (evt) => {
if (data.resizing) { if (data.resizing) {
prefStore.setNavWidth(Math.max(evt.clientX - data.navMenuWidth, 300)) prefStore.setAsideWidth(Math.max(evt.clientX - data.navMenuWidth, 300))
saveWidth() saveWidth()
} }
} }
@ -62,7 +48,7 @@ const startResize = () => {
} }
const asideWidthVal = computed(() => { const asideWidthVal = computed(() => {
return prefStore.general.navMenuWidth + 'px' return prefStore.general.asideWidth + 'px'
}) })
const dragging = computed(() => { const dragging = computed(() => {
@ -72,68 +58,64 @@ const dragging = computed(() => {
<template> <template>
<!-- app content--> <!-- app content-->
<!-- <div id="app-container"></div>--> <div id="app-container" :class="{ dragging }" class="flex-box-h" :style="prefStore.generalFont">
<n-spin :show="data.initializing" :theme-overrides="{ opacitySpinning: 0 }"> <nav-menu v-model:value="tabStore.nav" :width="data.navMenuWidth" />
<template #description> {{ $t('launching') }} </template> <!-- structure page-->
<div id="app-container" :class="{ dragging }" class="flex-box-h" :style="prefStore.generalFont"> <div v-show="tabStore.nav === 'structure'" class="flex-box-h flex-item-expand">
<nav-menu v-model:value="tabStore.nav" :width="data.navMenuWidth" /> <div id="app-side" :style="{ width: asideWidthVal }" class="flex-box-h flex-item">
<!-- structure page--> <browser-pane
<div v-show="tabStore.nav === 'structure'" class="flex-box-h flex-item-expand"> v-for="t in tabStore.tabs"
<div id="app-side" :style="{ width: asideWidthVal }" class="flex-box-h flex-item"> v-show="get(tabStore.currentTab, 'name') === t.name"
<browser-pane :key="t.name"
v-for="t in tabStore.tabs" class="flex-item-expand"
v-show="get(tabStore.currentTab, 'name') === t.name" />
:key="t.name" <div
class="flex-item-expand" :class="{
/> 'resize-divider-hover': data.hoverResize,
<div 'resize-divider-drag': data.resizing,
:class="{ }"
'resize-divider-hover': data.hoverResize, class="resize-divider"
'resize-divider-drag': data.resizing, @mousedown="startResize"
}" @mouseout="data.hoverResize = false"
class="resize-divider" @mouseover="data.hoverResize = true"
@mousedown="startResize" />
@mouseout="data.hoverResize = false"
@mouseover="data.hoverResize = true"
/>
</div>
<content-pane class="flex-item-expand" />
</div> </div>
<content-pane class="flex-item-expand" />
<!-- server list page -->
<div v-show="tabStore.nav === 'server'" class="flex-box-h flex-item-expand">
<div id="app-side" :style="{ width: asideWidthVal }" class="flex-box-h flex-item">
<connection-pane class="flex-item-expand" />
<div
:class="{
'resize-divider-hover': data.hoverResize,
'resize-divider-drag': data.resizing,
}"
class="resize-divider"
@mousedown="startResize"
@mouseout="data.hoverResize = false"
@mouseover="data.hoverResize = true"
/>
</div>
<content-server-pane class="flex-item-expand" />
</div>
<!-- log page -->
<div v-show="tabStore.nav === 'log'">display log</div>
</div> </div>
</n-spin>
<!-- server list page -->
<div v-show="tabStore.nav === 'server'" class="flex-box-h flex-item-expand">
<div id="app-side" :style="{ width: asideWidthVal }" class="flex-box-h flex-item">
<connection-pane class="flex-item-expand" />
<div
:class="{
'resize-divider-hover': data.hoverResize,
'resize-divider-drag': data.resizing,
}"
class="resize-divider"
@mousedown="startResize"
@mouseout="data.hoverResize = false"
@mouseover="data.hoverResize = true"
/>
</div>
<content-server-pane class="flex-item-expand" />
</div>
<!-- log page -->
<div v-show="tabStore.nav === 'log'">display log</div>
</div>
</template> </template>
<style lang="scss"> <style scoped lang="scss">
#app-container { #app-container {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
border-top: var(--border-color) 1px solid; border-top: v-bind('themeVars.borderColor') 1px solid;
box-sizing: border-box; box-sizing: border-box;
#app-toolbar { #app-toolbar {
height: 40px; height: 40px;
border-bottom: var(--border-color) 1px solid; border-bottom: v-bind('themeVars.borderColor') 1px solid;
} }
#app-side { #app-side {
@ -144,7 +126,7 @@ const dragging = computed(() => {
//height: 100%; //height: 100%;
width: 2px; width: 2px;
border-left-width: 5px; border-left-width: 5px;
background-color: var(--border-color); background-color: v-bind('themeVars.dividerColor');
} }
.resize-divider-hover { .resize-divider-hover {

View File

@ -1,7 +1,7 @@
.content-container { .content-container {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
background-color: var(--bg-color); //background-color: var(--bg-color);
padding-top: 2px; padding-top: 2px;
padding-bottom: 5px; padding-bottom: 5px;
box-sizing: border-box; box-sizing: border-box;

View File

@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n'
import ContentToolbar from './ContentToolbar.vue' import ContentToolbar from './ContentToolbar.vue'
import Copy from '../icons/Copy.vue' import Copy from '../icons/Copy.vue'
import Save from '../icons/Save.vue' import Save from '../icons/Save.vue'
import { useMessage } from 'naive-ui' import { useMessage, useThemeVars } from 'naive-ui'
import { types } from '../../consts/value_view_type.js' import { types } from '../../consts/value_view_type.js'
import Close from '../icons/Close.vue' import Close from '../icons/Close.vue'
import Edit from '../icons/Edit.vue' import Edit from '../icons/Edit.vue'
@ -13,6 +13,7 @@ import { types as redisTypes } from '../../consts/support_redis_type.js'
import { ClipboardSetText } from '../../../wailsjs/runtime/runtime.js' import { ClipboardSetText } from '../../../wailsjs/runtime/runtime.js'
import { toLower } from 'lodash' import { toLower } from 'lodash'
import useConnectionStore from '../../stores/connections.js' import useConnectionStore from '../../stores/connections.js'
const themeVars = useThemeVars()
const props = defineProps({ const props = defineProps({
name: String, name: String,
@ -215,5 +216,6 @@ const onSaveValue = async () => {
<style lang="scss" scoped> <style lang="scss" scoped>
.value-wrapper { .value-wrapper {
overflow: hidden; overflow: hidden;
border-top: v-bind('themeVars.borderColor') 1px solid;
} }
</style> </style>

View File

@ -76,6 +76,13 @@ const onClose = () => {
label-align="right" label-align="right"
label-placement="left" label-placement="left"
> >
<n-form-item :label="$t('theme')" required>
<n-radio-group v-model:value="prefStore.general.theme" name="theme" size="medium">
<n-radio-button v-for="opt in prefStore.themeOption" :key="opt.value" :value="opt.value">
{{ opt.label }}
</n-radio-button>
</n-radio-group>
</n-form-item>
<n-form-item :label="$t('language')" required> <n-form-item :label="$t('language')" required>
<n-select <n-select
v-model:value="prefStore.general.language" v-model:value="prefStore.general.language"

View File

@ -1,9 +1,8 @@
<script setup> <script setup>
import { NIcon, useMessage } from 'naive-ui' import { useMessage, useThemeVars } from 'naive-ui'
import AddLink from '../icons/AddLink.vue' import AddLink from '../icons/AddLink.vue'
import BrowserTree from './BrowserTree.vue' import BrowserTree from './BrowserTree.vue'
import IconButton from '../common/IconButton.vue' import IconButton from '../common/IconButton.vue'
import Filter from '../icons/Filter.vue'
import useTabStore from '../../stores/tab.js' import useTabStore from '../../stores/tab.js'
import { computed } from 'vue' import { computed } from 'vue'
import { get } from 'lodash' import { get } from 'lodash'
@ -14,6 +13,7 @@ import { useConfirmDialog } from '../../utils/confirm_dialog.js'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import useConnectionStore from '../../stores/connections.js' import useConnectionStore from '../../stores/connections.js'
const themeVars = useThemeVars()
const dialogStore = useDialogStore() const dialogStore = useDialogStore()
const tabStore = useTabStore() const tabStore = useTabStore()
const currentName = computed(() => get(tabStore.currentTab, 'name', '')) const currentName = computed(() => get(tabStore.currentTab, 'name', ''))
@ -59,27 +59,12 @@ const onRefresh = () => {
<!-- bottom function bar --> <!-- bottom function bar -->
<div class="nav-pane-bottom flex-box-h"> <div class="nav-pane-bottom flex-box-h">
<icon-button <icon-button :icon="AddLink" size="20" stroke-width="4" t-tooltip="new_key" @click="onNewKey" />
:icon="AddLink" <icon-button :icon="Refresh" size="20" stroke-width="4" t-tooltip="reload" @click="onRefresh" />
color="#555"
size="20"
stroke-width="4"
t-tooltip="new_key"
@click="onNewKey"
/>
<icon-button
:icon="Refresh"
color="#555"
size="20"
stroke-width="4"
t-tooltip="reload"
@click="onRefresh"
/>
<div class="flex-item-expand"></div> <div class="flex-item-expand"></div>
<icon-button <icon-button
:disabled="currentSelect.key == null" :disabled="currentSelect.key == null"
:icon="Delete" :icon="Delete"
color="#555"
size="20" size="20"
stroke-width="4" stroke-width="4"
t-tooltip="remove_key" t-tooltip="remove_key"
@ -94,4 +79,9 @@ const onRefresh = () => {
</div> </div>
</template> </template>
<style lang="scss" scoped></style> <style scoped lang="scss">
.nav-pane-bottom {
color: v-bind('themeVars.iconColor');
border-top: v-bind('themeVars.borderColor') 1px solid;
}
</style>

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import useDialogStore from '../../stores/dialog.js' import useDialogStore from '../../stores/dialog.js'
import { NIcon } from 'naive-ui' import { NIcon, useThemeVars } from 'naive-ui'
import AddGroup from '../icons/AddGroup.vue' import AddGroup from '../icons/AddGroup.vue'
import AddLink from '../icons/AddLink.vue' import AddLink from '../icons/AddLink.vue'
import IconButton from '../common/IconButton.vue' import IconButton from '../common/IconButton.vue'
@ -10,6 +10,7 @@ import Unlink from '../icons/Unlink.vue'
import useConnectionStore from '../../stores/connections.js' import useConnectionStore from '../../stores/connections.js'
import { ref } from 'vue' import { ref } from 'vue'
const themeVars = useThemeVars()
const dialogStore = useDialogStore() const dialogStore = useDialogStore()
const connectionStore = useConnectionStore() const connectionStore = useConnectionStore()
const filterPattern = ref('') const filterPattern = ref('')
@ -27,7 +28,6 @@ const onDisconnectAll = () => {
<div class="nav-pane-bottom flex-box-h"> <div class="nav-pane-bottom flex-box-h">
<icon-button <icon-button
:icon="AddLink" :icon="AddLink"
color="#555"
size="20" size="20"
stroke-width="4" stroke-width="4"
t-tooltip="new_conn" t-tooltip="new_conn"
@ -35,7 +35,6 @@ const onDisconnectAll = () => {
/> />
<icon-button <icon-button
:icon="AddGroup" :icon="AddGroup"
color="#555"
size="20" size="20"
stroke-width="4" stroke-width="4"
t-tooltip="new_group" t-tooltip="new_group"
@ -44,7 +43,6 @@ const onDisconnectAll = () => {
<icon-button <icon-button
:disabled="!connectionStore.anyConnectionOpened" :disabled="!connectionStore.anyConnectionOpened"
:icon="Unlink" :icon="Unlink"
color="#555"
size="20" size="20"
stroke-width="4" stroke-width="4"
t-tooltip="disconnect_all" t-tooltip="disconnect_all"
@ -59,4 +57,9 @@ const onDisconnectAll = () => {
</div> </div>
</template> </template>
<style lang="scss" scoped></style> <style scoped lang="scss">
.nav-pane-bottom {
color: v-bind('themeVars.iconColor');
border-top: v-bind('themeVars.borderColor') 1px solid;
}
</style>

View File

@ -1,12 +1,12 @@
<script setup> <script setup>
import useDialogStore from '../../stores/dialog.js' import useDialogStore from '../../stores/dialog.js'
import { h, nextTick, onMounted, reactive, ref } from 'vue' import { h, nextTick, reactive, ref } from 'vue'
import useConnectionStore from '../../stores/connections.js' import useConnectionStore from '../../stores/connections.js'
import { NIcon, useDialog, useMessage } from 'naive-ui' import { NIcon, useDialog, useMessage } from 'naive-ui'
import { ConnectionType } from '../../consts/connection_type.js' import { ConnectionType } from '../../consts/connection_type.js'
import ToggleFolder from '../icons/ToggleFolder.vue' import ToggleFolder from '../icons/ToggleFolder.vue'
import ToggleServer from '../icons/ToggleServer.vue' import ToggleServer from '../icons/ToggleServer.vue'
import { debounce, indexOf, throttle } from 'lodash' import { debounce, indexOf } from 'lodash'
import Config from '../icons/Config.vue' import Config from '../icons/Config.vue'
import Delete from '../icons/Delete.vue' import Delete from '../icons/Delete.vue'
import Unlink from '../icons/Unlink.vue' import Unlink from '../icons/Unlink.vue'

View File

@ -114,7 +114,7 @@ const openGithub = () => {
:collapsed-icon-size="iconSize" :collapsed-icon-size="iconSize"
@update:value="(val) => emit('update:value', val)" @update:value="(val) => emit('update:value', val)"
:options="menuOptions" :options="menuOptions"
></n-menu> />
<div class="flex-item-expand"></div> <div class="flex-item-expand"></div>
<div class="nav-menu-item flex-box-v"> <div class="nav-menu-item flex-box-v">
<n-dropdown <n-dropdown
@ -127,7 +127,7 @@ const openGithub = () => {
> >
<icon-button :icon="Config" :size="iconSize" class="nav-menu-button" /> <icon-button :icon="Config" :size="iconSize" class="nav-menu-button" />
</n-dropdown> </n-dropdown>
<icon-button :icon="Github" :size="iconSize" class="nav-menu-button" @click="openGithub"></icon-button> <icon-button :icon="Github" :size="iconSize" class="nav-menu-button" @click="openGithub" />
</div> </div>
</div> </div>
</template> </template>
@ -136,7 +136,7 @@ const openGithub = () => {
#app-nav-menu { #app-nav-menu {
//width: 60px; //width: 60px;
height: 100vh; height: 100vh;
border-right: var(--border-color) solid 1px; border-right: v-bind('themeVars.borderColor') solid 1px;
.nav-menu-item { .nav-menu-item {
align-items: center; align-items: center;

View File

@ -102,6 +102,10 @@
"score": "Score", "score": "Score",
"order_no": "Order", "order_no": "Order",
"preferences": "Preferences", "preferences": "Preferences",
"theme": "Theme",
"theme_light": "Light",
"theme_dark": "Dark",
"theme_auto": "Auto",
"language": "Language", "language": "Language",
"font": "Font", "font": "Font",
"font_size": "Font Size", "font_size": "Font Size",

View File

@ -105,6 +105,10 @@
"score": "分值", "score": "分值",
"order_no": "序号", "order_no": "序号",
"preferences": "偏好设置", "preferences": "偏好设置",
"theme": "主题",
"theme_light": "浅色",
"theme_dark": "深色",
"theme_auto": "自动",
"language": "语言", "language": "语言",
"font": "字体", "font": "字体",
"font_size": "字体尺寸", "font_size": "字体尺寸",

View File

@ -27,13 +27,14 @@ const usePreferencesStore = defineStore('preferences', {
*/ */
state: () => ({ state: () => ({
general: { general: {
theme: 'light',
language: 'en', language: 'en',
font: '', font: '',
fontSize: 14, fontSize: 14,
useSysProxy: false, useSysProxy: false,
useSysProxyHttp: false, useSysProxyHttp: false,
checkUpdate: false, checkUpdate: false,
navMenuWidth: 300, asideWidth: 300,
}, },
editor: { editor: {
font: '', font: '',
@ -47,6 +48,24 @@ const usePreferencesStore = defineStore('preferences', {
return ':' return ':'
}, },
themeOption() {
const i18n = useI18n()
return [
{
value: 'light',
label: i18n.t('theme_light'),
},
{
value: 'dark',
label: i18n.t('theme_dark'),
},
{
value: 'auto',
label: i18n.t('theme_auto'),
},
]
},
/** /**
* all available language * all available language
* @returns {{label: string, value: string}[]} * @returns {{label: string, value: string}[]}
@ -58,6 +77,10 @@ const usePreferencesStore = defineStore('preferences', {
})) }))
}, },
/**
* all system font list
* @returns {{path: string, label: string, value: string}[]}
*/
fontOption() { fontOption() {
const i18n = useI18n() const i18n = useI18n()
const option = map(this.fontList, (font) => ({ const option = map(this.fontList, (font) => ({
@ -73,6 +96,10 @@ const usePreferencesStore = defineStore('preferences', {
return option return option
}, },
/**
* current font selection
* @returns {{fontSize: string}}
*/
generalFont() { generalFont() {
const fontStyle = { const fontStyle = {
fontSize: this.general.fontSize + 'px', fontSize: this.general.fontSize + 'px',
@ -167,8 +194,8 @@ const usePreferencesStore = defineStore('preferences', {
return false return false
}, },
setNavWidth(width) { setAsideWidth(width) {
this.general.navMenuWidth = width this.general.asideWidth = width
}, },
}, },
}) })

View File

@ -1,14 +1,13 @@
:root { :root {
--bg-color: #ffffff; //--bg-color: #ffffff;
--bg-color-page: #f2f3f5; //--bg-color-page: #f2f3f5;
--text-color-regular: #606266; //--text-color-regular: #606266;
--border-color: #dcdfe6; //--border-color: #dcdfe6;
--transition-duration-fast: 0.2s; --transition-duration-fast: 0.2s;
--transition-function-ease-in-out-bezier: cubic-bezier(0.645, 0.045, 0.355, 1); --transition-function-ease-in-out-bezier: cubic-bezier(0.645, 0.045, 0.355, 1);
} }
html { html {
background-color: #ffffff;
//text-align: center; //text-align: center;
cursor: default; cursor: default;
-webkit-user-select: none; /* Chrome, Safari */ -webkit-user-select: none; /* Chrome, Safari */
@ -82,8 +81,8 @@ body {
} }
.content-wrapper { .content-wrapper {
background-color: var(--bg-color); //height: 100%;
height: 100%; flex-grow: 1;
overflow: hidden; overflow: hidden;
gap: 5px; gap: 5px;
padding: 5px; padding: 5px;
@ -96,7 +95,7 @@ body {
} }
.value-wrapper { .value-wrapper {
border-top: var(--border-color) 1px solid; //border-top: v-bind('themeVars.borderColor') 1px solid;
padding: 5px; padding: 5px;
user-select: text; user-select: text;
} }
@ -118,13 +117,12 @@ body {
.nav-pane-container { .nav-pane-container {
overflow: hidden; overflow: hidden;
background-color: var(--bg-color);
.nav-pane-bottom { .nav-pane-bottom {
align-items: center; align-items: center;
gap: 8px; gap: 8px;
padding: 3px 5px 5px 5px; padding: 3px 5px 5px 5px;
min-height: 35px; min-height: 35px;
border-top: var(--border-color) 1px solid; //border-top: v-bind('themeVars.borderColor') 1px solid;
} }
} }