Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't get to work with Tailwind #6

Closed
bipsen opened this issue Oct 19, 2023 · 39 comments
Closed

Can't get to work with Tailwind #6

bipsen opened this issue Oct 19, 2023 · 39 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@bipsen
Copy link

bipsen commented Oct 19, 2023

Love to see this new Nuxt module as well as the TailwindCSS version of PrimeVue! I have been using PrimeVue as a Nuxt plugin as well as Tailwind so far, with this setup:

// plugins/primevue.ts
import PrimeVue from "primevue/config";
import Tailwind from "primevue/passthrough/tailwind";
import Button from "primevue/button";

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(PrimeVue, {
    unstyled: true,
    pt: Tailwind,
  });
  nuxtApp.vueApp.component("Button", Button);
});

Unfortunately, I can't get it work with the new module. I have something like this in nuxt.config.js:

// nuxt.config.js
import { defineNuxtConfig } from "nuxt/config";
import Tailwind from "primevue/passthrough/tailwind";

export default defineNuxtConfig({
  modules: [
    "@nuxtjs/tailwindcss",
    "nuxt-primevue",
  ],

  build: {
    transpile: ["primevue"],
  },

  primevue: {
    options: {
      ripple: true,
      unstyled: true,
      pt: Tailwind,
    },
  },
});

Both Tailwind and PrimeVue seem to work independently, but the stylings are not applied. I have also tried applied "MyDesignSystem" as per https://primevue.org/tailwind/, which also doesn't seem to work. Any ideas for how to fix this?

@mertsincan
Copy link
Member

Hi,

Which PrimeVue version are you using?

@mertsincan mertsincan added the bug Something isn't working label Oct 19, 2023
@mertsincan mertsincan added this to the 0.0.4 milestone Oct 19, 2023
@mertsincan mertsincan self-assigned this Oct 19, 2023
@mertsincan
Copy link
Member

Thanks a lot for the report! I'll work on it and get back to you.

@deepfriedmind
Copy link

Same for me with this config:

import { usePassThrough } from 'primevue/passthrough'
import Tailwind from 'primevue/passthrough/tailwind'

const primeVueTailwindOverrides = {
  datatable: {
    column: {
      bodyCell: ...
    }
  }
  ...
}
const passThroughStyles = usePassThrough(Tailwind, primeVueTailwindOverrides)

export default defineNuxtConfig({
  primevue: {
    options: { pt: passThroughStyles, unstyled: true },
  },
  ...
})

Except some styles seem to randomly work.

Is this the correct way to add overrides to the Tailwind styles when using the module, btw? It's not mentioned in the docs.

@adirizky54
Copy link

Same issue with me, props from import Tailwind from 'primevue/passthrough/tailwind' not pass properly.

Screenshot 2023-10-19 at 00 36 53 Screenshot 2023-10-19 at 00 37 04 Screenshot 2023-10-19 at 00 37 38

@micheee
Copy link

micheee commented Oct 20, 2023

Same here, I'd be happy to sponsor a coffee once this is fixed ☕
My config is practically identical to the one @bipsen posted.

Which PrimeVue version are you using?

I am using the following versions:

@mertsincan
Copy link
Member

mertsincan commented Oct 20, 2023

Hi all,

I researched this issue in detail. The main reason for these issues is that there are non-serializable (exp; function) definitions in pt presets. Details; https://nuxt.com/docs/guide/going-further/runtime-config#serialization
When you examine the Tailwind preset, you will see that function definitions are used to specify conditional situations. Therefore, when we pass this preset to the PrimeVue object in the nuxt module, these definitions are serialized directly as '{}'.

For example, when you use the following config, it works fine.

// nuxt.config.js
primevue: {
   options: {
        pt: {
              button: {
                     root: 'MY_BUTTON_CLASS' // (serializable)
              }
        }
   }
}

But, the following config doesn't work;

