Giter Club home page Giter Club logo

vue-tailwind's Introduction

Vue-Tailwind

CI

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.

Another UI library?

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?

So what are the alternatives?

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?

Best of both worlds

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:

  • Define your components look and feel by defining custom default CSS classes.
  • Add unlimited variants for every specific use case.
  • Override the default value of the props according to your needs.
  • Create different versions of one component with different default settings.

Installation

1. Install the dependencies

npm install vue-tailwind --save

Or:

yarn add vue-tailwind

2. Install TailwindCSS (Optional)

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

2.1 Add the @tailwindcss/forms plugin

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

2.1 Add variants for disabled pseudo-class

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:

module.exports = {
  variants: {
    extend: {
      opacity: ['disabled'],
      cursor: ['disabled'],
    },
  },
  plugins: [
    require('@tailwindcss/forms'),
  ],
};

3. Configure Vue to use vue-tailwind

import Vue from 'vue'
import VueTailwind from 'vue-tailwind'

const components = {
  // ...You need to add the components you need here (explained above)
}

Vue.use(VueTailwind, components)

3.1 Import and install the components

import Vue from 'vue'
import VueTailwind from 'vue-tailwind'

import {
  TInput,
  TTextarea,
  TSelect,
  TRadio,
  TCheckbox,
  TButton,
  TInputGroup,
  TCard,
  TAlert,
  TModal,
  TDropdown,
  TRichSelect,
  TPagination,
  TTag,
  TRadioGroup,
  TCheckboxGroup,
  TTable,
  TDatepicker,
  TToggle,
  TDialog,
} from 'vue-tailwind/dist/components';

const settings = {
  // Use the following syntax
  // {component-name}: {
  //   component: {importedComponentObject},
  //   props: {
  //     {propToOverride}: {newDefaultValue}
  //     {propToOverride2}: {newDefaultValue2}
  //   }
  // }
  't-input': {
    component: TInput,
    props: {
      classes: 'border-2 block w-full rounded text-gray-800'
      // ...More settings
    }
  },
  't-textarea': {
    component: TTextarea,
    props: {
      classes: 'border-2 block w-full rounded text-gray-800'
      // ...More settings
    }
  },
  // ...Rest of the components
}

Vue.use(VueTailwind, settings)

3.2 Alternatively, you can use the v1.0 syntax

import Vue from 'vue'
// Notice that I am using a different path here:
import VueTailwind from 'vue-tailwind/dist/full'

const settings = {
  TInput: {
    classes: 'border-2 block w-full rounded text-gray-800',
    // ...More settings
  },
  TButton: {
    classes: 'rounded-lg border block inline-flex items-center justify-center',
    // ...More settings
  },
  // ...Rest of the components
}

Vue.use(VueTailwind, settings)

3.3 Or install only the components you need

import Vue from 'vue'
import VueTailwind from 'vue-tailwind'

import TInput from 'vue-tailwind/dist/t-input'
import TButton from 'vue-tailwind/dist/t-button'

const settings = {
  't-input': {
    component: TInput,
    props: {
      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',
      // ...More settings
    }
  },
  't-button': {
    component: TButton,
    props: {
      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',
      // ...More settings
    }
  },
}

Vue.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.

Read more β†’

Theming

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.

Example for a single-tag component:

import Vue from 'vue'
import VueTailwind from 'vue-tailwind'
import TButton from 'vue-tailwind/dist/t-button'

const settings = {
  't-button': {
    component: TButton,
    props: {
      // The fixed classes will never change and will be merged with the `classes` value or the active variant
      fixedClasses: 'focus:outline-none focus:shadow-outline inline-flex items-center transition ease-in-out duration-150',
      // Classes used when any variant is active
      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',
      variants: {
        // A red variant of the button (applied when `<t-button variant="error" />`)
        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',
        // A green variant of the button (applied when `<t-button variant="success" />`)
        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',
        // ...unlimited variants
      }
      // ...More settings
    }
  },
}

Vue.use(VueTailwind, settings)

Example for a complex component:

