frontend/components/Settings/AppSettings/Appearance.vue
JustTemmie 441dc0c15c
All checks were successful
ci/woodpecker/push/build-and-publish Pipeline was successful
ci/woodpecker/pr/build-and-publish Pipeline was successful
feat: actually add theme switching :mind_blown:
2025-07-05 17:36:08 +02:00

103 lines
2.3 KiB
Vue

<template>
<div>
<h1>Appearance</h1>
<p class="subtitle">THEMES</p>
<div class="themes">
<div v-for="theme of themes" class="theme-preview-container">
<span class="theme-preview"
:title="theme.displayName"
:style="{background:`linear-gradient(${theme.previewGradient})`}"
@click="changeTheme(theme.ID, theme.themeURL)"
>
<span class="theme-title" :style="{color:`${theme.complementaryColor}`}">
{{ theme.displayName }}
</span>
</span>
</div>
</div>
<p class="subtitle">ICONS</p>
<div class="themes">
</div>
</div>
</template>
<script lang="ts" setup>
const runtimeConfig = useRuntimeConfig()
const defaultThemes = runtimeConfig.public.defaultThemes
const baseURL = runtimeConfig.app.baseURL;
let themeLinkElement: HTMLLinkElement | null = null;
const themes: Array<Theme> = []
interface Theme {
ID: string
displayName: string
previewGradient: string
complementaryColor: string
themeURL: string
}
function changeTheme(ID: string, URL: string) {
if (themeLinkElement && themeLinkElement.getAttribute('href') === `${baseURL}themes/${URL}`) {
return;
}
localStorage.setItem("selectedTheme", ID);
// if the theme didn't originally load for some reason, create it
if (!themeLinkElement) {
themeLinkElement = document.createElement('link');
themeLinkElement.rel = 'stylesheet';
document.head.appendChild(themeLinkElement);
}
themeLinkElement.href = `${baseURL}themes/${URL}`;
}
const fetchThemes = async () => {
for (const theme of defaultThemes) {
const themeConfig = await fetch(`${baseURL}themes/${theme}.json`)
const themeConfigJson = await themeConfig.json() as Theme
themeConfigJson.ID = theme
themes.push(themeConfigJson)
}
console.log(themes)
}
await fetchThemes()
</script>
<style scoped>
.themes {
display: flex;
}
.theme-preview-container {
margin: .5em;
width: 5em;
height: 5em;
}
.theme-preview {
width: 5em;
height: 5em;
border-radius: 100%;
border: .1em solid var(--primary-color);
display: inline-block;
text-align: center;
align-content: center;
cursor: pointer;
}
.theme-title {
font-size: .8em;
line-height: 5em; /* same height as the parent to centre it vertically */
}
</style>