// nuxt.config.js
primevue: {
   options: {
        pt: {
              button: {
                     root: () => 'MY_BUTTON_CLASS' // OR `root: function() { return { class: 'MY_BUTTON_CLASS' } }` etc. (non-serializable)
              }
        }
   }
}

Finally, I think there are 2 ways to solve this issue.

  1. Users can register PrimeVue with pt option manually. Exp;
// nuxt.config.js

primevue: {
   usePrimeVue: false,
   // options -> this key is unnecessary.
   ...
}
// custom plugin or main.js etc in your APP
import PrimeVue from 'primevue/config';

...
vueApp.use(PrimeVue, { pt: Tailwind || <CUSTOM_PRESET>, unstyled: true, ... });
  1. We can add a special structure to module for 'pt' option. Exp;
// nuxt.config.js

primevue: {
   options: {
        pt: { 
              as: 'Tailwind',
              from: 'primevue/passthrough/tailwind',
              set: 'Tailwind'
        }
   }
}

Transform;

// in nuxt-primevue
import <pt.as> from <pt.from>;

vueApp.use(PrimeVue, { ...options, pt: <pt.set> })

WDYT?

@mertsincan mertsincan added enhancement New feature or request help wanted Extra attention is needed and removed bug Something isn't working labels Oct 20, 2023
@deepfriedmind
Copy link

