Nuxt UI 3 Dynamic Theming

Tello, It's in the name :), I would like to do like Nuxt UI 3 page: Allow the user to choose the primary color (or more) to retheme dynamically. I tried to research about it here and there, but I can't find more than chaning CSS variable, which would be a very tailwind way. Is there a way to dynamically override UI 3 palette to have a more effective dynamic theming ? Thanks 🙂
No description
8 Replies
kapa.ai
kapa.ai3w ago
Hi @Omnislash. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Yes, you can implement dynamic theming in Nuxt UI 3 similar to how the Nuxt UI documentation site does it. There are two main approaches: Using App Config (for Nuxt projects) In Nuxt UI 3, you can dynamically change the primary color (and other colors) at runtime using the reactive app config:
<script setup>
const appConfig = useAppConfig()

function changeThemeColor(color) {
appConfig.ui.colors.primary = color
}
</script>

<template>
<div>
<button @click="changeThemeColor('blue')">Blue Theme</button>
<button @click="changeThemeColor('green')">Green Theme</button>
<button @click="changeThemeColor('red')">Red Theme</button>
</div>
</template>
<script setup>
const appConfig = useAppConfig()

function changeThemeColor(color) {
appConfig.ui.colors.primary = color
}
</script>

<template>
<div>
<button @click="changeThemeColor('blue')">Blue Theme</button>
<button @click="changeThemeColor('green')">Green Theme</button>
<button @click="changeThemeColor('red')">Red Theme</button>
</div>
</template>
This approach leverages Nuxt's App Config system, which is reactive. When you change appConfig.ui.colors.primary, all components using that color will update automatically. Using CSS Variables (alternative approach) For more fine-grained control, you can also use CSS variables to override specific color shades:
:root {
--ui-primary: var(--ui-color-primary-700);
}

.dark {
--ui-primary: var(--ui-color-primary-200);
}
:root {
--ui-primary: var(--ui-color-primary-700);
}

.dark {
--ui-primary: var(--ui-color-primary-200);
}
You can dynamically change these variables using JavaScript:
document.documentElement.style.setProperty('--ui-primary', 'var(--ui-color-blue-500)')
document.documentElement.style.setProperty('--ui-primary', 'var(--ui-color-blue-500)')
Implementation Example The Nuxt UI documentation site itself uses this approach. According to a Stack Overflow post, they change the config reactively to implement their theme picker feature Stack Overflow Post. You can set up your initial configuration in app.config.ts:
export default defineAppConfig({
ui: {
colors: {
primary: 'indigo',
secondary: 'pink',
// other colors...
}
}
})
export default defineAppConfig({
ui: {
colors: {
primary: 'indigo',
secondary: 'pink',
// other colors...
}
}
})
Then modify it dynamically in your components as shown above. For more detailed information on theming in Nuxt UI 3, check out the Nuxt UI Theme documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@305772639438503936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Omnislash
OmnislashOP3w ago
@kapa.ai very nice thanks, looks good, but what about fully custom colors instead of existing tailwind colors ? Can I add a new brand new palette in useAppConfig ?
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, you can definitely add custom colors beyond the existing Tailwind colors in Nuxt UI 3. There are two approaches to implement fully custom color palettes: 1. Using CSS Variables with @theme directive For fully custom colors, you can define your own color palette using CSS variables in your main CSS file:
@import "tailwindcss";
@import "@nuxt/ui";

@theme static {
/* Define your custom brand color with all shades */
--color-mybrand-50: #f9f5ff;
--color-mybrand-100: #f0e7ff;
--color-mybrand-200: #e4d3ff;
--color-mybrand-300: #cfb0ff;
--color-mybrand-400: #b37eff;
--color-mybrand-500: #9a4dff;
--color-mybrand-600: #8520ff;
--color-mybrand-700: #7312df;
--color-mybrand-800: #5f10b8;
--color-mybrand-900: #4f0e96;
--color-mybrand-950: #2e0764;
}
@import "tailwindcss";
@import "@nuxt/ui";

@theme static {
/* Define your custom brand color with all shades */
--color-mybrand-50: #f9f5ff;
--color-mybrand-100: #f0e7ff;
--color-mybrand-200: #e4d3ff;
--color-mybrand-300: #cfb0ff;
--color-mybrand-400: #b37eff;
--color-mybrand-500: #9a4dff;
--color-mybrand-600: #8520ff;
--color-mybrand-700: #7312df;
--color-mybrand-800: #5f10b8;
--color-mybrand-900: #4f0e96;
--color-mybrand-950: #2e0764;
}
2. Registering Custom Colors in App Config To use your custom color in the app config system, you need to: 1. Define the color in your nuxt.config.ts file:
export default defineNuxtConfig({
ui: {
theme: {
colors: ['primary', 'secondary', 'mybrand'] // Add your custom color name
}
}
})
export default defineNuxtConfig({
ui: {
theme: {
colors: ['primary', 'secondary', 'mybrand'] // Add your custom color name
}
}
})
2. Then you can use it in your app.config.ts:
export default defineAppConfig({
ui: {
colors: {
mybrand: {
50: '#f9f5ff',
100: '#f0e7ff',
// ... other shades
900: '#4f0e96',
950: '#2e0764'
}
}
}
})
export default defineAppConfig({
ui: {
colors: {
mybrand: {
50: '#f9f5ff',
100: '#f0e7ff',
// ... other shades
900: '#4f0e96',
950: '#2e0764'
}
}
}
})
3. Now you can dynamically change it:
const appConfig = useAppConfig()
appConfig.ui.colors.mybrand = yourCustomColorObject
const appConfig = useAppConfig()
appConfig.ui.colors.mybrand = yourCustomColorObject
This approach allows you to define completely custom color palettes that aren't part of the default Tailwind colors, and still use them with all Nuxt UI components through the color="mybrand" prop. For more information on customizing the theme in Nuxt UI, check the Nuxt UI Theme documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@305772639438503936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Omnislash
OmnislashOP3w ago
@kapa.ai in your exemple I still have to create "mybrand" in main.css first. Is it possible to define a full new color in runtime ?
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You're right about the limitation in my previous example. Let's clarify how to define a completely new color palette at runtime in Nuxt UI 3. For fully dynamic color creation at runtime (without predefined CSS variables), you have a couple of options: Using v-bind in CSS You can use Vue's v-bind in your CSS to dynamically bind JavaScript variables to CSS properties:
<script setup>
import { ref } from 'vue'