import Vue from 'vue'
import VueTailwind from 'vue-tailwind'
import TAlert from 'vue-tailwind/dist/t-alert'

const settings = {
  't-alert': {
    component: TAlert,
    props: {
      // The fixed classes will never change and will be merged with the `classes` value or the active variant
      fixedClasses: {
        wrapper: 'rounded p-4 flex text-sm border-l-4',
        body: 'flex-grow',
        close: 'ml-4 rounded',
        closeIcon: 'h-5 w-5 fill-current'
      },
      classes: {
        wrapper: 'bg-blue-100 border-blue-500',
        body: 'text-blue-700',
        close: 'text-blue-700 hover:text-blue-500 hover:bg-blue-200',
        closeIcon: 'h-5 w-5 fill-current'
      },
      variants: {
        danger: {
          wrapper: 'bg-red-100 border-red-500',
          body: 'text-red-700',
          close: 'text-red-700 hover:text-red-500 hover:bg-red-200'
          // Notice that I am not defining the `closeIcon` class since we only
          // need to write the classes we want to override
        },
      }
    }
  },
}

Vue.use(VueTailwind, settings)

Read more β†’

Override 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.

import Vue from 'vue'
import VueTailwind from 'vue-tailwind'

import TDatepicker from 'vue-tailwind/dist/t-datepicker'
import TButton from 'vue-tailwind/dist/t-button'
import TModal from 'vue-tailwind/dist/t-modal'

// Locale to eventually replace the default Datepicker locale
import Spanish from 'vue-tailwind/dist/l10n/es'

const settings = {
  't-button': {
    component: TButton,
    props: {
      // classes: '...',
      // variants: '...',
      // ...
      // Originally it defaults to `undefined` that means is considered a submit
      // button if the button is inside a form.
      type: 'button',
    }
  },
  't-datepicker': {
    component: TDatepicker,
    props: {
      // classes: '...',
      // variants: '...',
      // ...
      // Originally a locale object with English values
      locale: Spanish,
    }
  },
  't-modal': {
    component: TModal,
    props: {
      // classes: '...',
      // variants: '...',
      // ...
      // Originally `true`
      escToClose: false,
    }
  },
}

Vue.use(VueTailwind, settings)

You can also use this feature to create different versions of the same component.

import Vue from 'vue'
import VueTailwind from 'vue-tailwind'

import TButton from 'vue-tailwind/dist/t-button'
import TTag from 'vue-tailwind/dist/t-tag'

const settings = {
  // What about one <t-button /> for normal button and a `<t-submit />` for a submit button
  't-button': {
    component: TButton,
    props: {
      type: 'button',
    }
  },
  't-submit': {
    component: TButton,
    props: {
      type: 'submit',
    }
  },
  // I love this use case for the TTag component and will let you guess what
  // is doing: πŸ‘‡
  'blog-title': { // Used like <blog-title>Title of a blog post</blog-title>
    component: TTag,
    props: {
      tag: 'h1',
      classes: 'font-semibold text-xl leading-6',
    }
  },
  'blog-subtitle': { // Used like <blog-title>subtitle of a blog post</blog-title>
    component: TTag,
    props: {
      tag: 'h2',
      classes: 'font-semibold text-xl leading-6',
    }
  },
  't-link': { // Used like <t-link href="">Open site</t-link>
    component: TTag,
    props: {
      tag: 'a',
      classes: 'text-blue-500 underline hover:text-blue-600',
    }
  }
}

Vue.use(VueTailwind, settings)

Read more β†’

Workflow

Once your different variants were defined you can use the variant prop to define which variant should be applied:

<t-input variant="error" />

The variant prop also accepts an object that takes the first attribute with a truthy value

<t-input
  :variant="{
    error: inputIsNotValid,
    success: inputIsValid,
  }"
/>

Read more β†’

What's new in version 2.x

  • Install only the components you need for smaller bundle size
  • Custom name for components
  • The ability to install the same component multiple times with different default settings and name
  • New default theme

