diff --git a/packages/ui/src/components/va-button/VaButton.stories.ts b/packages/ui/src/components/va-button/VaButton.stories.ts
index 2149eea298..6c031f086d 100644
--- a/packages/ui/src/components/va-button/VaButton.stories.ts
+++ b/packages/ui/src/components/va-button/VaButton.stories.ts
@@ -1,5 +1,5 @@
import { defineComponent } from 'vue'
-import VaButton from './VaButton.vue'
+import { VaButton } from './'
import VaButtonDemo from './VaButton.demo.vue'
export default {
@@ -22,3 +22,12 @@ export const RightShift = () => ({
`,
})
+
+export const StyleAttributes = () => ({
+ components: { VaButton },
+ template: `
+
+ Text
+
+ `,
+})
diff --git a/packages/ui/src/components/va-button/VaButton.vue b/packages/ui/src/components/va-button/VaButton.vue
index bcc6a7c5cf..b624e41950 100644
--- a/packages/ui/src/components/va-button/VaButton.vue
+++ b/packages/ui/src/components/va-button/VaButton.vue
@@ -223,8 +223,8 @@ defineExpose({
}
&::before {
- background: v-bind(backgroundColor);
- opacity: v-bind(backgroundColorOpacity);
+ background: var(--va-button-background, v-bind(backgroundColor));
+ opacity: var(--va-button-background-opacity, v-bind(backgroundColorOpacity));
}
&::after {
diff --git a/packages/ui/src/composables/useColors.ts b/packages/ui/src/composables/useColors.ts
index 8631ff56e4..6b4dbc7984 100644
--- a/packages/ui/src/composables/useColors.ts
+++ b/packages/ui/src/composables/useColors.ts
@@ -60,20 +60,12 @@ export const useColors = () => {
return colors
}
- /**
+ /**
* Returns color from config variables by name or return prop if color is a valid hex, hsl, hsla, rgb or rgba color.
* @param prop - should be color name or color in hex, hsl, hsla, rgb or rgba format.
* @param preferVariables - function should return (if possible) CSS variable instead of hex (hex is needed to set opacity).
- * @param defaultColor - this color will be used if prop is invalid.
*/
- const getColor = (prop?: string, defaultColor?: string, preferVariables?: boolean): CssColor => {
- if (!defaultColor) {
- /**
- * Most default color - fallback when nothing else is found.
- */
- defaultColor = colors.primary
- }
-
+ const getColorStrict = (prop: string, preferVariables?: boolean): CssColor | null => {
if (prop === 'transparent') {
return '#ffffff00'
}
@@ -90,10 +82,6 @@ export const useColors = () => {
}
}
- if (!prop) {
- prop = getColor(defaultColor)
- }
-
const colorValue = colors[prop] || colors[normalizeColorName(prop)]
if (colorValue) {
return preferVariables ? `var(${cssVariableName(prop)})` : colorValue
@@ -110,7 +98,23 @@ export const useColors = () => {
warn(`'${prop}' is not a proper color! Use HEX or default color themes
names (https://vuestic.dev/en/styles/colors#default-color-themes)`)
- return getColor(defaultColor)
+ return null
+ }
+
+ /**
+ * Returns color from config variables by name or return prop if color is a valid hex, hsl, hsla, rgb or rgba color.
+ * @param prop - should be color name or color in hex, hsl, hsla, rgb or rgba format.
+ * @param preferVariables - function should return (if possible) CSS variable instead of hex (hex is needed to set opacity).
+ * @param defaultColor - this color will be used if prop is invalid. By default it is primary color.
+ */
+ const getColor = (prop?: string, defaultColor?: string, preferVariables?: boolean): CssColor => {
+ if (!defaultColor) {
+ defaultColor = colors.primary
+ }
+
+ if (!prop) { return defaultColor }
+
+ return getColorStrict(prop, preferVariables) ?? defaultColor
}
const getComputedColor = (color: string) => {
@@ -125,7 +129,7 @@ export const useColors = () => {
.keys(colors)
.filter((key) => colors[key] !== undefined)
.reduce((acc: Record, colorName: string) => {
- acc[`--${prefix}-${kebabCase(colorName)}`] = getColor(colors[colorName], undefined, true)
+ acc[`--${prefix}-${kebabCase(colorName)}`] = getColor(colors[colorName]!, undefined, true)
acc[`--${prefix}-on-${kebabCase(colorName)}`] = getColor(getTextColor(getColor(colors[colorName]!)), undefined, true)
return acc
}, {})
@@ -185,6 +189,7 @@ export const useColors = () => {
applyPreset,
setColors,
getColors,
+ getColorStrict,
getColor,
getComputedColor,
getBoxShadowColor,
diff --git a/packages/ui/src/services/config-transport/createCSSVariables.ts b/packages/ui/src/services/config-transport/createCSSVariables.ts
new file mode 100644
index 0000000000..fc3599513a
--- /dev/null
+++ b/packages/ui/src/services/config-transport/createCSSVariables.ts
@@ -0,0 +1,33 @@
+import { ComponentInternalInstance, Ref, computed } from 'vue'
+import { cssVariableName } from '../color/utils'
+import { Props } from './shared'
+import { useColors } from '../../composables'
+
+export const createCSSVariables = (instance: ComponentInternalInstance, attributes: Props) => {
+ const name = instance.type.name
+
+ const { getColorStrict } = useColors()
+
+ return computed(() => {
+ const keys = Object.keys(attributes)
+
+ const variables = new Map()
+
+ for (let i = 0; i < keys.length; i++) {
+ const key = keys[i]
+ let value = String(attributes[key])
+
+ if (!key.startsWith('style:')) { continue }
+
+ const color = getColorStrict(value, true)
+
+ if (color) {
+ value = color
+ }
+
+ variables.set(cssVariableName(name?.slice(2) + '-' + key.slice(6)), String(value))
+ }
+
+ return variables
+ })
+}
diff --git a/packages/ui/src/services/config-transport/createRenderFn.ts b/packages/ui/src/services/config-transport/createRenderFn.ts
index e7113a882f..636f1a3d0e 100644
--- a/packages/ui/src/services/config-transport/createRenderFn.ts
+++ b/packages/ui/src/services/config-transport/createRenderFn.ts
@@ -1,4 +1,4 @@
-import { withCtx, h, DefineComponent, VNode, isVNode, Text, createBlock } from 'vue'
+import { withCtx, h, DefineComponent, VNode, isVNode, Text, createBlock, ComputedRef, normalizeStyle } from 'vue'
type VueInternalRenderFunction = Function
@@ -49,6 +49,28 @@ export const createRenderFn = (component: DefineComponent): VueInternalRenderFun
// When compile rendered function, it doesn't require thisArg
const thisArg = compiledRenderedFn ? undefined : customCtx
- return originalRenderFn.call(thisArg, customCtx, ...args.slice(1))
+ const result: VNode = originalRenderFn.call(thisArg, customCtx, ...args.slice(1))
+
+ if ('ctx' in result) {
+ const variables: ComputedRef