mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-10 07:52:23 +03:00
WIP
Updates the root $el to be a focusable button instead of a div. Allows for separating focusing of the component from opening the dropdown
This commit is contained in:
+46
-7
@@ -1,19 +1,42 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<sandbox hide-help v-slot="config">
|
||||
<v-select v-bind="config"/>
|
||||
</sandbox>
|
||||
</div>
|
||||
<!-- <div id="app">-->
|
||||
<!-- <sandbox hide-help v-slot="config">-->
|
||||
<!-- <v-select v-bind="config"/>-->
|
||||
<!-- </sandbox>-->
|
||||
<!-- </div>-->
|
||||
<form>
|
||||
<label for="name">Name</label>
|
||||
<input type="text" id="name" autofocus>
|
||||
|
||||
<label for="email">eMail</label>
|
||||
<input type="email" id="email">
|
||||
|
||||
<label for="emails">eMail</label>
|
||||
<select id="emails">
|
||||
<option value="one">one</option>
|
||||
<option value="two">two</option>
|
||||
</select>
|
||||
|
||||
<label for="country">Country</label>
|
||||
<v-select :options="countries" id="country" :filterable="false" />
|
||||
|
||||
<label for="hello">Hello</label>
|
||||
<input type="text" id="hello">
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import vSelect from '../src/components/Select';
|
||||
import Sandbox from '../docs/.vuepress/components/Sandbox';
|
||||
// import countries from '../docs/.vuepress/data/countryCodes';
|
||||
// import books from '../docs/.vuepress/data/books';
|
||||
import countries from '../docs/.vuepress/data/countryCodes';
|
||||
import books from '../docs/.vuepress/data/books';
|
||||
|
||||
export default {
|
||||
components: {Sandbox, vSelect},
|
||||
computed: {
|
||||
countries: () => countries,
|
||||
books: () => books,
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -36,4 +59,20 @@ export default {
|
||||
padding-top: 1em;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
form {
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
padding-top: 5rem;
|
||||
}
|
||||
|
||||
label {
|
||||
width:100%;
|
||||
display: block;
|
||||
margin-top:1rem;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div :dir="dir" class="v-select" :class="stateClasses">
|
||||
<div ref="toggle" @mousedown.prevent="toggleDropdown" class="vs__dropdown-toggle">
|
||||
<button :tabindex="tabindex" type="button" @keydown="keypressWhileToggleIsFocused" ref="toggle" @mousedown.prevent="maybeToggleDropdown" class="v-select vs__dropdown-toggle" :dir="dir" :class="stateClasses">
|
||||
|
||||
<div class="vs__selected-options" ref="selectedOptions">
|
||||
<slot v-for="option in selectedValue"
|
||||
@@ -49,8 +48,6 @@
|
||||
<div class="vs__spinner" v-show="mutableLoading">Loading...</div>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<transition :name="transition">
|
||||
<ul ref="dropdownMenu" v-if="dropdownOpen" class="vs__dropdown-menu" role="listbox" @mousedown.prevent="onMousedown" @mouseup="onMouseUp">
|
||||
<li
|
||||
@@ -71,7 +68,8 @@
|
||||
</li>
|
||||
</ul>
|
||||
</transition>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
</template>
|
||||
|
||||
<script type="text/babel">
|
||||
@@ -508,6 +506,7 @@
|
||||
search: '',
|
||||
open: false,
|
||||
isComposing: false,
|
||||
shouldDisplaySearch: true,
|
||||
pushedTags: [],
|
||||
_value: [] // Internal value managed by Vue Select if no `value` prop is passed
|
||||
}
|
||||
@@ -666,7 +665,7 @@
|
||||
* @param {Event} e
|
||||
* @return {void}
|
||||
*/
|
||||
toggleDropdown ({target}) {
|
||||
maybeToggleDropdown ({target}) {
|
||||
// don't react to click on deselect/clear buttons,
|
||||
// they dropdown state will be set in their click handlers
|
||||
const ignoredButtons = [
|
||||
@@ -678,7 +677,11 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.open) {
|
||||
this.toggleDropdown(true);
|
||||
},
|
||||
|
||||
toggleDropdown(toggle = true) {
|
||||
if (this.open || ! toggle) {
|
||||
this.searchEl.blur();
|
||||
} else if (!this.disabled) {
|
||||
this.open = true;
|
||||
@@ -829,7 +832,8 @@
|
||||
if (this.clearSearchOnBlur) {
|
||||
this.search = ''
|
||||
}
|
||||
this.closeSearchOptions()
|
||||
this.closeSearchOptions();
|
||||
this.$refs.toggle.focus();
|
||||
return
|
||||
}
|
||||
// Fixed bug where no-options message could not be closed
|
||||
@@ -907,6 +911,31 @@
|
||||
if (typeof handlers[e.keyCode] === 'function') {
|
||||
return handlers[e.keyCode](e);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
keypressWhileToggleIsFocused(e) {
|
||||
// if( e.target === this.searchEl ) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if( 'Tab' === e.code ) {
|
||||
// e.preventDefault();
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if( ['Space', 'Return'].includes(e.code) ) {
|
||||
// return this.toggleDropdown();
|
||||
// }
|
||||
//
|
||||
// if( ['ShiftLeft', 'ShiftRight'].includes(e.code)) {
|
||||
// e.preventDefault();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// return this.toggleDropdown()
|
||||
}
|
||||
},
|
||||
|
||||
@@ -970,7 +999,7 @@
|
||||
attributes: {
|
||||
'disabled': this.disabled,
|
||||
'placeholder': this.searchPlaceholder,
|
||||
'tabindex': this.tabindex,
|
||||
'tabindex': '-1',
|
||||
'readonly': !this.searchable,
|
||||
'id': this.inputId,
|
||||
'aria-expanded': this.dropdownOpen,
|
||||
@@ -1106,6 +1135,10 @@
|
||||
*/
|
||||
showClearButton() {
|
||||
return !this.multiple && this.clearable && !this.open && !this.isValueEmpty
|
||||
},
|
||||
|
||||
buttonIsFocused() {
|
||||
return this.$el === this.$root.$el.querySelector(':focus');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ $border-radius: $vs-border-radius;
|
||||
.vs__dropdown-toggle {
|
||||
appearance: none;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 0 0 4px 0;
|
||||
background: none;
|
||||
border: $border-width $border-style $border-color;
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
import { selectWithProps } from "../helpers";
|
||||
import { mountDefault, selectWithProps } from '../helpers';
|
||||
import OpenIndicator from "../../src/components/OpenIndicator";
|
||||
|
||||
describe("Toggling Dropdown", () => {
|
||||
fdescribe('focusing on the button wrapper', () => {
|
||||
test('when the search is focused buttonIsFocused is false', () => {
|
||||
const Select = mountDefault();
|
||||
Select.vm.$refs.search.focus();
|
||||
expect(Select.vm.buttonIsFocused).toBeFalsy();
|
||||
})
|
||||
|
||||
test('when the button is focused, buttonIsFocused is true', async () => {
|
||||
const Select = mountDefault();
|
||||
Select.vm.$refs.toggle.focus();
|
||||
await Select.vm.$nextTick();
|
||||
expect(Select.vm.buttonIsFocused).toBeTruthy();
|
||||
})
|
||||
});
|
||||
|
||||
it("should not open the dropdown when the el is clicked but the component is disabled", () => {
|
||||
const Select = selectWithProps({ disabled: true });
|
||||
Select.vm.toggleDropdown({ target: Select.vm.$refs.search });
|
||||
Select.vm.maybeToggleDropdown({ target: Select.vm.$refs.search });
|
||||
expect(Select.vm.open).toEqual(false);
|
||||
});
|
||||
|
||||
@@ -14,7 +29,7 @@ describe("Toggling Dropdown", () => {
|
||||
options: [{ label: "one" }]
|
||||
});
|
||||
|
||||
Select.vm.toggleDropdown({ target: Select.vm.$refs.search });
|
||||
Select.vm.maybeToggleDropdown({ target: Select.vm.$refs.search });
|
||||
expect(Select.vm.open).toEqual(true);
|
||||
});
|
||||
|
||||
@@ -26,7 +41,7 @@ describe("Toggling Dropdown", () => {
|
||||
|
||||
const selectedTag = Select.find(".vs__selected").element;
|
||||
|
||||
Select.vm.toggleDropdown({ target: selectedTag });
|
||||
Select.vm.maybeToggleDropdown({ target: selectedTag });
|
||||
expect(Select.vm.open).toEqual(true);
|
||||
});
|
||||
|
||||
@@ -35,7 +50,7 @@ describe("Toggling Dropdown", () => {
|
||||
const spy = jest.spyOn(Select.vm.$refs.search, "blur");
|
||||
|
||||
Select.vm.open = true;
|
||||
Select.vm.toggleDropdown({ target: Select.vm.$el });
|
||||
Select.vm.maybeToggleDropdown({ target: Select.vm.$el });
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
@@ -134,7 +149,7 @@ describe("Toggling Dropdown", () => {
|
||||
noDrop: true,
|
||||
});
|
||||
|
||||
Select.vm.toggleDropdown({ target: Select.vm.$refs.search });
|
||||
Select.vm.maybeToggleDropdown({ target: Select.vm.$refs.search });
|
||||
expect(Select.vm.open).toEqual(true);
|
||||
expect(Select.contains('.vs__dropdown-menu')).toBeFalsy();
|
||||
expect(Select.vm.stateClasses['vs--open']).toBeFalsy();
|
||||
|
||||
Reference in New Issue
Block a user