Plans for v3.x

  • Rebuild with Vue 3
  • Multiple typescript improvements
  • Stronger test coverage
  • Accesibility first
  • New Branding

Read more β†’

Contribute

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.

Changelog

Please see Release notes for more information about what was changed recently.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Made with love by @alfonsobries

vue-tailwind's People

Contributors

afflexux avatar alfonsobries avatar aravindpanicker avatar atymic avatar casperlaitw avatar cecicoding avatar dependabot[bot] avatar erickzh avatar francoisauclair911 avatar guastallaigor avatar ianjamieson avatar jaulz avatar jeanlouisgicquel avatar khairahscorner avatar murdockq avatar onmax avatar robertboes avatar xewl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-tailwind's Issues

help with modal

Hello thank for excellent project, i hope your help i dont know how i can have two column into the an Checkbox Group with a lot options, for example twenty, or well i how can have a modal with internal scroll in default template.
Currently my modal is very height
I try with:
<t-modal wrapper-class="bg-blue-100 border-blue-400 text-blue-700 rounded shadow-xl flex flex-col" overlay-class="top-0 bottom-0 right-0 w-1/2 fixed opacity-75" body-class="text-xl flex p-6" footerClass="bg-blue-400 p-3 flex justify-between" show ref="modal_alergias" > <template v-slot:header class="justify-around">Alergias mΓ‘s comunes</template> <template v-slor:default> <div class="w-full overflow-auto"> <t-checkbox-group v-model="calergias" name="checkbox-alergias" :selectAll="false" @change="passerAlergias" class="flex-col" :options="[ 'ALERGIAS NEGADAS','PENICILINA','ACAROS','CHOCOLATE','FRUTOS SECOS','HONGOS','HUMEDAD','LATEX','MARISCOS','MASCOTAS','MOHO','NIQUEL','PICADURA DE INSECTOS','POLEN','POLVO','SOL' ]" /> </div> </template> <template v-slot:footer> <t-button variant="tertiary" tertiary-class="border block text-white border-transparent hover:text-gray-300" @click="$refs.modal_alergias.hide()" >Cancelar</t-button> <t-button @click="$refs.modal_alergias.hide()" variant="danger">Aceptar</t-button> </template> </t-modal>
Thank for your time.

There are some mistyped words in documentation

Hello, i found some mistyped words and some examples that might be wrong in the documentation.

First I found some mistyped words in card documentation, I think this is because you are copy and paste from modal documentation πŸ˜†, so the word 'modal' in there should be 'card'.

Then I also found a strange example in using modal global methods documentation, I feel there are some mistakes there, and also there is one missing closing bracket.

I suggest you to re-check the documentation, may be there are some other mistakes in there.

Laravel Mix\

Hi ,

I can't seem to make a custom theme with laravel mix . Vue-tailwind works if I add props directly but my custom theme won't make any change .

My webpack.mix.js

const mix = require("laravel-mix");


mix.js("resources/js/app.js", "public/js")
    .webpackConfig({
        resolve: {
            alias: {
                "@": path.resolve(__dirname, "resources/js"),
                "@assets": path.resolve(__dirname, "resources/assets"),
                "@sass": path.resolve(__dirname, "resources/sass")
            }
        }
    })
    .options({
        hmrOptions: {
            host: "kick.test",
            port: 8080
        }
    })
    .postCss("resources/assets/css/main.css", "public/css", [
        require("tailwindcss")
    ]);

app.js

import Vue from "vue";
import App from "@/views/layout/app";

// Vue Router
import router from "./router";

import VueTailwind from "vue-tailwind";
import TailwindTheme from "./themes/tailwindTheme.js";
Vue.use(VueTailwind, {
    theme: TailwindTheme
});

var vm = new Vue({
    router,

    render: h => h(App)
}).$mount("#app");

tailwindTheme.js

