Skip to content

Commit

Permalink
Color css variables must be rendered on app root element, not body (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Fsss126 committed Jun 2, 2024
1 parent 0ffdb22 commit 995ce95
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 10 deletions.
5 changes: 4 additions & 1 deletion packages/ui/src/composables/useTeleported.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export const findTeleportedFrom = (el: HTMLElement | undefined | null): HTMLElem
export const useTeleported = () => {
const componentId = useCurrentComponentId()

const scopedDataV = getCurrentInstance()?.vnode.scopeId
const currentInstance = getCurrentInstance()

const scopedDataV = currentInstance?.vnode.scopeId

return {
teleportFromAttrs: {
Expand All @@ -35,6 +37,7 @@ export const useTeleported = () => {
teleportedAttrs: {
[TELEPORT_ATTR]: componentId,
...(scopedDataV ? { [scopedDataV]: '' } : undefined),
...currentInstance?.appContext.config?.globalProperties?.$vaColorConfig.getAppStylesRootAttribute(),
},
findTeleportedFrom,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { PartialGlobalConfig } from './../../global-config/types'
import { ColorVariables } from './../types'
import { App, watch, computed } from 'vue'
import { App, watch, computed, onMounted } from 'vue'
import { isServer } from '../../../utils/ssr'
import { cssVariableName } from '../utils'
import { useColors } from '../../../composables'
import { generateUniqueId } from '../../../utils/uuid'
import { addOrUpdateStyleElement } from '../../../utils/dom'
import { addOrUpdateStyleElement, removeStyleElement } from '../../../utils/dom'
import { isDev } from '../../../utils/env'

export const setCSSVariable = (name: string, value: string, root: HTMLElement) => {
root.style.setProperty(cssVariableName(name), value)
Expand All @@ -15,6 +16,10 @@ export const generateCSSVariable = (key: string, value: string) => {
return `${cssVariableName(key)}: ${value};\n`
}

const stylesRootAttr = 'data-va-styles-root'

const getStyleElementId = (id: string | number) => `va-color-variables-${id}`

export const createColorConfigPlugin = (app: App, config?: PartialGlobalConfig) => {
const { colors: configColors, getTextColor, getColor, currentPresetName, applyPreset } = useColors()

Expand All @@ -29,10 +34,11 @@ export const createColorConfigPlugin = (app: App, config?: PartialGlobalConfig)
return `${renderedColors};${renderedOnColors}`
}

const renderCSSVariablesStyleContent = (colors: ColorVariables = configColors) => {
const renderCSSVariablesStyleContent = (colors: ColorVariables = configColors, selector = ':root') => {
const colorNames = Object.keys(colors)

let result = ':root {\n'
let result = `${selector} {
`
colorNames.forEach((key) => {
result += generateCSSVariable(key, colors[key])
})
Expand All @@ -44,15 +50,38 @@ export const createColorConfigPlugin = (app: App, config?: PartialGlobalConfig)
return result
}

const uniqueId = computed(generateUniqueId)
const uniqueId = computed(() => app._uid)

const stylesRootSelector = computed(() => `[${stylesRootAttr}="${uniqueId.value}"]`)

const updateColors = (newValue: ColorVariables | undefined) => {
if (!newValue) { return }
if (isServer()) { return }
if (!newValue || isServer()) { return }

const styleContent = renderCSSVariablesStyleContent(newValue, stylesRootSelector.value)

const styleContent = renderCSSVariablesStyleContent(newValue)
addOrUpdateStyleElement(getStyleElementId(uniqueId.value), () => styleContent)
}

function getAppStylesRootAttribute () {
return { [stylesRootAttr]: uniqueId.value }
}

addOrUpdateStyleElement(`va-color-variables-${uniqueId.value}`, () => styleContent)
const origMount = app.mount

app.mount = function (...args: Parameters<typeof origMount>) {
const result = origMount.apply(this, args)
const appRootElement = app._container as HTMLElement

// Remove previous styles when remounting to the same root element (happens on HMR)
const existingStylesId = appRootElement.getAttribute(stylesRootAttr)

if (existingStylesId && existingStylesId !== uniqueId.value.toString()) {
removeStyleElement(getStyleElementId(existingStylesId))
}

appRootElement.setAttribute(stylesRootAttr, uniqueId.value.toString())

return result
}

watch(configColors, (newValue) => {
Expand All @@ -62,6 +91,7 @@ export const createColorConfigPlugin = (app: App, config?: PartialGlobalConfig)
return {
colors: configColors,
currentPresetName,
getAppStylesRootAttribute,
renderCSSVariables,
updateColors,
renderCSSVariablesStyleContent,
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/utils/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ export const addOrUpdateStyleElement = (id: string, getStyles: () => string): vo
document.head.append(stylesElement)
}
}

export const removeStyleElement = (id: string): void => {
document.getElementById(id)?.remove()
}

0 comments on commit 995ce95

Please sign in to comment.