90+ Vue UI Components Styled with Tailwind CSS
Tags: vue
Published: 2023-08-30 20:42:44

[PrimeVue](https://primevue.org) has recently announced the new [Unstyled](https://primevue.org/unstyled/) mode that removes the default styling and exposes the component internals via [pass through props](https://primevue.org/passthrough/properties) API. With the unstyled mode, components do the hard work by providing the feature set and accessibility out of the box but leaves out the styling to the user.

Although any CSS library like Bootstrap and Bulma can be used, Tailwind CSS integration is match made in heaven, there is even a built-in Tailwind theme available in PrimeVue.

Interested? Let's dive in!

##Setup
This part assumes that Tailwind is already available in your application, if not visit the Tailwind CSS [framework guides](https://tailwindcss.com/docs/installation/framework-guides) like Vite or Nuxt for the installation. The built-in default theme is basically a [global pass through](https://primevue.org/passthrough/) configuration that needs to be imported from **primevue/passthrough/tailwind** path and then defined during setup. Since the theme is exclusive to unstyled mode, the **unstyled** setting is required in addition.

```js
import {createApp} from "vue";
import PrimeVue from "primevue/config";
import Tailwind from "primevue/passthrough/tailwind";

const app = createApp(App);

app.use(PrimeVue, { unstyled: true, pt: Tailwind });
```

Tailwind uses PurgeCSS internally to remove unused classes, since PrimeVue components are loaded from node_modules the **content** property at **tailwind.config.js** needs to be aware of PrimeVue, otherwise the classes utilized in the theme will be removed as well.

```js
export default {
    ...
    content: [
        "./index.html",
        "./src/**/*.{vue,js,ts,jsx,tsx}",
        "./node_modules/primevue/**/*.{vue,js,ts,jsx,tsx}"
    ],
    ...
}
```

Voilà 💚, you now have 90+ awesome Vue UI components styled with Tailwind that will work in harmony with the rest of your application.

##Customization
The built-in theme provides a strong base that can be extended further for your requirements. For customization, the pass through values need to be overriden. The unstyled section of the theming documentation for each component demonstrates the theme with an editable example. For instance, the panel component has the following default configuration.

```js
panel: {
    header: ({ props }) => ({
        class: [
            'flex items-center justify-between', // flex and alignments
            'border border-gray-300 bg-gray-100 text-gray-700 rounded-tl-lg rounded-tr-lg', // borders and colors
            'dark:bg-gray-900 dark:border-blue-900/40 dark:text-white/80', // Dark mode
            { 'p-5': !props.toggleable, 'py-3 px-5': props.toggleable } // condition
        ]
    }),
    title: {
        class: ['leading-none font-bold']
    },
    toggler: {
        class: [
            'inline-flex items-center justify-center overflow-hidden relative no-underline', // alignments
            'w-8 h-8 text-gray-600 border-0 bg-transparent rounded-full transition duration-200 ease-in-out', // widths, borders, and transitions
            'hover:text-gray-900 hover:border-transparent hover:bg-gray-200 dark:hover:text-white/80 dark:hover:bg-gray-800/80 dark:focus:shadow-[inset_0_0_0_0.2rem_rgba(147,197,253,0.5)]', // hover
            'focus:outline-none focus:outline-offset-0 focus:shadow-[0_0_0_0.2rem_rgba(191,219,254,1)]' // focus
        ]
    },
    togglerIcon: {
        class: ['inline-block']
    },
    content: {
        class: [
            'p-5 border border-gray-300 bg-white text-gray-700 border-t-0 last:rounded-br-lg last:rounded-bl-lg',
            'dark:bg-gray-900 dark:border-blue-900/40 dark:text-white/80' // Dark mode
        ] // padding, borders, and colors
    }
},
```

Let's assume the title section should be lighter and bigger.

```js
import {createApp} from "vue";
import PrimeVue from "primevue/config";
import { usePassThrough } from "primevue/passthrough";
import Tailwind from "primevue/passthrough/tailwind";

const app = createApp(App);

//Tailwind customization
const CustomTailwind = usePassThrough(
    Tailwind,
    {
        panel: {
            title: {
                class: ['leading-none font-light text-2xl']
            }
        }
    },
    {
        mergeSections: true,  // Used to merge with other PT sections. The default is true.
        mergeProps: false,    // Whether to use override or merge with existing configuration
    }
);

app.use(PrimeVue, { unstyled: true, pt: CustomTailwind });
```

##Example

Take a look at the CodeSandbox sample to see the Tailwind CSS + PrimeVue in action
{% embed https://codesandbox.io/p/sandbox/unstyled-primevue-dialog-with-tailwind-css-2jp96n?embed=1 %}