Skip to content

Commit 260114b

Browse files
committed
refactor(custom/colors): Use useStyleTag for injecting accent color styles
- Refactor custom accent color logic to avoid directly updating CSS variables, which caused resets and disappearance from body styles on window resize - Replace manual creation and injection of `<style>` tags with `vueuse`'s `useStyleTag` utility - Ensure accent color styles are consistently applied without latency, lag, or DOM freezing - Improve performance and reliability by leveraging `useStyleTag` for dynamic style injection Changes summary: - Refactored the custom accent color logic to use `vueuse`'s `useStyleTag` for injecting styles into the document head. This approach eliminates issues with CSS variables being reset or disappearing during window resize, while also removing latency, lag, and DOM freezing that occurred with manual `<style>` tag injection. The result is a smoother and more reliable implementation.
1 parent 1b4d39d commit 260114b

1 file changed

Lines changed: 36 additions & 34 deletions

File tree

components/Custom/Colors/Index.vue

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
<template>
22
<section class="section-colors colors">
33
<div class="section-cards">
4-
<ColorPicker
4+
<!-- <ColorPicker
55
v-for="picker in colorPickers"
66
:key="picker.id"
77
:id="picker.id"
88
:mode="picker.mode"
99
v-model="picker.model"
1010
@change="picker.handler"
11-
/>
11+
/> -->
1212

13-
<!-- <ColorPicker id="lightColor" v-model="lightHex" mode="Light" @change="saveLight" />
14-
<ColorPicker id="darkColor" v-model="darkHex" mode="Dark" @change="saveDark" /> -->
13+
<ColorPicker id="lightColor" v-model="lightHex" mode="Light" @change="saveLight" />
14+
<ColorPicker id="darkColor" v-model="darkHex" mode="Dark" @change="saveDark" />
1515
</div>
1616

1717
<Separator />
@@ -32,8 +32,8 @@
3232
</template>
3333

3434
<script setup>
35-
import { onMounted, watch, ref } from 'vue'
36-
import { useCssVar } from '@vueuse/core'
35+
import { onMounted, watch, computed } from 'vue'
36+
import { useStyleTag } from '@vueuse/core'
3737
import { useAccentColors } from '@/composables/useAccentColors.js'
3838
import ColorPicker from '@/components/Custom/Colors/ColorPicker.vue'
3939
import ButtonPrimary from '@/components/ButtonPrimary.vue'
@@ -44,42 +44,44 @@ import Separator from '@/components/Separator.vue'
4444
import { accentUserBubbleItem } from '@/utils/storage'
4545
import { useToggleStorage } from '@/composables/useToggleStorage.js'
4646
47-
// toggle
4847
const toggleAccentUserBubble = useToggleStorage(accentUserBubbleItem, 'dsx-toggle-accent-user-bubble')
4948
5049
const { lightHex, darkHex, load, saveLight, saveDark, reset, lightHSL, darkHSL } = useAccentColors()
5150
52-
// Reactive array for color pickers
53-
const colorPickers = ref([
54-
{ id: 'lightColor', model: lightHex, mode: 'Light', handler: saveLight },
55-
{ id: 'darkColor', model: darkHex, mode: 'Dark', handler: saveDark },
56-
])
51+
const accentCSS = computed(() => {
52+
const [lightH, lightS, lightL] = lightHSL.value
53+
const [darkH, darkS, darkL] = darkHSL.value
5754
58-
// Apply CSS variables efficiently without reparsing stylesheets
59-
let rafId
60-
let cssH, cssS, cssL
61-
const applyLiveCssVars = () => {
62-
if (rafId) cancelAnimationFrame(rafId)
63-
rafId = requestAnimationFrame(() => {
64-
const isDark = document.body.classList.contains('dark')
65-
const h = isDark ? darkHSL.value[0] : lightHSL.value[0]
66-
const s = isDark ? darkHSL.value[1] : lightHSL.value[1]
67-
const l = isDark ? darkHSL.value[2] : lightHSL.value[2]
68-
cssH.value = String(h)
69-
cssS.value = `${s}%`
70-
cssL.value = `${l}%`
71-
})
72-
}
55+
return `
56+
body.light{
57+
--accent-h: ${String(lightH)} !important;
58+
--accent-s: ${lightS}% !important;
59+
--accent-l: ${lightL}% !important;
60+
}
61+
62+
body.dark{
63+
--accent-h: ${String(darkH)} !important;
64+
--accent-s: ${darkS}% !important;
65+
--accent-l: ${darkL}% !important;
66+
}
67+
`
68+
})
7369
74-
onMounted(async () => {
75-
// bind css vars to body element
76-
cssH = useCssVar('--accent-h', () => document.body)
77-
cssS = useCssVar('--accent-s', () => document.body)
78-
cssL = useCssVar('--accent-l', () => document.body)
70+
const {
71+
css,
72+
load: loadStyles,
73+
unload: unloadStyles,
74+
} = useStyleTag(accentCSS.value, { id: 'dsx-accent-styles', immediate: true })
7975
76+
// Update CSS when accent values change
77+
watch(accentCSS, (newCSS) => {
78+
css.value = newCSS
79+
})
80+
81+
onMounted(async () => {
8082
await load()
81-
applyLiveCssVars()
8283
})
8384
84-
watch([lightHSL, darkHSL], applyLiveCssVars, { deep: false })
85+
// optional: clean up on unmount if needed
86+
// onUnmounted(() => unloadStyles())
8587
</script>

0 commit comments

Comments
 (0)