Default theme CSS wins over custom preset in 4.3.4 and 4.3.5
Describe the bug
After upgrade to 4.3.5 styles from custom preset are not applied. They are present in browser, but default theme CSS wins over the customized one. In the given example the button gets custom color in 4.3.3 but does not get it in 4.3.4 and 4.3.5
Pull Request Link
No response
Reason for not contributing a PR
- [ ] Lack of time
- [x] Unsure how to implement the fix/feature
- [ ] Difficulty understanding the codebase
- [ ] Other
Other Reason
No response
Reproducer
https://stackblitz.com/edit/primevue-4-vite-issue-template-scdqp96w?file=package.json
Environment
Chrome on Windows 11
Vue version
3
PrimeVue version
4.3.5
Node version
20.19.1
Browser(s)
No response
Steps to reproduce the behavior
- Create custom theme preset using
definePreset - Add theme-dependent style for the component, e.g. components->button->colorScheme->dark->warn->color
- The button gets default value of the var(--p-button-warn-color)
Reproducible for different components and styles in the preset, not only buttons.
Expected behavior
The button should get re-defined color from custom preset. The CSS var with the desired value is present but later overwritten and not being applied. Downgrade to 4.3.3 fixes the problem.
I can't tell you what changed between 4.3.3 and 4.3.5, but what i can tell you is that your example code misses the "root" level.
You wrote:
(...)
dark: {
warn: {
color: 'green',
},
},
(...)
But it should be
(...)
dark: {
root: {
warn: {
color: 'green',
},
},
},
(...)
With this change in place i see the color as expected: https://stackblitz.com/edit/primevue-4-vite-issue-template-tgzju65j?file=src%2FCustomPreset.js,index.html
Your code:
After my changes:
That being said, somebody else on the PrimeTek community Discord server also wrote they were hit by this change, @mertsincan is it possible that something was changed in the primeuix version between 4.3.3 and 4.3.5 that causes this change in behavior?
I edited the example @proprofondo provided to primevue 4.3.3 and sure enough, there root isn't required. https://stackblitz.com/edit/primevue-4-vite-issue-template-wddjuals?file=package.json (primevue 4.3.3) starting with 4.3.4 it seems to be required https://stackblitz.com/edit/primevue-4-vite-issue-template-qphpxrw6?file=package.json (primevue 4.3.4). Only change between these two is the primevue version. @mertsincan could this be an regression / undocumented breaking change in primeuix?
Just as information for others...
Be aware if you’re still using the old package to import themes. PrimeVue migrated to @primeuix/themes some time ago. I previously used the old @primevue/themes package in another project and encountered the same button styling issue you described. As MelkorCC mentioned above, the token structure has also changed.
You can find the design tokens for each design at the bottom of this page.
- https://primevue.org/button/
Here’s the link to the Aura theme design tokens (export const colorScheme):
- https://github.com/primefaces/primeuix/blob/main/packages/themes/src/presets/aura/button/index.ts
I'm also encountering CSS-related issues with PrimeVue 4.3.4 and 4.3.5, which are resolved by downgrading to 4.3.3.
In my specific case, while my custom PrimeVue theme (created using definePreset based on the Lara theme from @primeuix/themes) appears to apply its own semantic colors and component-specific overrides correctly, I've found that Tailwind CSS utility classes used on or around PrimeVue components are no longer rendering as expected.
For example, if I apply a Tailwind class like border-black to an element, it shows up correctly in the browser's devtools, but the border doesn't actually render visually.
Downgrading PrimeVue to 4.3.3 resolves this problem, and my Tailwind classes render correctly again alongside PrimeVue.
My setup is a Nuxt 3 project using @primevue/nuxt-module and Tailwind CSS. Here's the relevant part of my nuxt.config.js showing how the PrimeVue preset is defined and used:
import { definePreset } from '@primeuix/themes';
import Lara from '@primeuix/themes/lara';
const mainColor = 'somecolor'; // My actual color value
const CustomLara = definePreset(Lara, {
// ... my semantic and component customizations
semantic: {
primary: {
500: mainColor,
// ... other shades
}
},
components: {
progressspinner: { /* ... custom spinner styles ... */ }
}
});
// ...
export default defineNuxtConfig({
// ...
primevue: {
options: {
theme: {
preset: CustomLara,
options: {
prefix: 'pv',
// ... other options
}
},
},
},
// ...
});
Be aware if you’re still using the old package to import themes. PrimeVue migrated to @primeuix/themes some time ago. I previously used the old @primevue/themes package in another project and encountered the same button styling issue you described.
@borsTiHD Actually @primevue/themes just reexports primeuix stuff. So while you are correct, people should migrate, this is probably not the problem here (random example from 4.3.3: https://github.com/primefaces/primevue/blob/4.3.3/packages/themes/src/presets/aura/button/index.js )
@ct255 i think this is something that should be tracked in a different issue and you might also want to provide a minimal reproducer on stackblitz
I think this is the same as the unresolved issue in https://github.com/primefaces/primevue/issues/7258 .
@borsTiHD I can confirm that the issue is not affected by in which way you load theme library. I used @primevue/themes and upgrade to @primeuix/themes was actually my first guess. But it didn't help. While changing version of the primevue itself does the change.
@MelkorCC thanks for the hint with root. It fixes the issue. But I have many components re-styled in old way and would like to avoid refactoring. So I leave the ticket open for now, till fixed or documented that root is mandatory from now on.
Thanks
@MelkorCC / @proprofondo Yes, I also noticed this when I took a closer look at the export of the package. My bad. I edited my post as “general info”. For my problem, I migrated to the correct package and also adjusted the object structure.
Be aware if you’re still using the old package to import themes. PrimeVue migrated to @primeuix/themes some time ago. I previously used the old @primevue/themes package in another project and encountered the same button styling issue you described.
@borsTiHD Actually @primevue/themes just reexports primeuix stuff. So while you are correct, people should migrate, this is probably not the problem here (random example from 4.3.3: https://github.com/primefaces/primevue/blob/4.3.3/packages/themes/src/presets/aura/button/index.js )
@ct255 i think this is something that should be tracked in a different issue and you might also want to provide a minimal reproducer on stackblitz
so sorry, seem like that is about my config and the prefix, I found out that the PrimeUI is hard coded the --p so the prefix I set not work, so I remove it and it good to go, but still have no clue why downgrade work
Hello! Could you help me with such question, please? In my library I have primevue.ts
import type { App } from "vue";
import PrimeVue from "primevue/config";
import Button from "primevue/button";
import Toast from "primevue/toast";
import ToastService from "primevue/toastservice";
import Ripple from "primevue/ripple";
import Lara from "@primeuix/themes/lara";
import { definePreset } from "@primeuix/themes";
import "../styles/fabrix-colors.css";
import { palette } from "@primeuix/themes";
export const applyThemeColors = () => {
const computedStyle = getComputedStyle(document.documentElement);
const primaryColorValue = computedStyle.getPropertyValue("--primary-color");
const primaryColor = palette(primaryColorValue);
return {
primary: primaryColor,
secondary: {
50: "{gray.50}",
100: "{gray.100}",
200: "{gray.200}",
300: "{gray.300}",
400: "{gray.400}",
500: "{gray.500}",
600: "{gray.600}",
700: "{gray.700}",
800: "{gray.800}",
900: "{gray.900}",
950: "{gray.950}",
},
};
};
export const MyPreset = definePreset(Lara, {
semantic: applyThemeColors(),
//Your customizations, see the following sections for examples
});
export const PrimeVuePlugin = {
install: (app: App) => {
applyThemeColors();
app.use(PrimeVue, {
ripple: false,
theme: {
preset: MyPreset,
options: {
prefix: "p",
darkModeSelector: "system",
cssLayer: {
name: "primevue",
order: "prime, primevue, fabrix",
},
},
},
});
app.use(ToastService);
app.component("Button", Button);
app.component("Toast", Toast);
app.directive("ripple", Ripple);
},
};
I use this library in another project like this: main.js
import "primeicons/primeicons.css";
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
// Fabrix styling:
import { UiKitPlugin, MyPreset } from "@fabrix/ui-kit";
import { applyThemeColors } from "@fabrix/ui-kit";
import "@fabrix/ui-kit/ui-kit.css";
import PrimeVue from "primevue/config";
App.created = function () {
if (this.created) this.created();
this.$auth.init();
};
const app = createApp(App);
console.log("First version of preset is", MyPreset);
const themeColors = applyThemeColors();
console.log("Theme colors", themeColors);
const themeConfig = {
...MyPreset,
semantic: {
...MyPreset.semantic,
primary: themeColors.primary,
secondary: themeColors.secondary,
},
};
console.log("Updated preset is", themeConfig);
app.use(PrimeVue, {
theme: { preset: themeConfig },
});
app.use(UiKitPlugin, import.meta.env);
app.mount("#app");
export default app;
The colors from the library are not being applied in the project that uses it.
Though the colors in the themeConfig object are exactly as expected and correct, but they are not being applied despite using the following configuration:
app.use(PrimeVue, {
theme: { preset: themeConfig },
});
The CSS-variable is defined in my library like this:
fabrix-colors.css
:root {
--primary-color: #1f36c7;
} How should I act to fix this?
I tried to use not only this method, but, for example, another one method: primevue.ts
import type { App } from "vue";
import PrimeVue from "primevue/config";
import Button from "primevue/button";
import Toast from "primevue/toast";
import ToastService from "primevue/toastservice";
import Ripple from "primevue/ripple";
import Lara from "@primeuix/themes/lara";
import { definePreset } from "@primeuix/themes";
import "../styles/fabrix-colors.css";
import { palette } from "@primeuix/themes";
const computedStyle = getComputedStyle(document.documentElement);
const primaryColorValue = computedStyle.getPropertyValue("--primary-color");
const primaryColor = palette(primaryColorValue);
export const MyPreset = definePreset(Lara, {
semantic: {
primary: primaryColor,
secondary: {
50: "{gray.50}",
100: "{gray.100}",
200: "{gray.200}",
300: "{gray.300}",
400: "{gray.400}",
500: "{gray.500}",
600: "{gray.600}",
700: "{gray.700}",
800: "{gray.800}",
900: "{gray.900}",
950: "{gray.950}",
},
},
//Your customizations, see the following sections for examples
});
export const PrimeVuePlugin = {
install: (app: App) => {
app.use(PrimeVue, {
ripple: false,
theme: {
preset: MyPreset,
options: {
prefix: "p",
darkModeSelector: "system",
cssLayer: {
name: "primevue",
order: "prime, primevue, fabrix",
},
},
},
});
main.js
import ConfirmationService from "primevue/confirmationservice";
import ToastService from "primevue/toastservice";
import Tooltip from "primevue/tooltip";
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
// Fabrix styling:
import { UiKitPlugin, MyPreset } from "@fabrix/ui-kit";
import "@fabrix/ui-kit/ui-kit.css";
import "primeicons/primeicons.css";
import axios from "axios";
import qs from "qs";
import store from "./store/store";
import PrimeVue from "primevue/config";
App.created = function () {
if (this.created) this.created();
this.$auth.init();
};
const app = createApp(App);
console.log("First version of preset is", MyPreset);
/
app.use(PrimeVue, {
theme: { preset: MyPreset },
});
axios.defaults.baseURL = import.meta.env.CLIENT__API_BASE_URL;
axios.defaults.withCredentials = true;
axios.defaults.paramsSerializer = (params) =>
qs.stringify(params, { arrayFormat: "comma" });
app.use(router);
app.use(store);
app.use(UiKitPlugin, import.meta.env);
app.use(ToastService);
app.use(ConfirmationService);
app.directive("tooltip", Tooltip);
app.mount("#app");
export default app;
the result is the same.
And when I do like this in my library,
primevue.ts
import type { App } from "vue";
import PrimeVue from "primevue/config";
import Button from "primevue/button";
import Toast from "primevue/toast";
import ToastService from "primevue/toastservice";
import Ripple from "primevue/ripple";
import Lara from "@primeuix/themes/lara";
import { definePreset } from "@primeuix/themes";
import "../styles/fabrix-colors.css";
import { palette } from "@primeuix/themes";
// const computedStyle = getComputedStyle(document.documentElement);
// const primaryColorValue = computedStyle.getPropertyValue("--primary-color");
const primaryColorValue = "#1f36c7";
const primaryColor = palette(primaryColorValue);
export const MyPreset = definePreset(Lara, {
semantic: {
primary: primaryColor,
secondary: {
50: "{gray.50}",
100: "{gray.100}",
200: "{gray.200}",
300: "{gray.300}",
400: "{gray.400}",
500: "{gray.500}",
600: "{gray.600}",
700: "{gray.700}",
800: "{gray.800}",
900: "{gray.900}",
950: "{gray.950}",
},
},
//Your customizations, see the following sections for examples
});
export { PrimeVue };
export const PrimeVuePlugin = {
install: (app: App) => {
app.use(PrimeVue, {
ripple: false,
theme: {
preset: MyPreset,
options: {
prefix: "p",
darkModeSelector: "system",
cssLayer: {
name: "primevue",
order: "prime, primevue, fabrix",
},
},
},
});
app.use(ToastService);
app.component("Button", Button);
app.component("Toast", Toast);
app.directive("ripple", Ripple);
},
};
the colors in the project, that uses this library are correct. But I really need to use CSS variables in my library, so this variant is not suitable
Correct implementation is:
button: {
colorScheme: {
light: {
root: {
warn: {
color: 'blue',
},
}
},
dark: {
root: {
warn: {
color: 'green',
},
}
},
},
}
@tugcekucukoglu that doesn't explain tho why the behavior changed between 4.3.3 and 4.3.4 and why this change wasn't mentioned in the release notes.