Skip to content

Commit

Permalink
Sizes styles rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
Fsss126 committed May 1, 2024
1 parent 68e2d18 commit e416ef4
Show file tree
Hide file tree
Showing 19 changed files with 236 additions and 63 deletions.
26 changes: 19 additions & 7 deletions packages/nuxt/src/runtime/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,27 @@ import {
type PartialGlobalConfig
} from 'vuestic-ui'
import { markRaw, computed, watch, type Ref } from 'vue'
import { useHead, ReactiveHead, defineNuxtPlugin, useCookie } from '#imports'
import type { VuesticOptions } from '../types'
import { useHead, ReactiveHead, defineNuxtPlugin, useCookie } from '#imports'
import NuxtLink from '#app/components/nuxt-link'
import configFromFile from '#vuestic-config'

import type { VuesticOptions } from '../types'

function getGlobalProperty (app, key) {
return app.config.globalProperties[key]
}

export default defineNuxtPlugin(async (nuxtApp) => {
export default defineNuxtPlugin((nuxtApp) => {
const { vueApp: app } = nuxtApp

// It's important to use `, because TS will compile qoutes to " and JSON will not be parsed...
const moduleOptions: VuesticOptions = JSON.parse(`<%= options.value %>`)
const moduleOptions: VuesticOptions = JSON.parse('<%= options.value %>')
const themeCookie = useCookie(moduleOptions.themeCookieKey)
const userConfig = configFromFile || moduleOptions.config || {}
const configWithColors: PartialGlobalConfig = {
...userConfig,
colors: {
currentPresetName: themeCookie.value || userConfig.colors?.currentPresetName || 'light',
...userConfig.colors,
...userConfig.colors
}
}

Expand All @@ -44,7 +43,7 @@ export default defineNuxtPlugin(async (nuxtApp) => {
VaDropdownPlugin,
VaToastPlugin,
VaModalPlugin,
ColorsClassesPlugin,
ColorsClassesPlugin
},
/** Do not import any components. Nuxt will import them automatically */
components: {}
Expand Down Expand Up @@ -76,6 +75,19 @@ export default defineNuxtPlugin(async (nuxtApp) => {
}))
}

const componentConfig = getGlobalProperty(app, '$vaComponentConfig')
if (componentConfig) {
useHead(computed(() => {
return {
style: [
{
innerHTML: componentConfig.renderStyles()
}
]
} satisfies ReactiveHead
}))
}

// Watch for preset name change and update cookie
const { globalConfig } = getGlobalProperty(app, '$vaConfig') as { globalConfig: Ref<GlobalConfig> }
watch(() => globalConfig.value.colors.currentPresetName, (newTheme) => {
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
VaToastPlugin,
VaModalPlugin,
VaDropdownPlugin,
BreakpointConfigPlugin,
BreakpointConfigPlugin, ComponentConfigPlugin,
} from './../src/main'
import demoIconAliases from './vuestic-config/demo-icon-aliases'
import demoIconFonts from './vuestic-config/demo-icon-fonts'
Expand Down Expand Up @@ -49,7 +49,7 @@ setup((app) => {
},
},
},
plugins: { VaToastPlugin, VaDropdownPlugin, VaModalPlugin, BreakpointConfigPlugin },
plugins: { VaToastPlugin, VaDropdownPlugin, VaModalPlugin, BreakpointConfigPlugin, ComponentConfigPlugin },
}))
})

