mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-03-08 04:50:45 +08:00
feat(ui): add theme manager and dark mode
This commit is contained in:
@@ -5,19 +5,36 @@
|
|||||||
--header-height: 60px;
|
--header-height: 60px;
|
||||||
--header-background-color: white;
|
--header-background-color: white;
|
||||||
--header-border-color: lightgray;
|
--header-border-color: lightgray;
|
||||||
|
--header-text-color: black;
|
||||||
--menu-background-color: white;
|
--menu-background-color: white;
|
||||||
--menu-border-color: lightgray;
|
--menu-border-color: lightgray;
|
||||||
--menu-selected-background-color: rgba(208, 250, 255, 0.659);
|
--menu-selected-background-color: rgba(208, 250, 255, 0.659);
|
||||||
|
--menu-text-color: black;
|
||||||
--scroller-background-color: rgba(130, 175, 180, 0.5);
|
--scroller-background-color: rgba(130, 175, 180, 0.5);
|
||||||
--normal-background-color: rgb(241, 241, 241);
|
--normal-background-color: rgb(241, 241, 241);
|
||||||
|
--text-color: black;
|
||||||
--menu-width: 200px;
|
--menu-width: 200px;
|
||||||
--page-max-width: 1200px;
|
--page-max-width: 1200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-theme='dark'] {
|
||||||
|
--header-background-color: #2b2b2b;
|
||||||
|
--header-border-color: #555;
|
||||||
|
--header-text-color: white;
|
||||||
|
--menu-background-color: #333;
|
||||||
|
--menu-border-color: #555;
|
||||||
|
--menu-selected-background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
--menu-text-color: white;
|
||||||
|
--normal-background-color: #121212;
|
||||||
|
--text-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-family: 'Roboto', sans-serif;
|
font-family: 'Roboto', sans-serif;
|
||||||
|
background-color: var(--normal-background-color);
|
||||||
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="menu-footer">
|
<div class="menu-footer">
|
||||||
<div class="menu-footer-btn" @click="$emit('toggle-dark-mode')">
|
<div class="menu-footer-btn" @click="cycleTheme">
|
||||||
<i class="fas fa-moon"></i>
|
<i :class="iconClass"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { themeState, cycleTheme, ThemeMode } from '../utils/theme'
|
||||||
export default {
|
export default {
|
||||||
name: 'MenuComponent',
|
name: 'MenuComponent',
|
||||||
props: {
|
props: {
|
||||||
@@ -37,7 +38,20 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
computed: {
|
||||||
|
iconClass() {
|
||||||
|
switch (themeState.mode) {
|
||||||
|
case ThemeMode.DARK:
|
||||||
|
return 'fas fa-moon'
|
||||||
|
case ThemeMode.LIGHT:
|
||||||
|
return 'fas fa-sun'
|
||||||
|
default:
|
||||||
|
return 'fas fa-desktop'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: { cycleTheme }
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import Toast, { POSITION } from 'vue-toastification'
|
|||||||
import 'vue-toastification/dist/index.css'
|
import 'vue-toastification/dist/index.css'
|
||||||
import { useToast } from 'vue-toastification'
|
import { useToast } from 'vue-toastification'
|
||||||
import { checkToken, clearToken } from './utils/auth'
|
import { checkToken, clearToken } from './utils/auth'
|
||||||
|
import { initTheme } from './utils/theme'
|
||||||
|
|
||||||
// Configurable API domain and port
|
// Configurable API domain and port
|
||||||
export const API_DOMAIN = 'http://127.0.0.1'
|
export const API_DOMAIN = 'http://127.0.0.1'
|
||||||
@@ -14,6 +15,8 @@ export const API_BASE_URL = API_PORT ? `${API_DOMAIN}:${API_PORT}` : API_DOMAIN
|
|||||||
export const GOOGLE_CLIENT_ID = '777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com'
|
export const GOOGLE_CLIENT_ID = '777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com'
|
||||||
export const toast = useToast()
|
export const toast = useToast()
|
||||||
|
|
||||||
|
initTheme()
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.use(Toast, { position: POSITION.TOP_RIGHT })
|
app.use(Toast, { position: POSITION.TOP_RIGHT })
|
||||||
|
|||||||
52
open-isle-cli/src/utils/theme.js
Normal file
52
open-isle-cli/src/utils/theme.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { reactive } from 'vue'
|
||||||
|
|
||||||
|
export const ThemeMode = {
|
||||||
|
SYSTEM: 'system',
|
||||||
|
LIGHT: 'light',
|
||||||
|
DARK: 'dark'
|
||||||
|
}
|
||||||
|
|
||||||
|
const THEME_KEY = 'theme-mode'
|
||||||
|
|
||||||
|
export const themeState = reactive({
|
||||||
|
mode: ThemeMode.SYSTEM
|
||||||
|
})
|
||||||
|
|
||||||
|
function apply(mode) {
|
||||||
|
const root = document.documentElement
|
||||||
|
if (mode === ThemeMode.SYSTEM) {
|
||||||
|
root.dataset.theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||||
|
} else {
|
||||||
|
root.dataset.theme = mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initTheme() {
|
||||||
|
const saved = localStorage.getItem(THEME_KEY)
|
||||||
|
if (saved && Object.values(ThemeMode).includes(saved)) {
|
||||||
|
themeState.mode = saved
|
||||||
|
}
|
||||||
|
apply(themeState.mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setTheme(mode) {
|
||||||
|
if (!Object.values(ThemeMode).includes(mode)) return
|
||||||
|
themeState.mode = mode
|
||||||
|
localStorage.setItem(THEME_KEY, mode)
|
||||||
|
apply(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cycleTheme() {
|
||||||
|
const modes = [ThemeMode.SYSTEM, ThemeMode.LIGHT, ThemeMode.DARK]
|
||||||
|
const index = modes.indexOf(themeState.mode)
|
||||||
|
const next = modes[(index + 1) % modes.length]
|
||||||
|
setTheme(next)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.matchMedia) {
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
||||||
|
if (themeState.mode === ThemeMode.SYSTEM) {
|
||||||
|
apply(ThemeMode.SYSTEM)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user