// Your dynamic color palette defined in JavaScript
const customColorPalette = ref({
50: '#f9f5ff',
100: '#f0e7ff',
200: '#e4d3ff',
300: '#cfb0ff',
400: '#b37eff',
500: '#9a4dff',
600: '#8520ff',
700: '#7312df',
800: '#5f10b8',
900: '#4f0e96',
950: '#2e0764'
})

// Function to update the palette
function updateColorPalette(newPalette) {
customColorPalette.value = newPalette
}
</script>

<style>
:root {
--ui-color-mybrand-50: v-bind('customColorPalette[50]');
--ui-color-mybrand-100: v-bind('customColorPalette[100]');
--ui-color-mybrand-200: v-bind('customColorPalette[200]');
--ui-color-mybrand-300: v-bind('customColorPalette[300]');
--ui-color-mybrand-400: v-bind('customColorPalette[400]');
--ui-color-mybrand-500: v-bind('customColorPalette[500]');
--ui-color-mybrand-600: v-bind('customColorPalette[600]');
--ui-color-mybrand-700: v-bind('customColorPalette[700]');
--ui-color-mybrand-800: v-bind('customColorPalette[800]');
--ui-color-mybrand-900: v-bind('customColorPalette[900]');
--ui-color-mybrand-950: v-bind('customColorPalette[950]');

/* Set the main color variable */
--ui-mybrand: var(--ui-color-mybrand-500);
}

.dark {
--ui-mybrand: var(--ui-color-mybrand-400);
}
</style>
<script setup>
import { ref } from 'vue'

// Your dynamic color palette defined in JavaScript
const customColorPalette = ref({
50: '#f9f5ff',
100: '#f0e7ff',
200: '#e4d3ff',
300: '#cfb0ff',
400: '#b37eff',
500: '#9a4dff',
600: '#8520ff',
700: '#7312df',
800: '#5f10b8',
900: '#4f0e96',
950: '#2e0764'
})

// Function to update the palette
function updateColorPalette(newPalette) {
customColorPalette.value = newPalette
}
</script>

<style>
:root {
--ui-color-mybrand-50: v-bind('customColorPalette[50]');
--ui-color-mybrand-100: v-bind('customColorPalette[100]');
--ui-color-mybrand-200: v-bind('customColorPalette[200]');
--ui-color-mybrand-300: v-bind('customColorPalette[300]');
--ui-color-mybrand-400: v-bind('customColorPalette[400]');
--ui-color-mybrand-500: v-bind('customColorPalette[500]');
--ui-color-mybrand-600: v-bind('customColorPalette[600]');
--ui-color-mybrand-700: v-bind('customColorPalette[700]');
--ui-color-mybrand-800: v-bind('customColorPalette[800]');
--ui-color-mybrand-900: v-bind('customColorPalette[900]');
--ui-color-mybrand-950: v-bind('customColorPalette[950]');

/* Set the main color variable */
--ui-mybrand: var(--ui-color-mybrand-500);
}

.dark {
--ui-mybrand: var(--ui-color-mybrand-400);
}
</style>
This approach uses Vue's dynamic styles with v-bind feature, allowing you to create and modify color palettes entirely at runtime. Programmatically Setting CSS Variables Alternatively, you can programmatically set CSS variables:
function setCustomColorPalette(colorName, palette) {
// Set each shade
Object.entries(palette).forEach(([shade, value]) => {
document.documentElement.style.setProperty(
`--ui-color-${colorName}-${shade}`,
value
)
})

// Set the main color variable for light mode
document.documentElement.style.setProperty(
`--ui-${colorName}`,
`var(--ui-color-${colorName}-500)`
)

// You might want to set a different shade for dark mode
// This would need to be applied to the .dark class
}

// Usage
setCustomColorPalette('mybrand', {
50: '#f9f5ff',
100: '#f0e7ff',
// ... other shades
})
function setCustomColorPalette(colorName, palette) {
// Set each shade
Object.entries(palette).forEach(([shade, value]) => {
document.documentElement.style.setProperty(
`--ui-color-${colorName}-${shade}`,
value
)
})

// Set the main color variable for light mode
document.documentElement.style.setProperty(
`--ui-${colorName}`,
`var(--ui-color-${colorName}-500)`
)

// You might want to set a different shade for dark mode
// This would need to be applied to the .dark class
}

// Usage
setCustomColorPalette('mybrand', {
50: '#f9f5ff',
100: '#f0e7ff',
// ... other shades
})
Remember that for either approach, you'll still need to register the color name in your Nuxt config to use it with component props like color="mybrand", but the actual color values can be completely dynamic. These methods allow you to create entirely new color palettes at runtime without having to predefine them in your CSS files. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@305772639438503936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?