const TInput = {
    // Notice that this will override the full `baseClass` setting so probably you want to keep some
    // of the clases and just replace the ones you want to override.
    // baseClass: 'border block w-full rounded',
    baseClass: "border block rounded",
    defaultStatusClass: "bg-white",
    warningStatusClass: "border-yellow-400 bg-yellow-100",
    errorStatusClass: "border-red-300 bg-red-100",
    successStatusClass: "border-green-300 bg-green-100",
    disabledClass: "bg-gray-100 cursor-not-allowed opacity-75",
    defaultSizeClass: "p-3",
    largeSizeClass: "p-4 text-lg",
    smallSizeClass: "p-2 text-sm"
};

const TButton = {
    // baseClass: 'border block rounded inline-flex items-center justify-center',
    baseClass:
        "rounded-lg border block inline-flex items-center justify-center",
    // primaryClass: 'text-white bg-blue-500 border-blue-500 hover:bg-blue-600 hover:border-blue-600',
    primaryClass:
        "text-black bg-purple-500 border-purple-500 hover:bg-purple-600 hover:border-purple-600"
};

const TailwindTheme = {
    TInput,
    TButton
};

export default TailwindTheme;

Not working after 0.4.2

The package.json appears to be using an entry point of:

"main": "./dist/vue-tailwind.common.js",

That file seems to not be getting built when v0.4.4 is being installed. It works if I install 0.4.2 though.

Feature request: Render anchor when a button has `to` or `href` attributes.

Hi!

I would be cool if buttons get rendered as anchors when you have a to or href attribute. I've noticed that when you click a button with a to prop, it activates when the left mouse button button is down (i think it should activate when mouse button is up), and also it activates then you click the right mouse button, which i think is a bug. An example of library that generates both button and a when necessary is Bootstrap-Vue.

I know you are busy and have other things, so i would be interested to implement this feature and make a pull request, if you authorize me.

Thanks in advance!

Null props error on t-dropdown and t-button (solution mooted)

When I use the t-dropdown component (using examples) I get:

[Vue warn]: Invalid prop: type check failed for prop "href". Expected String with value "null", got Null

Then if I click on the button I get:


[Vue warn]: Error in v-on handler: "TypeError: e is null"

found in

---> <TButton>
       <Popper> at popper.js.vue
         <TDropdown>
           <Index> at resources/js/pages/Dashboard/Participants/Index.vue
             <Dashboard> at resources/js/layouts/dashboard.vue
               <Inertia>
                 <Root>

Treeshaking

Hi, are we able to pick and choose the components to use? Reduce bundle size?

How to merge multiple variants?

Hi,

Hi have button with variants: primary and secondary. I also have a variant disabled with deals with opacity. I want to have a primary disabled button, but according to the doc, only one variant at a time can affect my button.

It can also happen if I have some variants for size like small, medium, big, so question is how to have a small primary variant?

How to deal with that?

thanks

before-close doesn't pass event on modals.

Hi!

