support theming

This commit is contained in:
lightling 2024-04-05 00:23:50 -04:00
parent 48b8f132d6
commit fb120750ab
4 changed files with 58 additions and 9 deletions

View file

@ -0,0 +1,39 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { injectStylesheet } from 'src/utilities/dom'
import { storage } from 'src/utilities/fetch'
import { useRouteStore } from 'src/routes'
const routeStore = useRouteStore()
const globalConfig = routeStore._globals
const options = ref(globalConfig.themes)
const currentTheme = ref('')
let node: HTMLLinkElement
const onThemeChosen = (event: Event) => {
storage.write(`${globalConfig.id}::currentTheme`, currentTheme.value)
node.setAttribute('href', globalConfig.themes[currentTheme.value].url)
}
onMounted(async () => {
currentTheme.value = storage.read(`${globalConfig.id}::currentTheme`) || Object.keys(globalConfig.themes)[0]
node = injectStylesheet(globalConfig.themes[currentTheme.value].url, 'theme-stylesheet')
})
</script>
<template lang="pug">
.theme-picker
select(
v-model='currentTheme'
@change='onThemeChosen($event)'
)
option(
v-for='(option, key) in options'
:value='key'
) {{ option.displayName|| option }}
</template>
<style scoped lang="sass">
</style>

View file

@ -3,12 +3,14 @@ import { onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { getCurrentRoute } from 'src/utilities/vuetils'
import { injectStylesheet } from 'src/utilities/dom'
import { storage } from './utilities/fetch'
import { useRouteStore } from 'src/routes'
import type { WarningModal } from 'content/routes.js'
import HeaderLink from 'src/components/shared/header-link.vue'
import ThemePicker from 'src/components/shared/theme-picker.vue'
import WarningPrompt from 'src/components/shared/warning-prompt.vue'
const router = useRouter()
@ -40,14 +42,6 @@ const determineWarning = () => {
: routeConfig.warning
}
const injectStylesheet = (url: string, className: string) => {
const newElement = document.createElement('link')
newElement.setAttribute('rel', 'stylesheet')
newElement.setAttribute('href', url)
newElement.classList.add(className)
document.head.appendChild(newElement)
}
const determineStylesheets = (stylesheetUrls?: string[]) => {
const staleStylesheets = document.head.querySelectorAll('link.page-stylesheet[rel="stylesheet"]')
staleStylesheets.forEach(stylesheet => {
@ -105,6 +99,7 @@ onMounted(async () => {
v-for='entry in globalConfig.header'
:entry='entry'
)
ThemePicker
main(
v-if='ready'
)

View file

@ -71,7 +71,7 @@ export const useRouteStore = defineStore('routeStore', {
},
rememberRouteWarning(route: string) {
this._routesAlreadyWarned[route] = true
}
},
},
})

View file

@ -4,6 +4,21 @@ import { type DateRange } from 'src/types/shared/dateRange'
export const deepCopy = rfdc()
/**
* Injects a stylesheet link into th ehead of the document
* @param url the url of the stylesheet
* @param className the classname to give the stylesheet
*/
export const injectStylesheet = (url: string, className: string) => {
const newElement = document.createElement('link')
newElement.setAttribute('rel', 'stylesheet')
newElement.setAttribute('href', url)
newElement.classList.add(className)
document.head.appendChild(newElement)
return newElement
}
/**
* Runs element.querySelector for every selector in the order they were passed in until an element is found
* @param element the element to query children from