Either way, this would still force you to keep your custom styles in the Nuxt config file, right? Because currently, you have to restart the dev server for any style change (unless I'm missing something), which is not sustainable. With the implementation before this module, i.e. with a custom Nuxt plugin, only the page is reloaded (which is still a pain compared to HMR).

@mertsincan
Copy link
Member

mertsincan commented Oct 20, 2023

HMR is entirely related to Nuxt's configurations(nuxt/issues/18964). As far as I know, you can establish an HMR structure in Nuxt using Vite's infrastructure. The details can be found in the Vite documentation. https://vitejs.dev/guide/api-hmr.html#hmr-api

Regarding the main topic, if you follow a similar path to the solution I initially suggested (think of it as if you were not using the Nuxt-PrimeVue module), all configurations are within your control. You can adjust PrimeVue options according to your needs. You can even perform overrides using the 'UsePassThrough' feature.

My second suggestion is to have a preset ready. With this prepared preset, the nuxt-primevue module creates a plugin internally and imports it. Then, it adds its value to the options section when registering for PrimeVue.

@deepfriedmind
Copy link

I mean that you can't get HMR (or auto page reload) to work for changes to nuxt.config.ts, so if you keep the Tailwind style overrides there it will require a server restart if you change anything. And as far as I can tell, that's what you need to do with this module currently, unless you add usePrimeVue: false and add a file to /plugins yourself (in which case you can get auto page reload, not sure about HMR). And pardon me if I'm ignorant but it's not clear to me from the documentation what this actually entails:

Whether to install the PrimeVue plugin, defaults to true. Disable this option if you prefer to configure PrimeVue manually e.g. with a Nuxt plugin.

i.e. what does this module do if I'm creating a Nuxt plugin manually anyway? (which is what I was already doing before this existed). I'm confused 🙂

Also, I saw in this discussion that usePassThrough is not recommended anymore.

@mertsincan
Copy link
Member

mertsincan commented Oct 20, 2023

i.e. what does this module do if I'm creating a Nuxt plugin manually anyway? (which is what I was already doing before this existed). I'm confused 🙂

So let's start with the question of what the module is needed for.

  1. Users wanted to register all components with a single config instead of registering all components/directives one by one.
modules: ['nuxt-primevue']

instead of 

vueApp.component('Button', Button);
vueApp.component('DataTable', DataTable);
vueApp.component('InputText', InputText);
etc.
  1. As you know, we recently added unstyled mode to PrimeVue. While implementing this mode, we made some adjustments in the core to keep the css as a string and add it to the document in cases where it is not an unstyled mode. So how does this work? When you set PrimeVue to 'unstyled: false', the css of your components kept as strings are added to the document using useStyle (This is the process of creating <style> with JS and adding css into it. document.createElement('style')). So what problems did this cause? As you know, this structure only works on the client side because it uses the 'document' object. That's why it caused this flicker in Nuxt. No styles injected on SSR resulting in Large Layout Shifts on load  primevue#4210
    https://www.reddit.com/r/vuejs/comments/17asb5r/comment/k5ggkga/?utm_source=share&utm_medium=web2x&context=3

Code Refs;
https://github.com/primefaces/primevue/blob/master/components/lib/accordion/style/AccordionStyle.js#L3
https://github.com/primefaces/primevue/blob/master/components/lib/usestyle/UseStyle.js#L28

We created the nuxt-primevue module to fix the issues I mentioned above. This module will be of great importance in our new styled mode structure in the future.
https://www.youtube.com/watch?v=iBJU3T4A8Jo&t=52s (Cagatay gave clues on the new styled mode structure.)

unless you add usePrimeVue: false and add a file to /plugins yourself (in which case you can get auto page reload, not sure about HMR). And pardon me if I'm ignorant but it's not clear to me from the documentation what this actually entails:

What I'm talking about here is not entirely about you creating a plugin. Where you will register the components, PrimeVue, Services is up to you. So what does the usePrimeVue option do? When you use the 'usePrimeVue: true' option, nuxt-primevue module automatically adds a structure like vueApp.use(PrimeVue, options) in itself. Users do not need to add this manually. In some cases, users may want to set the 'options' parameter dynamically according to certain conditions, or as I mentioned above, 'serializable/non-serializable' limitations may arise. In such cases, users are expected to make vueApp.use(PrimeVue, options) themselves by using usePrimeVue: false. This is the same as when you use it without the module. In short, usePrimeVue only decides whether the structure vueApp.use(PrimeVue, options) will be added by the module.

Code Ref: https://github.com/primefaces/primevue-nuxt-module/blob/main/src/module.ts#L79

Also, I saw in this discussion that usePassThrough is not recommended anymore.

Yes, our suggestion is that users create their own presets instead of overriding them. This allows users to establish a more controllable structure. So why don't we recommend usePassThrough first? The best example of this is trying to change the bg of a button. Imagine having a style like the one below or imagine that the tailwind class generates something like this;

.bg-red {
   background: red;
}

.bg-blue {
   background: blue;
}

If we used the bg-blue class to change the bg of a button in the preset and you override it with usePassThrough and set bg-red, the bg of the button will be blue according to the css above. This is a very simple example, but I hope it explains the subject better. You can think of this in more complex structures.

I hope these details didn't confuse you even more :)

@cagataycivici
Copy link
Member

Personally I would not want to keep raw PT config in nuxt config, we'll discuss this for sure at earliest.

@micheee
Copy link

micheee commented Oct 20, 2023

I had success now, I followed @mertsincan first proposal:

Added: plugins/tailprime.ts

import PrimeVue from "primevue/config";
import Tailwind from "primevue/passthrough/tailwind";

export default defineNuxtPlugin((app) => {
  app.vueApp.use(PrimeVue, { unstyled: true, pt: Tailwind });
});

And the following nuxtconfig.ts

// https://nuxt.com/docs/api/configuration/nuxt-config
/** @type {import('nuxt').Config} */
export default defineNuxtConfig({
  devtools: { enabled: true },
  css: ["primeicons/primeicons.css"],

  postcss: {
    plugins: {
      tailwindcss: {},
      autoprefixer: {},
    },
  },
  modules: ["nuxt-primevue", "@nuxtjs/tailwindcss"],
  primevue: {
    usePrimeVue: false,
  },
});

So there's no raw PT config (as far as I understand); however, it would be just a tiny tad nicer if I wouldn't need the plugins/tailprime.ts-Plugin.

But for now, at least all services, components and directives are registered globally without manual intervention, so that is already a big plus for me :)

@deepfriedmind
Copy link

