Gathering detailed insights and metrics for vue-tailwind
Gathering detailed insights and metrics for vue-tailwind
Gathering detailed insights and metrics for vue-tailwind
Gathering detailed insights and metrics for vue-tailwind
vue-cli-plugin-tailwind
vue-cli plugin for Tailwind CSS
@headlessui/vue
A set of completely unstyled, fully accessible UI components for Vue 3, designed to integrate beautifully with Tailwind CSS.
daisyui
daisyUI 5 - The Tailwind CSS Component Library
@dao-style/vue-cli-plugin-tailwind
Tailwind plugin for vue-cli
Vue UI components with configurable classes ready for TailwindCSS
npm install vue-tailwind
Typescript
Module System
Node Version
NPM Version
TypeScript (60.31%)
JavaScript (38.5%)
Vue (1.1%)
HTML (0.09%)
CSS (0.01%)
Total Downloads
853,220
Last Day
408
Last Week
2,132
Last Month
8,991
Last Year
122,835
MIT License
2,167 Stars
1,047 Commits
134 Forks
26 Watchers
21 Branches
19 Contributors
Updated on Apr 25, 2025
Minified
Minified + Gzipped
Latest Version
2.5.1
Package Id
vue-tailwind@2.5.1
Unpacked Size
2.75 MB
Size
381.49 kB
File Count
340
NPM Version
8.5.1
Node Version
17.6.0
Cumulative downloads
Total Downloads
Last Day
63.2%
408
Compared to previous day
Last Week
4.9%
2,132
Compared to previous week
Last Month
2%
8,991
Compared to previous month
Last Year
-26.4%
122,835
Compared to previous year
11
1
41
For more info, check the official site: https://vue-tailwind.com/.
VueTailwind is a set of Vue components created to be customized to adapt to your application's unique design.
Most component libraries depend on CSS frameworks with an opinionated and limited number of styles defined by the people who maintain those libraries.
Those libraries are great and make our work easy, but hey, we made a beautiful custom design, right?
We can use a framework like TailwindCss to define our style, but that will end with us writing long CSS classes repeatedly, which could quickly become unmaintainable. Also, create some components like modals, date pickers, etc., is a tricky task, and let's admit it, nobody has time for that, right?
The VueTailwind components are meant to be customized with custom CSS classes that you can define when you install the library.
Plus, most component settings are configurable, so using this library is like having your personal set of components for your particular needs.
All that means that with this library, you will be able to:
1npm install vue-tailwind --save
Or:
1yarn add vue-tailwind
This library uses TailwindCSS classes by default. Still, it should work with any CSS framework since all the CSS classes are configurable.
To install TailwindCSS follow his official documentation: https://tailwindcss.com/docs/installation
The default theme of this library depends on the @tailwindcss/forms
plugin. To use it, follow the steps on the plugin source page.
https://github.com/tailwindlabs/tailwindcss-forms
Also needed for the default theme and strongly recommended since it adds the ability to use some classes like disabled:opacity-50 disabled:cursor-not-allowed
to disabled inputs.
See https://tailwindcss.com/docs/configuring-variants on the TailwindCSS docs for more info.
As a reference, your tailwind.config.js
may look like this:
1module.exports = { 2 variants: { 3 extend: { 4 opacity: ['disabled'], 5 cursor: ['disabled'], 6 }, 7 }, 8 plugins: [ 9 require('@tailwindcss/forms'), 10 ], 11};
1import Vue from 'vue' 2import VueTailwind from 'vue-tailwind' 3 4const components = { 5 // ...You need to add the components you need here (explained above) 6} 7 8Vue.use(VueTailwind, components)
1import Vue from 'vue' 2import VueTailwind from 'vue-tailwind' 3 4import { 5 TInput, 6 TTextarea, 7 TSelect, 8 TRadio, 9 TCheckbox, 10 TButton, 11 TInputGroup, 12 TCard, 13 TAlert, 14 TModal, 15 TDropdown, 16 TRichSelect, 17 TPagination, 18 TTag, 19 TRadioGroup, 20 TCheckboxGroup, 21 TTable, 22 TDatepicker, 23 TToggle, 24 TDialog, 25} from 'vue-tailwind/dist/components'; 26 27const settings = { 28 // Use the following syntax 29 // {component-name}: { 30 // component: {importedComponentObject}, 31 // props: { 32 // {propToOverride}: {newDefaultValue} 33 // {propToOverride2}: {newDefaultValue2} 34 // } 35 // } 36 't-input': { 37 component: TInput, 38 props: { 39 classes: 'border-2 block w-full rounded text-gray-800' 40 // ...More settings 41 } 42 }, 43 't-textarea': { 44 component: TTextarea, 45 props: { 46 classes: 'border-2 block w-full rounded text-gray-800' 47 // ...More settings 48 } 49 }, 50 // ...Rest of the components 51} 52 53Vue.use(VueTailwind, settings)
1import Vue from 'vue' 2// Notice that I am using a different path here: 3import VueTailwind from 'vue-tailwind/dist/full' 4 5const settings = { 6 TInput: { 7 classes: 'border-2 block w-full rounded text-gray-800', 8 // ...More settings 9 }, 10 TButton: { 11 classes: 'rounded-lg border block inline-flex items-center justify-center', 12 // ...More settings 13 }, 14 // ...Rest of the components 15} 16 17Vue.use(VueTailwind, settings)
1import Vue from 'vue' 2import VueTailwind from 'vue-tailwind' 3 4import TInput from 'vue-tailwind/dist/t-input' 5import TButton from 'vue-tailwind/dist/t-button' 6 7const settings = { 8 't-input': { 9 component: TInput, 10 props: { 11 classes: 'block w-full px-3 py-2 text-black placeholder-gray-400 transition duration-100 ease-in-out bg-white border border-gray-300 rounded shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none focus:ring-opacity-50 disabled:opacity-50 disabled:cursor-not-allowed', 12 // ...More settings 13 } 14 }, 15 't-button': { 16 component: TButton, 17 props: { 18 classes: 'block px-4 py-2 text-white transition duration-100 ease-in-out bg-blue-500 border border-transparent rounded shadow-sm hover:bg-blue-600 focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none focus:ring-opacity-50 disabled:opacity-50 disabled:cursor-not-allowed', 19 // ...More settings 20 } 21 }, 22} 23 24Vue.use(VueTailwind, settings)
Note: Using the syntax from point 3.3 is the best way to prevent a big bundle size but only if you import a couple of components. If the number of components you install increases, the recommended way to install them is to use the syntax from the points 3.1 or 3.2 to help the library reuse some code and keep the bundle size at a minimum.
To apply a custom theme you should play with the classes
, fixedClasses
, and variants
props.
The classes
and fixedClasses
props usually expects an string
with a CSS class for single-tag components (inputs, button, etc.) and an object
for more complex components (modals, datepicker, etc) (see component docs for details).
The variants
props expects an object where every key represents the variant name and every value the classes that will be used when that variant is applied.
1import Vue from 'vue' 2import VueTailwind from 'vue-tailwind' 3import TButton from 'vue-tailwind/dist/t-button' 4 5const settings = { 6 't-button': { 7 component: TButton, 8 props: { 9 // The fixed classes will never change and will be merged with the `classes` value or the active variant 10 fixedClasses: 'focus:outline-none focus:shadow-outline inline-flex items-center transition ease-in-out duration-150', 11 // Classes used when any variant is active 12 classes: 'text-white bg-blue-600 hover:bg-blue-500 focus:border-blue-700 active:bg-blue-700 text-sm font-medium border border-transparent px-3 py-2 rounded-md', 13 variants: { 14 // A red variant of the button (applied when `<t-button variant="error" />`) 15 error: 'text-white bg-red-600 hover:bg-red-500 focus:border-red-700 active:bg-red-700 text-sm font-medium border border-transparent px-3 py-2 rounded-md', 16 // A green variant of the button (applied when `<t-button variant="success" />`) 17 success: 'text-white bg-green-600 hover:bg-green-500 focus:border-green-700 active:bg-green-700 text-sm font-medium border border-transparent px-3 py-2 rounded-md', 18 // ...unlimited variants 19 } 20 // ...More settings 21 } 22 }, 23} 24 25Vue.use(VueTailwind, settings)
1import Vue from 'vue' 2import VueTailwind from 'vue-tailwind' 3import TAlert from 'vue-tailwind/dist/t-alert' 4 5const settings = { 6 't-alert': { 7 component: TAlert, 8 props: { 9 // The fixed classes will never change and will be merged with the `classes` value or the active variant 10 fixedClasses: { 11 wrapper: 'rounded p-4 flex text-sm border-l-4', 12 body: 'flex-grow', 13 close: 'ml-4 rounded', 14 closeIcon: 'h-5 w-5 fill-current' 15 }, 16 classes: { 17 wrapper: 'bg-blue-100 border-blue-500', 18 body: 'text-blue-700', 19 close: 'text-blue-700 hover:text-blue-500 hover:bg-blue-200', 20 closeIcon: 'h-5 w-5 fill-current' 21 }, 22 variants: { 23 danger: { 24 wrapper: 'bg-red-100 border-red-500', 25 body: 'text-red-700', 26 close: 'text-red-700 hover:text-red-500 hover:bg-red-200' 27 // Notice that I am not defining the `closeIcon` class since we only 28 // need to write the classes we want to override 29 }, 30 } 31 } 32 }, 33} 34 35Vue.use(VueTailwind, settings)
All the components on this library have default settings added as component props according to how we understand those settings are most commonly used.
I am aware that in many cases is useful to change the default value, so you don't need to add the prop over and over when needed.
1import Vue from 'vue' 2import VueTailwind from 'vue-tailwind' 3 4import TDatepicker from 'vue-tailwind/dist/t-datepicker' 5import TButton from 'vue-tailwind/dist/t-button' 6import TModal from 'vue-tailwind/dist/t-modal' 7 8// Locale to eventually replace the default Datepicker locale 9import Spanish from 'vue-tailwind/dist/l10n/es' 10 11const settings = { 12 't-button': { 13 component: TButton, 14 props: { 15 // classes: '...', 16 // variants: '...', 17 // ... 18 // Originally it defaults to `undefined` that means is considered a submit 19 // button if the button is inside a form. 20 type: 'button', 21 } 22 }, 23 't-datepicker': { 24 component: TDatepicker, 25 props: { 26 // classes: '...', 27 // variants: '...', 28 // ... 29 // Originally a locale object with English values 30 locale: Spanish, 31 } 32 }, 33 't-modal': { 34 component: TModal, 35 props: { 36 // classes: '...', 37 // variants: '...', 38 // ... 39 // Originally `true` 40 escToClose: false, 41 } 42 }, 43} 44 45Vue.use(VueTailwind, settings)
You can also use this feature to create different versions of the same component.
1import Vue from 'vue' 2import VueTailwind from 'vue-tailwind' 3 4import TButton from 'vue-tailwind/dist/t-button' 5import TTag from 'vue-tailwind/dist/t-tag' 6 7const settings = { 8 // What about one <t-button /> for normal button and a `<t-submit />` for a submit button 9 't-button': { 10 component: TButton, 11 props: { 12 type: 'button', 13 } 14 }, 15 't-submit': { 16 component: TButton, 17 props: { 18 type: 'submit', 19 } 20 }, 21 // I love this use case for the TTag component and will let you guess what 22 // is doing: 👇 23 'blog-title': { // Used like <blog-title>Title of a blog post</blog-title> 24 component: TTag, 25 props: { 26 tag: 'h1', 27 classes: 'font-semibold text-xl leading-6', 28 } 29 }, 30 'blog-subtitle': { // Used like <blog-title>subtitle of a blog post</blog-title> 31 component: TTag, 32 props: { 33 tag: 'h2', 34 classes: 'font-semibold text-xl leading-6', 35 } 36 }, 37 't-link': { // Used like <t-link href="">Open site</t-link> 38 component: TTag, 39 props: { 40 tag: 'a', 41 classes: 'text-blue-500 underline hover:text-blue-600', 42 } 43 } 44} 45 46Vue.use(VueTailwind, settings)
Once your different variants were defined you can use the variant
prop to define which variant should be applied:
1<t-input variant="error" />
The variant prop also accepts an object that takes the first attribute with a truthy value
1<t-input 2 :variant="{ 3 error: inputIsNotValid, 4 success: inputIsValid, 5 }" 6/>
Is this project helpful for you? Consider sponsoring me https://github.com/sponsors/alfonsobries.
Of course, any other kind help is welcome, even if you notice some grammar mistakes (English is not my primary language) see contribute page for details.
Please see Release notes for more information about what was changed recently.
If you discover any security related issues, please email alfonso@vexilo.com instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.
Made with love by @alfonsobries
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 4/17 approved changesets -- score normalized to 2
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
102 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-05-05
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More