primefaces / primevue-nuxt-module

MIT License
73 stars 11 forks source link

Can't get to work with Tailwind #6

Closed bipsen closed 1 year ago

bipsen commented 1 year ago

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 commented 1 year ago

Hi,

Which PrimeVue version are you using?

mertsincan commented 1 year ago

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

deepfriedmind commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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:

nuxt@3.8.0
nuxt-primevue@0.0.3
primevue@3.37.0
@nuxtjs/tailwindcss@6.8.0
tailwindcss@3.3.3
mertsincan commented 1 year ago

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, ... });

2) 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?

deepfriedmind commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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.

2) 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