Expand Down
17 changes: 7 additions & 10 deletions packages/ui/src/components/va-button/VaButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class="va-button"
:class="computedClass"
:style="computedStyle"
v-bind="attributesComputed"
v-bind="{ ...variablesComputed, ...attributesComputed }"
>
<span class="va-button__content" :class="wrapperClassComputed">
<slot
Expand Down Expand Up @@ -109,7 +109,9 @@ const props = defineProps({
plain: { type: Boolean, default: false },
round: { type: Boolean, default: false },
size: {
type: [String, Number] as PropType<'small' | 'medium' | 'large' | string | number>,
type: [String, Number] as PropType<
'small' | 'medium' | 'large' | string | number
>,
default: 'medium',
},
icon: { type: String, default: '' },
Expand Down Expand Up @@ -188,7 +190,6 @@ const variablesComputed = useComponentVariables(props)
const computedStyle = computed(() => ({
borderColor: props.borderColor ? getColor(props.borderColor) : 'transparent',
...contentColorComputed.value,
...variablesComputed.value,
}))
defineExpose({
Expand Down Expand Up @@ -294,9 +295,7 @@ defineExpose({
.va-button__content {
font-size: var(--va-button-font-size);
padding:
var(--va-button-content-py)
var(--va-button-content-px);
padding: var(--va-button-content-py) var(--va-button-content-px);
line-height: var(--va-button-line-height);
}
Expand All @@ -323,13 +322,11 @@ defineExpose({
.va-button__content {
padding-top:
calc(
var(--va-button-content-py) -
var(--va-button-bordered-border)
var(--va-button-content-py) - var(--va-button-bordered-border)
);
padding-bottom:
calc(
var(--va-button-content-py) -
var(--va-button-bordered-border)
var(--va-button-content-py) - var(--va-button-bordered-border)
);
}
}
Expand Down
20 changes: 17 additions & 3 deletions packages/ui/src/components/va-config/VaConfig.demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,19 @@
<VbCard title="Colors">
<va-config :colors="{ variables: {
primary: '#f0f',
} }">
<va-button>
} }" :components="isOn ? {
VaButton: {
size: 'xs',
sizesConfig: {
xs: {
variables: {
fontSize: '10px',
},
},
},
},
} : undefined">
<va-button @click="isOn = !isOn">
Button inside va-config
</va-button>

Expand All @@ -106,7 +117,7 @@
</template>

<script>
import { computed } from 'vue'
import { computed, ref } from 'vue'
import { useGlobalConfig } from '../../services/global-config/global-config'
import { useColors } from '../../composables'
import { VaButton } from '../va-button'
Expand Down Expand Up @@ -148,6 +159,8 @@ export default {
const { getColor } = useColors()
const isOn = ref(true)
const cardPreset = {
highlightTop: {
square: true,
Expand Down Expand Up @@ -198,6 +211,7 @@ export default {
buttonRoundConfigValue,
cardPreset,
buttonPreset,
isOn,
}
},
computed: {
Expand Down
76 changes: 52 additions & 24 deletions packages/ui/src/components/va-config/VaConfig.vue
Original file line number Diff line number Diff line change
@@ -1,52 +1,78 @@
<template>
<CssVarsRenderer v-if="doRenderCssVars" v-bind="$attrs">
<CssVarsRenderer v-if="doRenderCssVars" v-bind="{ ...props, ...$attrs }">
<slot />
</CssVarsRenderer>
<slot v-else />
</template>

<script lang="ts">
import { computed, PropType, h, Fragment, defineComponent } from 'vue'
import { computed, PropType, h, Fragment, defineComponent, useCssVars } from 'vue'
import { useComponentPresetProp } from '../../composables/useComponentPreset'
import { ComponentConfig } from '../../services/component-config'
import { provideLocalConfig, useLocalConfig } from '../../composables/useLocalConfig'
import {
provideLocalConfig,
useLocalConfig,
} from '../../composables/useLocalConfig'
import { useGlobalConfigProvider } from './hooks/useGlobalConfigProvider'
import { PartialGlobalConfig } from '../../services/global-config'
import { renderSlotNodes } from '../../utils/headless'
import { useColors } from '../../composables'
import { useColors, useCurrentComponentId } from '../../composables'
import { renderComponentsStyles } from '../../services/component-config/utils/render-styles-from-config'
const ConfigProps = {
components: {
type: Object as PropType<ComponentConfig>,
default: () => ({}),
},
colors: { type: Object as PropType<PartialGlobalConfig['colors']> },
i18n: { type: Object as PropType<PartialGlobalConfig['i18n']> },
}
const CssVarsRenderer = defineComponent({
name: 'VaCssVarsRenderer',
props: ConfigProps,
inheritAttrs: false,
setup (props, { slots, attrs }) {
const { colorsToCSSVariable, colors } = useColors()
const { colorsToCSSVariable, currentPresetName } = useColors()
const id = useCurrentComponentId()
const style = computed(() => {
return colorsToCSSVariable(colors)
const styleAttr = computed(() => {
return colorsToCSSVariable({
...props.colors?.variables,
...(props.colors?.presets || {})[currentPresetName.value],
})
})
return () => h(Fragment, attrs, renderSlotNodes(slots.default, {}, {
style: style.value,
}) || undefined)
const elementId = `va-config-${id}`
const componentStyles = computed(() => renderComponentsStyles(props.components, `#${elementId}`))
return () =>
h(
'div',
{ ...attrs, style: styleAttr.value, id: elementId },
[
componentStyles.value ? h('style', { innerHTML: componentStyles.value }) : undefined,
slots.default?.(),
],
)
},
})
</script>

<script lang="ts" setup>
defineOptions({
name: 'VaConfig',
inheritAttrs: false,
})
const props = defineProps({
...useComponentPresetProp,
components: { type: Object as PropType<ComponentConfig>, default: () => ({}) },
colors: { type: Object as PropType<PartialGlobalConfig['colors']> },
i18n: { type: Object as PropType<PartialGlobalConfig['i18n']> },
...ConfigProps,
})
const prevChain = useLocalConfig()
Expand All @@ -55,19 +81,21 @@ const nextChain = computed(() => [...prevChain.value, props.components])
provideLocalConfig(nextChain)
const newConfig = useGlobalConfigProvider(computed(() => {
const config = {} as any
const newConfig = useGlobalConfigProvider(
computed(() => {
const config = {} as any
if (props.colors) {
config.colors = props.colors
}
if (props.colors) {
config.colors = props.colors
}
if (props.i18n) {
config.i18n = props.i18n
}
if (props.i18n) {
config.i18n = props.i18n
}
return config
}))
return config
}),
)
const doRenderCssVars = computed(() => {
return Boolean(props.colors)
Expand Down
12 changes: 1 addition & 11 deletions packages/ui/src/composables/useComponentVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,14 @@ import { ReadonlyOrPlainArray } from '../utils/types/array'
import { computed, getCurrentInstance } from 'vue'
import { isCSSSizeValue, isCSSVariable } from '../utils/css'
import isNil from 'lodash/isNil'
import { SizeProps, SizesConfig } from '../services/size'
import { SizeProps, SizesConfig } from '../services/component-config/theme'
import { useBem } from './useBem'

const sizeToAbsolute = (size: unknown) => {
if (typeof size === 'number') { return `${size}px` }
return String(size)
}

export const renderVariablesFromConfig = <Variables extends string>(sizesConfig: SizesConfig<Variables, string>, componentName: string) => {
return Object.entries(sizesConfig).reduce<Record<string, string>>((acc, [size, { variables }]) => {
for (const property in variables) {
acc[cssVariableName({ componentName, size, property })] = variables[property]
}

return acc
}, {})
}

export const useComponentVariables = <Variables extends string>(props: SizeProps<SizesConfig<Variables, string>>, componentName = getCurrentInstance()?.type.name) => {
if (!componentName) {
throw new Error('Component name must be provided!')
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/composables/useSize.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PropType } from 'vue'
import { SizesConfig } from '../services/size'
import { SizesConfig } from '../services/component-config/theme'

/**
* You could add these props to any component by destructuring them inside props option.
Expand Down
11 changes: 11 additions & 0 deletions packages/ui/src/services/component-config/config/default.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { ComponentConfig } from '../types'

export const getComponentsDefaultConfig = (): ComponentConfig =>
// TODO: Should be handled in size service
({
VaRating: {
size: 'xl',
sizesConfig: {
xl: {
variables: {
numberItemSize: '28px',
},
},
},
},
all: {},
presets: {
VaButton: {
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/services/component-config/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './theme'
export * from './types'
export * from './config/default'
export * from './utils/use-component-config-props'
Loading

0 comments on commit e416ef4

Please sign in to comment.