refactor: change theme handling to support element-ui scss variables

This commit is contained in:
pa
2025-07-27 21:39:10 +09:00
committed by Natsumi
parent 96dfe2fcef
commit def96c1a4d
6 changed files with 91 additions and 98 deletions
+5 -3
View File
@@ -8,12 +8,14 @@
// For a copy, see <https://opensource.org/licenses/MIT>. // For a copy, see <https://opensource.org/licenses/MIT>.
// //
@use "./assets/scss/flags.scss"; $--font-path: '~element-ui/lib/theme-chalk/fonts';
@use "./assets/scss/animated-emoji.scss";
@use './assets/scss/flags.scss';
@use './assets/scss/animated-emoji.scss';
@import '~animate.css/animate.min.css'; @import '~animate.css/animate.min.css';
@import '~noty/lib/noty.css'; @import '~noty/lib/noty.css';
@import '~element-ui/lib/theme-chalk/index.css'; @import '~element-ui/packages/theme-chalk/src/index';
.color-palettes { .color-palettes {
background: #409eff; background: #409eff;
+1
View File
@@ -9,3 +9,4 @@ export * from './user';
export * from './instance'; export * from './instance';
export * from './world'; export * from './world';
export * from './moderation'; export * from './moderation';
export * from './themes';
+39
View File
@@ -0,0 +1,39 @@
export const THEME_CONFIG = {
system: {
cssFile: '',
requiresDarkBase: false,
isDark: 'system',
name: 'System'
},
light: {
cssFile: '',
requiresDarkBase: false,
isDark: false,
name: 'Light'
},
dark: { cssFile: '', requiresDarkBase: true, isDark: true, name: 'Dark' },
darkvanillaold: {
cssFile: 'theme.darkvanillaold.css',
requiresDarkBase: true,
isDark: true,
name: 'Dark Vanilla Old'
},
darkvanilla: {
cssFile: 'theme.darkvanilla.css',
requiresDarkBase: true,
isDark: true,
name: 'Dark Vanilla'
},
pink: {
cssFile: 'theme.pink.css',
requiresDarkBase: true,
isDark: true,
name: 'Pink'
},
material3: {
cssFile: 'theme.material3.css',
requiresDarkBase: true,
isDark: true,
name: 'Material 3'
}
};
+24 -59
View File
@@ -1,5 +1,6 @@
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useAppearanceSettingsStore } from '../../../stores'; import { useAppearanceSettingsStore } from '../../../stores';
import { THEME_CONFIG } from '../../constants';
/** /**
* *
@@ -21,43 +22,10 @@ function changeAppDarkStyle(isDark) {
} }
} }
/**
*
* @param {string} themeMode
* @returns
*/
function changeAppThemeStyle(themeMode) { function changeAppThemeStyle(themeMode) {
const themeStyle = {}; const themeConfig = THEME_CONFIG[themeMode];
switch (themeMode) { if (!themeConfig) return;
case 'light':
themeStyle.href = '';
break;
case 'dark':
themeStyle.href = '';
break;
case 'darkvanillaold':
themeStyle.href = 'theme.darkvanillaold.css';
break;
case 'darkvanilla':
themeStyle.href = 'theme.darkvanilla.css';
break;
case 'pink':
themeStyle.href = 'theme.pink.css';
break;
case 'material3':
themeStyle.href = 'theme.material3.css';
break;
case 'system':
themeStyle.href = '';
break;
}
/**
* prevents flickering
* giving absolute paths does prevent flickering
* when switching from another dark theme to 'dark' theme
* <del>works on my machine</del>
*/
let filePathPrefix = 'file://vrcx/'; let filePathPrefix = 'file://vrcx/';
if (LINUX) { if (LINUX) {
filePathPrefix = './'; filePathPrefix = './';
@@ -70,38 +38,35 @@ function changeAppThemeStyle(themeMode) {
$appThemeStyle.rel = 'stylesheet'; $appThemeStyle.rel = 'stylesheet';
document.head.appendChild($appThemeStyle); document.head.appendChild($appThemeStyle);
} }
$appThemeStyle.href = themeStyle.href $appThemeStyle.href = themeConfig.cssFile
? `${filePathPrefix}${themeStyle.href}` ? `${filePathPrefix}${themeConfig.cssFile}`
: ''; : '';
let $appThemeDarkStyle = document.getElementById('app-theme-dark-style'); let $appThemeDarkStyle = document.getElementById('app-theme-dark-style');
const darkThemeCssPath = `${filePathPrefix}theme.dark.css`; const darkThemeCssPath = `${filePathPrefix}theme.dark.css`;
const shouldApplyDarkBase =
themeConfig.requiresDarkBase ||
(themeMode === 'system' && systemIsDarkMode());
if (!$appThemeDarkStyle && themeMode !== 'light') { if (shouldApplyDarkBase) {
if (themeMode === 'system' && !systemIsDarkMode()) { if (!$appThemeDarkStyle) {
return; $appThemeDarkStyle = document.createElement('link');
$appThemeDarkStyle.setAttribute('id', 'app-theme-dark-style');
$appThemeDarkStyle.rel = 'stylesheet';
$appThemeDarkStyle.href = darkThemeCssPath;
document.head.insertBefore($appThemeDarkStyle, $appThemeStyle);
} else if ($appThemeDarkStyle.href !== darkThemeCssPath) {
$appThemeDarkStyle.href = darkThemeCssPath;
} }
$appThemeDarkStyle = document.createElement('link');
$appThemeDarkStyle.setAttribute('id', 'app-theme-dark-style');
$appThemeDarkStyle.rel = 'stylesheet';
$appThemeDarkStyle.href = darkThemeCssPath;
document.head.insertBefore($appThemeDarkStyle, $appThemeStyle);
} else { } else {
if (themeMode === 'system' && systemIsDarkMode()) { $appThemeDarkStyle && $appThemeDarkStyle.remove();
if ($appThemeDarkStyle.href === darkThemeCssPath) {
return;
}
$appThemeDarkStyle.href = darkThemeCssPath;
} else if (themeMode !== 'light' && themeMode !== 'system') {
if ($appThemeDarkStyle.href === darkThemeCssPath) {
return;
}
$appThemeDarkStyle.href = darkThemeCssPath;
} else {
$appThemeDarkStyle && $appThemeDarkStyle.remove();
}
} }
let isDarkForExternalApp = themeConfig.isDark;
if (isDarkForExternalApp === 'system') {
isDarkForExternalApp = systemIsDarkMode();
}
changeAppDarkStyle(isDarkForExternalApp);
} }
/** /**
+7 -34
View File
@@ -340,40 +340,12 @@
</el-button> </el-button>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item <el-dropdown-item
@click.native="saveThemeMode('system')" v-for="(config, themeKey) in THEME_CONFIG"
v-text=" :key="themeKey"
t('view.settings.appearance.appearance.theme_mode_system') @click.native="saveThemeMode(themeKey)"
"></el-dropdown-item> :class="{ 'is-active': themeMode === themeKey }">
<el-dropdown-item {{ t(`view.settings.appearance.appearance.theme_mode_${themeKey}`) }}
@click.native="saveThemeMode('light')" </el-dropdown-item>
v-text="
t('view.settings.appearance.appearance.theme_mode_light')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('dark')"
v-text="
t('view.settings.appearance.appearance.theme_mode_dark')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('darkvanilla')"
v-text="
t('view.settings.appearance.appearance.theme_mode_darkvanilla')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('darkvanillaold')"
v-text="
t('view.settings.appearance.appearance.theme_mode_darkvanillaold')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('pink')"
v-text="
t('view.settings.appearance.appearance.theme_mode_pink')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('material3')"
v-text="
t('view.settings.appearance.appearance.theme_mode_material3')
"></el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</div> </div>
@@ -1885,6 +1857,7 @@
import FeedFiltersDialog from './dialogs/FeedFiltersDialog.vue'; import FeedFiltersDialog from './dialogs/FeedFiltersDialog.vue';
import AvatarProviderDialog from './dialogs/AvatarProviderDialog.vue'; import AvatarProviderDialog from './dialogs/AvatarProviderDialog.vue';
import { openExternalLink } from '../../shared/utils'; import { openExternalLink } from '../../shared/utils';
import { THEME_CONFIG } from '../../shared/constants';
const { messages, t } = useI18n(); const { messages, t } = useI18n();
const { $message } = getCurrentInstance().proxy; const { $message } = getCurrentInstance().proxy;
+15 -2
View File
@@ -64,7 +64,14 @@ module.exports = (env, argv) => {
use: [ use: [
MiniCssExtractPlugin.loader, MiniCssExtractPlugin.loader,
'css-loader', 'css-loader',
'sass-loader' {
loader: 'sass-loader',
options: {
sassOptions: {
quietDeps: true
}
}
}
] ]
}, },
{ {
@@ -77,7 +84,13 @@ module.exports = (env, argv) => {
] ]
}, },
devServer: { devServer: {
port: 9000 port: 9000,
client: {
overlay: {
warnings: false,
errors: true
}
}
}, },
resolve: { resolve: {
extensions: ['.js', '.vue', '.css', '.scss'], extensions: ['.js', '.vue', '.css', '.scss'],