I'm trying to prevent one of my app's modals from closing, but i'm not receiving the event parameter on my event handler. I have no idea of what to do, it just doesn't work :(

I'm using the component incorrectly?

<template>
  <t-modal ref="modal" v-model="show" ... @before-close="beforeClose">
    ...
  </t-modal>
</template>

<script>
export default {

  ...

  methods: {
    beforeClose (e) {
      console.log(e) // undefined
      e.stop()
    }
  }
}
</script>

Thanks in advance!

`t-select` arrow misplaced when adding wrapper class

When adding a wrapper-class attribute to the t-select component, the placement of the select element's down arrow (SVG) shifts outside the bounds of the select.

My Vue code:

    <div :class="classList.field">
      <label for="register_user_type" :class="classList.label">
        {{ $t('register.user_type') }}
      </label>
      <t-select
        id="register_user_type"
        :placeholder="$t('register.user_type_placeholder')"
        :options="userTypes"
        wrapper-class=""
      ></t-select>
    </div>

The HTML output:

<div data-v-22688508="" class="">
  <select id="register_user_type" class="t-select t-select-size-default t-select-status-default block appearance-none w-full border pr-8 rounded leading-tight p-3 bg-white">
    <option value="">Select one</option>
    <option value="solo">Solo Artist</option>
    <option value="lead">Band Leader</option>
    <option value="member">Band Member</option>
    <option value="player">Session Player</option>
    <option value="dj">DJ</option>
    <option value="other">Other</option>
  </select>
  <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="fill-current h-4 w-4">
      <path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"></path>
    </svg>
  </div>
</div>

What it actually looks like:
Screenshot 2020-03-31 18 06 23

Modal not scrolling

I have a modal with this configuration.

  TModal: {
    fixedClasses: {
      overlay:
        'z-40 overflow-auto left-0 top-0 bottom-0 right-0 w-full h-full fixed bg-opacity-50 flex',
      wrapper: 'z-50 relative mx-auto my-auto max-w-lg lg:max-w-6xl',
      modal: 'bg-white shadow overflow-hidden relative',
      body: 'p-4',
      header: 'p-4  text-sm font-semibold uppercase text-gray-700',
      footer: 'p-4 text-sm font-semibold uppercase text-gray-700 flex justify-center',
      close: 'absolute right-0 top-0 m-3 text-gray-700 hover:text-gray-600',
      closeIcon: 'h-5 w-5 fill-current',
    },
    classes: {
      overlay: 'bg-black ',
      wrapper: '',
      modal: '',
      body: 'p-4',
      header: 'text-gray-700 border-b',
      footer: 'border-t ',
      close: 'text-gray-700 hover:text-gray-600',
      closeIcon: '',
    },
    variants: {
      danger: {
        overlay: 'bg-red-500',
        header: 'border-red-100 text-red-700 border-b',
        footer: 'border-red-100 bg-red-100 border-t  ',
        close: 'text-red-700 hover:text-red-600',
      },
      clean: {
        modal: 'rounded shadow-lg',
        footer: 'bg-gray-100 ',
        body: 'p-4 text-sm text-gray-700',
        close:
          'bg-blue-100 p-1 flex items-center justify-center leading-normal rounded-full text-blue-80 hover:bg-blue-200',
      },
    },

When the modal pops up, it is scrollable on desktop or in the chrome emulator. However, the modal is not scrollable on an actual mobile phone. The page is shorter than the mobile phone screen but the modal gets longer than that. I checked the body that and the overflow-hidden gets added to there. So it is not like the body is preventing the modal from scrolling. I also tried adding overflow-y-scroll to different parts but no luck.

Thanks in advance.

How i can add selected attribute to t-select component?

Hi, someone can help me, i need add selected attribute to but i know not, this is my code:
Thanks advance!!
<t-select id="genero" v-model="genero" name="genero" :options="[ { key: 'H', description: 'Hombre' }, { key: 'M', description: 'Mujer' }, ]" value-attribute="key" text-attribute="description" base-class="block appearance-none w-full border-2 border-blue-300 pr-8 rounded-lg leading-tight bg-blue-100" required />
I try with this code without success:
:options="[ { key: 'H', description: 'Hombre', **selected: true** }, { key: 'M', description: 'Mujer' }, ]"

Modal not included in default.js

Hi
Thanks for the great project, it is a pleasure to work with.

default.js does not export TModal, I know I can copy the defaults from TModal.js, however I would like to 'inherit' the classes.

Thanks
CoffeeKing68

Benefit of this package?

It looks to me, like you're reinventing another Bootstrap/Bulma, etc. I think many people would choose tailwind just for simplicity of class utilities. Could you share your thoughts, when you created this project?

Dropdown arrow icon colour

Is it possible to change the colour of the arrow icon? I can't seem to find a way to do this? For example if I set the button to grey the arrow becomes hardly visible.

Vanilla components losing class on Nuxt

New components (Date picker, Toggle, etc) works just fine but older ones works only partial, all HTML and JS works, but it does not have any classes.

1 - Plugin and Import
image
image

2 - Using new components
image
image
image

3 - using "older" components
image
image
image


On the Props of new components default calsses are setted, but on old one it's not
vue-tailwind/src/components/TToggle.ts
image

vue-tailwind/src/components/TCard.ts /
image

Nuxt Component support

Nuxt Components automatically allow all components in an app to use other components without importing themβ€”the source files are scanned, and used components are automatically imported. This allows for tree shaking without manually importing each component. A simple starting point for this library is creating the file nuxt.js in the root directory:

import { join } from 'path'

export default function () {
  this.nuxt.hook('components:dirs', (dirs) => {
    // Add ./components dir to the list
    dirs.push({ path: join(__dirname, 'src/components') }, { path: join(__dirname, 'src/inputs') });
  });
}

Then, users of the library can opt-into it by adding vue-tailwind in Nuxt's buildModules config. Some work will need to be done for adding configuration.

Usage with prefix classes?

My tailwind setup involves prefixing all tailwind classes with 'tw-'. How exactly can I command this package to adopt the pattern?

Multiple radio groups on the same page have duplicate ids

When you have multiple options groups on the same page, they end up with duplicate ids. This means clicking the first item on the last group on the page with focus your cursor/select the first item of the first group on the page.

I'll PR a fix when I have time.

Using custom setter for computed properties fires an extra trigger

Hi,

I'm binding a v-model to my vuex store using v-model and custom getter and setter. I noticed that if I use a custom setter with a t-element it fires two times. First when there is an update, then after the update.

reproduction link (without vuex)> https://codesandbox.io/s/sleepy-ritchie-r59ej?file=/src/CustomComputed.vue

There is no consequences with my data, but I want to avoid useless updates because it creates unwanted API calls.

[Feature] Navigation drawer

So for the new issue, I'm working on a navigation drawer, is that something you'd be interested in?

Here's some screenshots of what I have up to now;

Left:

Right:

Bottom

Top

Fullscreen

Props:

  • position left/right/bottom/top
  • fullscreen bool
  • header bool (visible header)

Events:

  • show
  • dismissed

Slots:

  • header-content
  • activator (can be anything)

Example usage

<drawer
	fullscreen
	@dismiss="dismiss"
>
	<t-button slot="activator"
		slot-scope="scope"
		@click="scope.toggle"
		size="sm"
		class="ml-2"
	>
		Show Notifications.
	</t-button>
	<template slot="content">
		<ul class="mt-2 text-sm text-gray-700 h-full">
			<li v-for="alert in alerts"
				class="pl-6 py-2 flex border-b"
				:key="alert.name"
			>
				<span>
					<i class="mdi mr-3 text-lg" :class="alert.icon"></i>
				</span>
				<div class="flex flex-col">
					<span v-text="alert.name"></span>
					<span
						v-text="alert.date"
						class="text-xs text-gray-500"
					></span>
				</div>
			</li>
		</ul>
	</template>
</drawer>

Possible bug report - Nuxt.js

Hello,
I'm using this library in a normal Vue.js project and everything is great there.
However, I started to use this in a Nuxt.js project and during the development I'm getting several warnings like this:

[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.

I did some research on it and this is caused usually when the Virtual DOM and the DOM rendered in the server side is different, during development. There's a comparisson between the two, and if they're different from each other, it bails hydration, by possibly discarding the DOM rendered in the server side and render again only using the Virtual DOM in the client side.

The thing is, I did some debugging in the source code and I found the element rendered in the server side and the Virtual DOM node rendered in the client side, and to me they are both look pretty much the same, disregarding all the properties since they are different elements.

Also the number of VNode and the NodeList numbers are the same.

I put a breakpoint in line 6374 of vue.runtime.esm.js as you can see in the screenshot below:

image

If you go back to the devtools console, you can see the elm and the vnode that they are going to be compared:

image

image

image

In my case the component that is causing this warnings is the t-input, but I feel like any component can cause this error.

I try to comment all the JS (requests server/client side) and still is causing the warning, even if the input is empty.

I also try to use the <client-only> tag and the ssr: false in the plugins, like below, but they both didn't work:

plugins: [    
    { src: "~/plugins/vue-tailwind", ssr: false }
]

This is the warning message I'm getting in the console, with the Vue warn:

image

As you can see the number of NodeList (server side) is the same as the number of VNode (client side).

If you know what I'm doing wrong, or if you have any kind of information regarding this warnings, or if you need more information, please let me know. Any help is appreciated!

Thank you.

Rich select does not show selected item on route change

Using TRichSelect on two different pages which vue router load/render them. On first load it works as expected but when navigating to the other page or get back to the current page selected item text is not showing however when I open the select the option is highlighted.
Please check screen shots showing selectedOption is not set when it has localValue

Screen Shot 2020-08-20 at 12 11 24 pm
Screen Shot 2020-08-20 at 12 10 51 pm

Tabs/Collapse component

Hello,

I'm using vue-tailwind for a new e-commerce projet and I would like to help you implement the tabs and also collapse component. Do you have a trello to see upcoming and current progress work ?
I'm available here : [email protected]

PS: Nice work for this projet

Usage in Laravel throws Module not found: Can't resolve 'vue-tailwind'

Hello, I'm trying to use your package in a Laravel application, but when I try to build the javascript it throws: Module not found: Error: Can't resolve 'vue-tailwind'

If I change the import from:
import VueTailwind from 'vue-tailwind
to:
import VueTailwind from 'vue-tailwind
it starts working.

[bug] Custom Modal theme not working with dist files

src/main.js

import Vue from 'vue';
import app from '@core/app';
import router from '@plugins/router/router';
import store from '@plugins/state/';
import './js/registerServiceWorker';
import './assets/sass/tailwind.scss';
import './js/plugins/vuetailwind'
Vue.config.productionTip = true;

new Vue({
	store,
	router,
	render: h => h(app),
}).$mount('#app');

js/plugins/vuetailwind

import Vue from 'vue';
import VueTailwind from 'vue-tailwind';
import TModal from './modal';

Vue.use(VueTailwind, {
	theme: {
		TModal
	}
});

modal.js

const TModal = {
	baseClass: 'z-40 overflow-auto left-0 top-0 bottom-0 right-0 w-full h-full fixed text-primary',
	overlayClass: 'z-40 overflow-auto left-0 top-0 bottom-0 right-0 w-full h-full fixed bg-black opacity-75',
	containerClass: 'z-50 relative p-3 mx-auto my-0 max-w-full',
	closeIconClass: 'fill-current h-6 w-6 absolute right-0 top-0 m-6',
	wrapperClass: 'bg-primary rounded shadow-lg border flex flex-col overflow-hidden',
	headerClass: 'bg-secondary px-6 py-3 text-xl border-b',
	bodyClass: 'text-primary p-6 flex-grow',
	footerClass: 'bg-secondary px-6 py-3 border-t',
};

export default TModal

It doesn't work, but when I change it from :

import VueTailwind from 'vue-tailwind'

to:

import VueTailwind from 'vue-tailwind/src/index'

My custom theme works, I'm not sure if this is intentional or not because of the docs doesn't include the /src/index part

https://vue-tailwind.com/#install-and-use

Radio Group Component has issues with array of objects

My radio group element is declared like this:

<t-radio-group
  :options="[
    { value: 1, text: 'ABC' },
    { value: 2, text: 'XYZ' }
  ]"
  v-model="modelVal"
></t-radio-group>

The modelVal is set to 1 in the data part. The expected behavior is to change the modelVal in the data to the value of the option. However, it doesn't change it and also, it doesn't uncheck the previously checked radio. So you end up with both radios checked and false modelVal...

This is how it renders

<div class="px-4 py-2 flex flex-col">
   <label for="1" class="">
      <span class=""><input value="1" id="1" type="radio" checked="checked" class="form-radio"></span>
      <span class="ml-2 text-gray-700 text-sm">ABC</span>
   </label>
   <label for="2" class="">
      <span class=""><input value="2" id="2" type="radio" class="form-radio"></span>
      <span class="ml-2 text-gray-700 text-sm">XYZ</span>
   </label>
</div>

Cannot find module '@/types/CssClass'

ERROR in D:/Code/Exenzo/jobboost.io-app/node_modules/vue-tailwind/dist/components/TDatepicker.d.ts(1,43)
Cannot find module '@/utils/dates'
ERROR in D:/Code/Exenzo/jobboost.io-app/node_modules/vue-tailwind/dist/components/TPagination.d.ts(2,22):
Cannot find module '@/types/CssClass'.

And many others, it seems that the internal aliases are not working.

DropDown: hide event doesn't work.

Hi!

The hide event isn't working on DropDown. I've resolved it using the blur event because i'm using the click trigger, but the hide event doesn't work anyway.

Example:

<template>
  <t-dropdown
    trigger="click"
    @click="onClick"
    @hide="onHide"
  >
     ...
  </t-dropdown>
</template>

<script>

export default {
  methods: {
    onClick() {
       console.log('on click') // It works!
    },
    onHide() {
       console.log('on hide') // It doesn't work...
    }
  }
}

</script>

Settings not working with storybook

I'm working with a design system and writing a components library which is running on storybook.

I've installed the plugin like this,

import Vue from 'vue'
import VueTailwind from 'vue-tailwind'

import { settings } from './settings'

Vue.use(VueTailwind, settings)

When I run the app on the development server, the components get styled as expected.
But when I use those components inside a story, the styles I've configured in settings.js are missing.

I checked the browser's dev tools and found that none of the configured classes gets assigned to the HTML elements.
Although, it works fine if I explicitly assign those classes in the story.

for eg.
I have a .button class for the TButton component. I've added it to the fixedClasses of the TButton component in settings.js.

The class gets assigned to the component if I serve the project on the development server but is missing if I use the same component in a story.

It only works If I pass in the .button class explicitly in the story's args.

This is what my story looks like:

import { TButton } from 'vue-tailwind'

export default {
  title: 'Example/Button',
  component: TButton,
  argTypes: {
    variant: {
      control: { type: 'select', options: ['', 'primary'] }
    },
    onClick: { action: 'click' }
  }
}

const Template = (_args, { argTypes }) => ({
  props: Object.keys(argTypes),
  components: { TButton },
  template: `
    <t-button @click="onClick" v-bind="$props">
      Button
    </t-button>`
})

export const Default = Template.bind({})
Default.args = {
  class: 'button'
}

export const Primary = Template.bind({})
Primary.args = {
  variant: 'primary'
}

Settings for TButton:

export const TButton = {
  fixedClasses: 'button',
  variants: {
    primary: 'is-primary'
  }
}

It works in the Default story because I'm explicitly passing the button class but not in the Primary story.

although it doesn't make sense but I even tried extending the component like this,

<template>
  <t-button v-bind="$props" v-on="$listeners">
    <slot />
  </t-button>
</template>

<script>
import { TButton } from 'vue-tailwind'

export default {
  name: 'AppButton',
  components: { TButton },
  extends: TButton
}
</script>

It still doesn't work

Thoughts on integrating with `vue-formulate`

I've been looking into simplifying all of my Vue+forms mess by using vue-formulate to handle everything from data-binding to validation. The only issue I have with the library is that building custom controls from scratch every time make me feel like I'm wasting my life.

Have you considered turning your components in a UI-only version of them that integrates with the mentioned package or something similar? You'd save some time writing most of that logic and I think everything would be easier to extend/compose.

Using the current state within a custom variant

Thank you very much for this project. I am currently trying to understand how to customise a component - for example TButton.

Currently, setting disabled to true does not change the appearance of TButton. Is this a bug? If it is not a bug how would I configure a custom button variant and - for example - make it grey in case it is disabled?

Best practice to open a modal from within a modal?

Is this the best method to open another modal from within a modal? First close and then open?

There is a bit of flash as this happens and I wonder if there is a better way to approach this?

Thanks

<button
  class="underline text-sblue-500"
  @click="$refs.modalLogin.hide(); $modal.show('modal-forgotten');"
 >Forgotten Password?</button>```

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.