-
Notifications
You must be signed in to change notification settings - Fork 97
Theming with Vuetify #237
-
Hello again everyone.
For those of you using Vuetify, you've probably already had to come up with a way to synchronize the colors of VueDataUI components with Vuetify's ability to switch between light and dark modes. Maybe @graphieros will create light and dark modes in the future :P
If you're struggling with ways to easily synchronize colors, here's a way I have found useful. It leverages composables within Vue, enabling reactive updates to all VueDataUI components based on the current Vuetify theme.
Note: I'm using VueUiScatter
for this example, but they're all very similar.
It starts with useConfig
This composable allows you to set all colors for each component, and then automatically apply them by overriding the component configurations.
// useConfig.ts import { computed, type Ref } from 'vue'; import { type VueUiScatterConfig } from 'vue-data-ui'; import { mergeObjects } from '@/core/utils'; import { useColors } from '../../config/useColors'; import { useTitle } from '../../config/vdu/useTitle'; import { useLegend } from '../../config/vdu/useLegend'; import { useTooltip } from '../../config/vdu/useTooltip'; export function useConfig(customConfig: Ref<VueUiScatterConfig>) { const { colors } = useColors(); const { title } = useTitle(colors); const { legend } = useLegend(colors); const { tooltip } = useTooltip(colors); const vuetifyConfig = computed<VueUiScatterConfig>(() => { return { style: { backgroundColor: colors.value.bg, color: colors.value.text, layout: { axis: { stroke: colors.value.stroke, }, dataLabels: { xAxis: { color: colors.value.text, }, yAxis: { color: colors.value.text, }, }, marginalBars: { fill: colors.value.stroke, }, }, title: title.value, legend: legend.value, tooltip: tooltip.value, }, }; }); const config = computed<VueUiScatterConfig>(() => { const custom = customConfig.value || {}; const vuetify = vuetifyConfig.value || {}; const merged = mergeObjects(custom, vuetify); return merged; }); return { config }; }
useColors
composable
// useColors.ts import { computed } from 'vue'; import { useTheme } from 'vuetify'; type iColors = { bg: string; text: string; stroke: string; }; export function useColors() { const theme = useTheme(); const themeName = computed<'light' | 'dark'>(() => { if (theme.current.value.dark) return 'dark'; return 'light'; }); const colors = computed<iColors>(() => { return { bg: theme.current.value.colors.surface, text: { light: '#1a1a1a', dark: '#f5f5f5' }[themeName.value], stroke: { light: '#afb0b0', dark: '#8f9090' }[themeName.value], }; }); return { colors }; }
useTitle
composable
// useTitle.ts import { computed, type Ref } from 'vue'; type iColors = { bg: string; text: string; stroke: string; }; export function useTitle(colors: Ref<iColors>) { const title = computed<any>(() => { return { color: colors.value.text, subtitle: { color: colors.value.stroke, }, }; }); return { title }; }
useLegend
composable
// useLegend.ts import { computed, type Ref } from 'vue'; type iColors = { bg: string; text: string; stroke: string; }; export function useLegend(colors: Ref<iColors>, noBackground?: boolean) { const legend = computed<any>(() => { if (noBackground) { return { color: colors.value.text, }; } else { return { color: colors.value.text, backgroundColor: colors.value.bg, }; } }); return { legend }; }
useTooltip
composable
// useTooltip.ts import { computed, type Ref } from 'vue'; type iColors = { bg: string; text: string; stroke: string; }; export function useTooltip(colors: Ref<iColors>, noOpacity?: boolean) { const tooltip = computed<any>(() => { if (noOpacity) { return { color: colors.value.text, backgroundColor: colors.value.bg + '80', // 50% opacity borderColor: colors.value.stroke, }; } else { // standard... return { color: colors.value.text, backgroundColor: colors.value.bg, backgroundOpacity: 50, borderColor: colors.value.stroke, }; } }); return { tooltip }; }
Applying this methodology
const defaultConfig = ref<VueUiScatterConfig>(getVueDataUiConfig('vue_ui_scatter')); const { config } = useConfig(defaultConfig);
<VueUiScatter v-if="dataset.length > 0" :dataset="dataset" :config="config" />
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1