Skip to content

Commit 947a961

Browse files
committed
2.0.0 release
1 parent 1a0cf18 commit 947a961

File tree

11 files changed

+765
-33
lines changed

11 files changed

+765
-33
lines changed

.github/stale.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Number of days of inactivity before an issue becomes stale
2-
daysUntilStale: 180
2+
daysUntilStale: 75
33
# Number of days of inactivity before a stale issue is closed
4-
daysUntilClose: 3
4+
daysUntilClose: 15
55
# Issues with these labels will never be considered stale
66
exemptLabels:
77
- pinned

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## v2.0.0
2+
3+
> `2021-06-20`
4+
5+
### 🎉 Feature
6+
- **BREAKING**: Completely rewritten `<template>` and `default.css`.
7+
- Caret is now always displayed when `caret: true` regardless if the multiselect has selected option(s).
8+
- Added `canDeselect` and `classes` prop.
9+
- Added `;` and `,` options to `addTagOn` prop.
10+
111
## v1.5.0
212

313
> `2021-05-17`

README.md

Lines changed: 155 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<img alt="npm" src="https://img.shields.io/npm/v/@vueform/multiselect">
2121
</a>
2222

23-
<h1>Vue 3 Multiselect</h1>
23+
<h1>Vue 3 Multiselect with Tailwind support</h1>
2424

2525
<a href="https://vueform.com?ref=github" target="_blank">
2626
<br>
@@ -46,12 +46,13 @@
4646

4747
## Other libraries
4848