@mertsincan Thank you very much for the detailed explanation. That, along with the implementation example from @micheee makes it clear what the benefit of the module is compared to a 100% custom plugin implementation. So I guess now the question becomes, how can the same DX be achieved, without the need for usePrimeVue: false and manually creating/configuring a plugin? 🙂 And @micheee, I assume your setup still doesn't provide HMR, right? So, that's another question 😄
Anyways, I'm super happy that there's finally an official Nuxt module and I'm very excited about the new tailwind.primevue.org
Thanks for the great work 🙌

@micheee
Copy link

micheee commented Oct 20, 2023

And @micheee, I assume your setup still doesn't provide HMR, right? So, that's another question 😄

I'm not 100% sure if everything is working, but for me, it's working quite well so far:

localhost3000list2023-10-20 at 23 07 48

I can add PrimeVue-components and change <script> without having to reload manually 👍

@mertsincan
Copy link
Member

Thanks a lot, @micheee @deepfriedmind ;) In addition, when you set usePrimeVue: false, there is no need for the options key. You can use other keys(components, directives and composables in the module) without problems.

@cagataycivici, I totally agree with you. But we should not forget that there is no rule that we cannot use pt in a module. We cannot use pt structures containing non-serializable definitions. This is also a situation related to Nuxt. If they do a study on this in the future, we can immediately integrate the improvements into the nuxt-primevue module. Details; #6 (comment)

@sfxcode
Copy link

sfxcode commented Oct 23, 2023

Good morning,

i run into the same problem with my primevue-nuxt module. Only solution i found was NOT to include pt in the module configuration, but configure it in app.vue:

const primevue = usePrimeVue();
primevue.config.pt = Tailwind

After some tests with this module i would do it the same way. Easy to switch themes like in the demo from @cagataycivici .
So i see no big problem with this topic.

Greetings,

Tom

@mertsincan
Copy link
Member

Hi,

Thanks a lot for your feedback, @sfxcode ;) We are always open to alternative solutions. Frankly, I have a few ideas, I plan to discuss them with the team and share them with you.

@karinegomes
Copy link

I installed the Nuxt module today and I'm also having styling issues with Tailwind. I have a custom PrimeVue theme and I'm using Tailwind mostly for the utility classes, so I'm not using pass-through, but Tailwind's styling are taking precedence over PrimeVue's theme. I tried changing the layers order but it didn't work:

@layer primevue, tailwind-base, tailwind-utilities;

@layer tailwind-base {
  @tailwind base;
}

@layer tailwind-utilities {
  @tailwind components;
  @tailwind utilities;
}

@mertsincan
Copy link
Member

Hi all,

I'm working on new module options. I will complete it asap and share it with you.

@mertsincan mertsincan removed the help wanted Extra attention is needed label Oct 23, 2023
@mertsincan
Copy link
Member

mertsincan commented Oct 24, 2023

Hi all,

I added the importPT option to use pt presets and the cssLayerOrder option to solve Tailwind order issues;
#10
#11