49-
* [@vueform/slider](https://github.com/vueform/slider) - Vue 3 slider component with multihandles, tooltips merging and formatting.
49+
* [@vueform/slider](https://github.com/vueform/slider) - Vue 3 slider component with Tailwind support.
5050
* [@vueform/toggle](https://github.com/vueform/toggle) - Vue 3 toggle component with labels, custom slots and styling options.
5151

5252
## Multiselect features
5353

5454
* Vue 2 & 3 support
55+
* Tailwind & utility class support
5556
* No dependencies
5657
* 100% coverage
5758
* TypeScript support
@@ -157,6 +158,155 @@ After that make sure to change the imported module to Vue 2 version of Multisele
157158
import Multiselect from '@vueform/multiselect/dist/multiselect.vue2.js'
158159
```
159160

161+
## Styling with CSS vars
162+
163+
The following CSS variables can be used to customize multiselect when using `default.css`:
164+
165+
``` css
166+
--ms-font-size: 1rem
167+
--ms-line-height: 1.375
168+
--ms-bg: #FFFFFF
169+
--ms-bg-disabled: #F3F4F6
170+
--ms-border-color: #D1D5DB
171+
--ms-border-width: 1px
172+
--ms-radius: 4px
173+
--ms-py: 0.5rem
174+
--ms-px: 0.875rem
175+
--ms-ring-width: 3px
176+
--ms-ring-color: #10B98130
177+
--ms-placeholder-color: #9CA3AF
178+
179+
--ms-tag-font-size: 0.875rem
180+
--ms-tag-line-height: 1.25rem
181+
--ms-tag-font-weight: 600
182+
--ms-tag-bg: #10B981
183+
--ms-tag-bg-disabled: #9CA3AF
184+
--ms-tag-color: #FFFFFF
185+
--ms-tag-color-disabled: #FFFFFF
186+
--ms-tag-radius: 4px
187+
--ms-tag-py: 0.125rem
188+
--ms-tag-px: 0.5rem
189+
--ms-tag-my: 0.25rem
190+
--ms-tag-mx: 0.25rem
191+
192+
--ms-tag-remove-radius: 4px
193+
--ms-tag-remove-py: 0.25rem
194+
--ms-tag-remove-px: 0.25rem
195+
--ms-tag-remove-my: 0rem
196+
--ms-tag-remove-mx: 0.125rem
197+
198+
--ms-dropdown-bg: #FFFFFF
199+
--ms-dropdown-border-color: #D1D5DB
200+
--ms-dropdown-border-width: 1px
201+
--ms-dropdown-radius: 4px
202+
203+
--ms-option-font-size: 1rem
204+
--ms-option-line-height: 1.375
205+
--ms-option-bg-pointed: #FFFFFF
206+
--ms-option-bg-selected: #10B981
207+
--ms-option-bg-disabled: #FFFFFF
208+
--ms-option-bg-selected-pointed: #26C08E
209+
--ms-option-bg-selected-disabled: #FFFFFF
210+
--ms-option-color-pointed: #1F2937
211+
--ms-option-color-selected: #FFFFFF
212+
--ms-option-color-disabled: #D1D5DB
213+
--ms-option-color-selected-pointed: #FFFFFF
214+
--ms-option-color-selected-disabled: #D1FAE5
215+
--ms-option-py: 0.5rem
216+
--ms-option-px: 0.75rem
217+
218+
--ms-empty-color: #4B5563
219+
```
220+
221+
Override them globally:
222+
223+
``` css
224+
:root {
225+
--ms-tag-bg: #059669;
226+
--ms-tag-color: #D1FAE5;
227+
--ms-tag-radius: 9999px;
228+
--ms-tag-font-weight: 400;
229+
}
230+
```
231+
232+
Or on an instance level:
233+
234+
``` vue
235+
<Multiselect
236+
v-model="value"
237+
:options="options"
238+
class="multiselect-green"
239+
/>
240+
241+
<Multiselect
242+
v-model="value"
243+
:options="options"
244+
class="multiselect-blue"
245+
/>
246+
```
247+
248+
``` css
249+
.multiselect-green {
250+
--ms-tag-bg: #D1FAE5;
251+
--ms-tag-color: #059669;
252+
}
253+
254+
.multiselect-blue {
255+
--ms-tag-bg: #DBEAFE;
256+
--ms-tag-color: #2563EB;
257+
}
258+
```
259+
260+
## Styling with Tailwind CSS
261+
262+
The `Multiselect` component accepts a `classes` property which allows to override default class names. When using utility classes you don't need to import `default.css`. Here's a default styling for Tailwind CSS:
263+
264+
``` vue
265+
<Multiselect v-model="value" :options="options" :classes="{
266+
container: 'relative mx-auto w-full flex items-center justify-end box-border cursor-pointer border border-gray-300 rounded bg-white text-base leading-snug outline-none',
267+
containerDisabled: 'cursor-default bg-gray-100',
268+
containerOpen: 'rounded-b-none',
269+
containerOpenTop: 'rounded-t-none',
270+
containerActive: 'ring ring-green-500 ring-opacity-30',
271+
singleLabel: 'flex items-center h-full absolute left-0 top-0 pointer-events-none bg-transparent leading-snug pl-3.5',
272+
multipleLabel: 'flex items-center h-full absolute left-0 top-0 pointer-events-none bg-transparent leading-snug pl-3.5',
273+
search: 'w-full absolute inset-0 outline-none appearance-none box-border border-0 text-base font-sans bg-white rounded pl-3.5',
274+
tags: 'flex-grow flex-shrink flex flex-wrap mt-1 pl-2',
275+
tag: 'bg-green-500 text-white text-sm font-semibold py-0.5 pl-2 rounded mr-1 mb-1 flex items-center whitespace-nowrap',
276+
tagDisabled: 'pr-2 !bg-gray-400 text-white',
277+
tagRemove: 'flex items-center justify-center p-1 mx-0.5 rounded-sm hover:bg-black hover:bg-opacity-10 group',
278+
tagRemoveIcon: 'bg-multiselect-remove bg-center bg-no-repeat opacity-30 inline-block w-3 h-3 group-hover:opacity-60',
279+
tagsSearch: 'h-full border-0 outline-none appearance-none p-0 text-base font-sans mx-1 mb-1 box-border flex-grow flex-shrink',
280+
placeholder: 'flex items-center h-full absolute left-0 top-0 pointer-events-none bg-transparent leading-snug pl-3.5 text-gray-400',
281+
caret: 'bg-multiselect-caret bg-center bg-no-repeat w-2.5 h-4 py-px box-content mr-3.5 relative z-10 opacity-40 flex-shrink-0 flex-grow-0 transition-transform transform',
282+
caretOpen: 'rotate-180',
283+
clear: 'pr-3.5 relative z-10 opacity-40 transition duration-300 flex-shrink-0 flex-grow-0 flex hover:opacity-80',
284+
clearIcon: 'bg-multiselect-remove bg-center bg-no-repeat w-2.5 h-4 py-px box-content inline-block',
285+
spinner: 'bg-multiselect-spinner bg-center bg-no-repeat w-4 h-4 z-10 mr-3.5 animate-spin flex-shrink-0 flex-grow-0',
286+
dropdown: 'absolute -left-px -right-px bottom-0 transform translate-y-full border border-gray-300 -mt-px overflow-y-scroll z-50 bg-white flex flex-col rounded-b',
287+
dropdownTop: '-translate-y-full top-px bottom-auto flex-col-reverse rounded-b-none rounded-t',
288+
options: 'flex flex-col p-0 m-0 list-none',
289+
optionsTop: 'flex-col-reverse',
290+
option: 'flex items-center justify-start box-border text-left cursor-pointer text-base leading-snug py-2 px-3',
291+
optionPointed: 'text-gray-800 bg-gray-100',
292+
optionSelected: 'text-white bg-green-500',
293+
optionDisabled: 'text-gray-300 cursor-not-allowed',
294+
optionSelectedPointed: 'text-white bg-green-500 opacity-90',
295+
optionSelectedDisabled: 'text-green-100 bg-green-500 bg-opacity-50 cursor-not-allowed',
296+
noOptions: 'py-2 px-3 text-gray-600 bg-white',
297+
noResults: 'py-2 px-3 text-gray-600 bg-white',
298+
fakeInput: 'bg-transparent absolute left-0 right-0 -bottom-px w-full h-px border-0 p-0 appearance-none outline-none text-transparent',
299+
spacer: 'h-9 py-px box-content',
300+
}" />
301+
```
302+
303+
Certain classes has different states which are merged to the base class when the state is active. For exmple `dropdown` will be merged with `dropdownTop` when `open-direction: 'top'` resulting in the following classes:
304+
```absolute -left-px -right-px bottom-0 transform translate-y-full border border-gray-300 -mt-px overflow-y-scroll z-50 bg-white flex flex-col rounded-b -translate-y-full top-px bottom-auto flex-col-reverse rounded-b-none rounded-t```
305+
306+
The same is true for `container`, `tag`, `options` and `option` classes.
307+
308+
In case you need to override the same type of utility you might use [@neojp/tailwind-important-variant](https://www.npmjs.com/package/@neojp/tailwindcss-important-variant) and use eg. `bg-green-500!`.
309+
160310
## Support
161311

162312
Join our [Discord channel](https://discord.gg/WhX2nG6GTQ) or [open an issue](https://github.com/vueform/multiselect/issues).
@@ -180,10 +330,11 @@ Join our [Discord channel](https://discord.gg/WhX2nG6GTQ) or [open an issue](htt
180330
| **loading** | `boolean` | `false` | Whether a loading spinner should be shown. |
181331
| **id** | `string` | `'multiselect'` | The `id` of the multiselect container DOM. |
182332
| **caret** | `boolean` | `true` | Whether should display the caret symbol on the right. |
183-
| **maxHeight** | `number` | `160` | The maximum height of options list (px). |
333+
| **maxHeight** | `string` | `10rem` | The maximum height of options list. |
184334
| **noOptionsText** | `string` | `'The list is empty'` | The text that should be displayed when options list is empty. |
185335
| **noResultsText** | `string` | `'No results found'` | The text that should be displayed when there are no search results. |
186336
| **openDirection** | `string` | `bottom` | Whether the option list should be displayed above or below the multiselect. Possible values: `top\|bottom` |
337+
| **classes** | `object` | | An object of class names that gets merged with the default values. Default: `{`<br>&nbsp;&nbsp;`container: 'multiselect',`<br>&nbsp;&nbsp;`containerDisabled: 'is-disabled',`<br>&nbsp;&nbsp;`containerOpen: 'is-open',`<br>&nbsp;&nbsp;`containerOpenTop: 'is-open-top',`<br>&nbsp;&nbsp;`containerActive: 'is-active',`<br>&nbsp;&nbsp;`singleLabel: 'multiselect-single-label',`<br>&nbsp;&nbsp;`multipleLabel: 'multiselect-multiple-label',`<br>&nbsp;&nbsp;`search: 'multiselect-search',`<br>&nbsp;&nbsp;`tags: 'multiselect-tags',`<br>&nbsp;&nbsp;`tag: 'multiselect-tag',`<br>&nbsp;&nbsp;`tagDisabled: 'is-disabled',`<br>&nbsp;&nbsp;`tagRemove: 'multiselect-tag-remove',`<br>&nbsp;&nbsp;`tagRemoveIcon: 'multiselect-tag-remove-icon',`<br>&nbsp;&nbsp;`tagsSearch: 'multiselect-tags-search',`<br>&nbsp;&nbsp;`placeholder: 'multiselect-placeholder',`<br>&nbsp;&nbsp;`caret: 'multiselect-caret',`<br>&nbsp;&nbsp;`caretOpen: 'is-open',`<br>&nbsp;&nbsp;`clear: 'multiselect-clear',`<br>&nbsp;&nbsp;`clearIcon: 'multiselect-clear-icon',`<br>&nbsp;&nbsp;`spinner: 'multiselect-spinner',`<br>&nbsp;&nbsp;`dropdown: 'multiselect-dropdown',`<br>&nbsp;&nbsp;`dropdownTop: 'is-top',`<br>&nbsp;&nbsp;`options: 'multiselect-options',`<br>&nbsp;&nbsp;`optionsTop: 'is-top',`<br>&nbsp;&nbsp;`option: 'multiselect-option',`<br>&nbsp;&nbsp;`optionPointed: 'is-pointed',`<br>&nbsp;&nbsp;`optionSelected: 'is-selected',`<br>&nbsp;&nbsp;`optionDisabled: 'is-disabled',`<br>&nbsp;&nbsp;`optionSelectedPointed: 'is-selected is-pointed',`<br>&nbsp;&nbsp;`optionSelectedDisabled: 'is-selected is-disabled',`<br>&nbsp;&nbsp;`noOptions: 'multiselect-no-options',`<br>&nbsp;&nbsp;`noResults: 'multiselect-no-results',`<br>&nbsp;&nbsp;`fakeInput: 'multiselect-fake-input',`<br>&nbsp;&nbsp;`spacer: 'multiselect-spacer'`<br>`}` |
187338

188339
### Advanced Props
189340

@@ -199,7 +350,7 @@ Join our [Discord channel](https://discord.gg/WhX2nG6GTQ) or [open an issue](htt
199350
| **resolveOnLoad** | `boolean` | `true` | Whether async options should be loaded initially (with an empty query). This should be `true` if you are planning to load non-object value(s) initially while using async options (to fetch matching objects for values). |
200351
| **appendNewTag** | `boolean` | `true` | Whether it should append new tag automatically to option list when using `tags` mode with `createTag`. If set to `false` you need to take care of appending a new tag to the provided `:options` list upon `@tag` event. |
201352
| **createTag** | `boolean` | `false` | Whether it should allow creating new tag based on search query when using `tags` mode. |
202-
| **addTagOn** | `array` | `['enter']` | The list of keys that creates a new tag while typing in the search field when having `createTag` enabled. Possible values: `enter\|space`. |
353+
| **addTagOn** | `array` | `['enter']` | The list of keys that creates a new tag while typing in the search field when having `createTag` enabled. Possible values: `enter\|space\|;\|,`. |
203354
| **hideSelected** | `boolean` | `true` | Whether selected options should be excluded from the option list when using `multiple` or `tags` mode. |
204355
| **showOptions** | `boolean` | `true` | Whether option list should be displayed. Can be used to create free-typed tags. |
205356
| **object** | `boolean` | `false` | Whether the value should be stored as an object.<br>If **false**:<br>`value: ['js','jsx','ts']`<br>If **true**:<br> `value: [`<br>&nbsp;&nbsp;`{value:'js',label:'Javascript'},`<br>&nbsp;&nbsp;`{value:'jsx',label:'JSX'},`<br>&nbsp;&nbsp;`{value:'ts',label:'Typescript'}`<br>`]` |

dist/multiselect.global.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/multiselect.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/multiselect.vue2.global.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/multiselect.vue2.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)