Usage with usePassThrough(But, please see #6 (comment))

// nuxt.config.js
import path from 'path';
...

primevue: {
  importPT: { as: 'CustomTailwind', from: path.resolve(__dirname, './assets/presets/custom.js')}
  ...
}
// assets/presets/custom.js
import { usePassThrough } from 'primevue/passthrough';
import Tailwind from 'primevue/passthrough/tailwind';

const CustomTailwind = usePassThrough(Tailwind, {
    button: {
        root: 'my-button'
    }
}, { mergeProps: true });

export default CustomTailwind;

🚀 Thank you very much everyone for all the feedback 🤙

@mertsincan mertsincan modified the milestone: 0.0.4 Oct 24, 2023
@alterhu2020
Copy link

Hi @mertsincan
Can you help me check whether this setting not works, which tailwind override the primevue all style?
https://stackblitz.com/edit/nuxt-starter-owueub?file=nuxt.config.ts

thanks very much

@mertsincan
Copy link
Member

mertsincan commented Oct 24, 2023

Hi @alterhu2020,

The new version has not been released yet. I plan to release it with the PrimeVue version tomorrow. You can try its after it is released. I'm also updating the documentation.

Best Regards,

@mertsincan
Copy link
Member

Hi all,

PrimeVue v3.38.1 and Nuxt-PrimeVue v0.1.0 released 🚀

@mertsincan
Copy link
Member

Nuxt-PrimeVue + Tailwind starter updated; https://github.com/primefaces/primevue-examples/tree/main/nuxt-styled-tailwind

New module doc; https://primevue.org/nuxt/

@deepfriedmind
Copy link

importPT: { as: 'CustomTailwind', from: path.resolve(__dirname, './assets/presets/custom.js')}

This tripped me up for a bit so it should probably be mentioned in the docs that you need to add this file as a "content file" in your Tailwind config as well, e.g.:

content: [
  './node_modules/primevue/**/*.{vue,js,ts,jsx,tsx}',
  './assets/presets/custom.js',
]

Otherwise, all the Tailwind classes used only in that file will be purged and won't work.

Oh, and to reiterate, this method allows for auto reload on save, but not HMR, as far as I can tell.

@zelarg
Copy link

zelarg commented Dec 15, 2023

Hi,

I was looking forward to importPT, but it doesn't seem to work for me out of some reason ... After couple of tries, I did test also on (unstyled) Nuxt-PrimeVue + Tailwind starter and I do struggle with same error also there (full console output at the bottom).
ERROR Failed to resolve import "C:Dev emp-primevue-examplepresetslara" from "virtual:nuxt:C:\Dev\temp-primevue-example\.nuxt\primevue-plugin.mjs". Does the file exist?

I must be doing something wrong, but I'm unable to figure it out... Is that starter project supposed to be working with latest nuxt+nust-primevue+tailwind? (the "styled" version works for me)

Node version v21.3.0 (tried also v18), [email protected], [email protected], @nuxtjs/[email protected]

Thanks!

C:\Dev\temp-primevue-example>npm run dev

> dev
> nuxt dev

Nuxt 3.8.0 with Nitro 2.7.0                                                                                   19:18:47
                                                                                                              19:18:47
  ➜ Local:    http://localhost:3000/
  ➜ Network:  use --host to expose

i Using Tailwind CSS from ~/assets/css/tailwind.css                                          nuxt:tailwindcss 19:18:48
  ➜ DevTools: press Shift + Alt + D in the browser (v1.0.0)                                                   19:18:49

i Tailwind Viewer: http:/localhost:3000/_tailwind/                                           nuxt:tailwindcss 19:18:49

[19:18:50]  ERROR  Failed to resolve import "C:Dev    emp-primevue-examplepresetslara" from "virtual:nuxt:C:\Dev\temp-primevue-example\.nuxt\primevue-plugin.mjs". Does the file exist?

i Vite client warmed up in 3193ms                                                                             19:18:53
√ Nitro built in 650 ms                                                                                 nitro 19:18:53

@mertsincan
Copy link
Member

mertsincan commented Dec 15, 2023

Hi,

Interesting! It works fine for me;
Screen Shot 2023-12-15 at 19 50 45

There may be a problem with the path. Please check importPT: { ..., from: path.resolve(__dirname, './presets/lara/') },
You can customize the from option according to your needs.

@zelarg
Copy link

zelarg commented Dec 15, 2023

Oh, sorry, I forgot to include nuxt.config.ts of my project, there I have:
(basically taken from primevue samples)

import { resolve } from 'path'
...
export default defineNuxtConfig({
...
primevue: {
        options: { unstyled: true, ripple: true },
        cssLayerOrder: 'tailwind-base, primevue, tailwind-utilities',
        importPT: { as: 'Lara', from: resolve(__dirname, './assets/primevue-themes/lara/') },
        components: {
             exclude: ['Editor', 'Chart'],
        },
    },

And the second test - using the unstyled starter, I'm using that as-is, so:

import * as path from 'path';

export default defineNuxtConfig({
    modules: ['@nuxtjs/tailwindcss', "nuxt-primevue"],
    primevue: {
        options: { unstyled: true },
        cssLayerOrder: "tailwind-base, primevue, tailwind-utilities",
        importPT: { as: 'Lara', from: path.resolve(__dirname, './presets/lara/') },
...

I tried bunch of different 'from' attributes:
from: './presets/lara/'
from: '~/presets/lara/'
from: '/presets/lara/'
from: 'presets/lara/'

Unfortunately, with no luck :( It looks like "something" might be broken in my npm packages then?

@mertsincan
Copy link
Member

Hmm. interesting. Could you please try it after deleting package-lock.json, node_modules and .nuxt, then npm install.

Do you confirm that you are using our sample project and have not changed anything?

@zelarg
Copy link

zelarg commented Dec 16, 2023

Do you confirm that you are using our sample project and have not changed anything?

I do confirm.

I start with project nuxt-unstyled-tailwind and do only npm install and npm run dev.
Here's a short video: https://drive.google.com/file/d/11YOag26dAuunrf9V7ml3sagLP9MHblVr/view?pli=1

As far as I can tell, I do not have nuxt/vue/primevue/tailwind installed globally:

c:\>npm list -g --depth=0
C:\Program Files\nodejs -> .\
+-- [email protected]
`-- [email protected]

@jaroslavek
Copy link

I have the same problem. I'm working on windows 11. Isn't the problem only in windows?

@mertsincan
Copy link
Member

I checked your error again. [19:18:50] ERROR Failed to resolve import "C:Dev emp-primevue-examplepresetslara
The path is not correct. (examplepresetslara) I think this issue is related to 'path' package with Windows. Could you please try;
path.resolve(__dirname, './/presets//lara//')
path.resolve(__dirname, '.\\presets\\lara\\')

@zelarg
Copy link

zelarg commented Dec 27, 2023

Hi,

Thanks for the feedback, here's what I tried (changing forward slash to backslash):

  • I have used nuxt-unstyled-tailwind sample project (same as before)
  • Changed nuxt.config.ts, using backslashes, like this;
    image
  • Result is basically the same as before:
ERROR  Failed to resolve import "C:Dev                                                                       12:45:51
uxt-unstyled-tailwindpresetslara" from "virtual:nuxt:C:\Dev\nuxt-unstyled-tailwind\.nuxt\primevue-plugin.mjs". Does the file exist?

See a screenshot from the 'cmd' console:
image

@craigjamesdobson
Copy link

I had the exact same issue as you @zelarg and changing the importPT to this on windows worked for me.

importPT: { as: "Lara", from: "~/presets/lara" },

@zelarg
Copy link

zelarg commented Dec 27, 2023

@craigjamesdobson Perfect, thanks! That fixed the problem on Windows for me.

@pjcunningham
Copy link

Yes, you should avoid cjs dependencies like __dirname link

importPT: { as: 'Lara', from: '@/presets/lara/' },

@muhdammar
Copy link

thank u bro @craigjamesdobson you saved my project!

@llops
Copy link

llops commented Jan 15, 2024

@craigjamesdobson another one who has to thank you 🥂

@xak2000
Copy link

xak2000 commented Jan 26, 2024

I followed the instructions on https://tailwind.primevue.org/nuxt/#preset on Windows 11 and was unable to make it work until I found the solution in the last comments of this issue.

@mertsincan Maybe it is worth to update the documentation and examples to get rid of path.resolve and use ~/presets/lara instead? As far as I understand Nuxt resolves the path by itself. Please correct me if I'm wrong.

I.e.:

importPT: { as: 'Lara', from: '~/primevue/presets/lara' },

Tested on Windows 11. Didn't test on Linux/Mac yet, but probably it will work as the path resolving is working correctly in other imports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests