Skip to content

Commit

Permalink
fix(dropdowns): Focus dropdown item on hover (#823)
Browse files Browse the repository at this point in the history
* fix(dropdowns): Remove focusing of headers

* [dropdown] Minor tweaks

* [nav-item-dropdown] Adjustments

* [dropdown]: namespaced classes

* [dropdown.js] add onMouseEnter handler

* [dropdown] focus on hover

* Update dropdown.js

* [dropdown] mouseover event

* [nav-item-dropdown] mouseover event

* Update dropdown.js

* Update dropdown-header.vue

remove tabindex
  • Loading branch information
tmorehouse committed Aug 12, 2017
1 parent 6891e9f commit 2e863d9
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 31 deletions.
2 changes: 1 addition & 1 deletion lib/components/dropdown-header.vue
@@ -1,5 +1,5 @@
<template> <template>
<component :is="tag" tabindex="-1" class="dropdown-header"> <component :is="tag" class="dropdown-header">
<slot></slot> <slot></slot>
</component> </component>
</template> </template>
Expand Down
34 changes: 25 additions & 9 deletions lib/components/dropdown.vue
@@ -1,5 +1,5 @@
<template> <template>
<div :id="id || null" :class="['dropdown', 'btn-group', { dropup, show: visible }]"> <div :id="id || null" :class="dropdownClasses">


<b-button :class="{'dropdown-toggle': !split}" <b-button :class="{'dropdown-toggle': !split}"
ref="button" ref="button"
Expand Down Expand Up @@ -28,10 +28,11 @@
<span class="sr-only">{{toggleText}}</span> <span class="sr-only">{{toggleText}}</span>
</b-button> </b-button>


<div :class="['dropdown-menu',{'dropdown-menu-right': right, show: visible}]" <div :class="menuClasses"
ref="menu" ref="menu"
role="menu" role="menu"
:aria-labelledby="id ? (id + (split ? '__BV_toggle_' : '__BV_button_')) : null" :aria-labelledby="id ? (id + (split ? '__BV_toggle_' : '__BV_button_')) : null"
@mouseover="onMouseOver"
@keyup.esc="onEsc" @keyup.esc="onEsc"
@keydown.tab="onTab" @keydown.tab="onTab"
@keydown.up="focusNext($event,true)" @keydown.up="focusNext($event,true)"
Expand Down Expand Up @@ -67,21 +68,36 @@
type: String, type: String,
default: null default: null
} }
},
computed: {
dropdownClasses() {
return [
'b-dropdown',
'dropdown',
'btn-group',
this.dropup ? 'dropup' : '',
this.visible ? 'show' : ''
];
},
menuClasses() {
return [
'dropdown-menu',
this.right ? 'dropdown-menu-right' : '',
this.visible ? 'show' : ''
];
}
} }
}; };
</script> </script>


<style> <style>
.dropdown-item:focus:not(.active), .b-dropdown.dropdown-item:focus:not(.active),
.dropdown-item:hover:not(.active), .b-dropdown.dropdown-item:hover:not(.active) {
.dropdown-header:focus:not(.active)
.dropdown-header:hover:not(.active) {
/* @See https://github.com/twbs/bootstrap/issues/23329 */ /* @See https://github.com/twbs/bootstrap/issues/23329 */
box-shadow: inset 0px 0px 400px 110px rgba(0, 0, 0, .09); box-shadow: inset 0px 0px 400px 110px rgba(0, 0, 0, .09);
} }
.dropdown-item:active, .b-dropdown.dropdown-item:active {
.dropdown-header:active {
box-shadow: initial; box-shadow: initial;
} }
</style> </style>
41 changes: 30 additions & 11 deletions lib/components/nav-item-dropdown.vue
@@ -1,5 +1,5 @@
<template> <template>
<li :id="id || null" :class="['nav-item','dropdown', {dropup, show: visible}]"> <li :id="id || null" :class="dropdownClasses">


<a :class="['nav-link', dropdownToggle, {disabled}]" <a :class="['nav-link', dropdownToggle, {disabled}]"
href="#" href="#"
Expand All @@ -15,10 +15,11 @@
<slot name="button-content"><slot name="text"><span v-html="text"></span></slot></slot> <slot name="button-content"><slot name="text"><span v-html="text"></span></slot></slot>
</a> </a>


<div :class="['dropdown-menu',{'dropdown-menu-right': right, show: visible}]" <div :class="menuClasses"
role="menu" role="menu"
ref="menu" ref="menu"
:aria-labelledby="id ? (id + '__BV_button_') : null" :aria-labelledby="id ? (id + '__BV_button_') : null"
@mouseover="onMouseOver"
@keyup.esc="onEsc" @keyup.esc="onEsc"
@keydown.tab="onTab" @keydown.tab="onTab"
@keydown.up="focusNext($event,true)" @keydown.up="focusNext($event,true)"
Expand All @@ -30,15 +31,6 @@
</li> </li>
</template> </template>


<style scoped>
.dropdown-item:focus,
.dropdown-item:hover,
.dropdown-header:focus {
background-color: #eaeaea;
outline: none;
}
</style>

<script> <script>
import { dropdownMixin } from '../mixins'; import { dropdownMixin } from '../mixins';
Expand All @@ -47,6 +39,22 @@
computed: { computed: {
dropdownToggle() { dropdownToggle() {
return this.noCaret ? '' : 'dropdown-toggle'; return this.noCaret ? '' : 'dropdown-toggle';
},
dropdownClasses() {
return [
'nav-item',
'b-nav-dropdown',
'dropdown',
this.dropup ? 'dropup' : '',
this.visible ? 'show' : ''
];
},
menuClasses() {
return [
'dropdown-menu',
this.right ? 'dropdown-menu-right': '',
this.visible ? 'show' : ''
];
} }
}, },
props: { props: {
Expand All @@ -57,3 +65,14 @@
} }
}; };
</script> </script>

<style>
.b-nav-dropdown.dropdown-item:focus:not(.active),
.b-nav-dropdown.dropdown-item:hover:not(.active) {
/* @See https://github.com/twbs/bootstrap/issues/23329 */
box-shadow: inset 0px 0px 400px 110px rgba(0, 0, 0, .09);
}
.b-nav-dropdown.dropdown-item:active {
box-shadow: initial;
}
</style>
24 changes: 14 additions & 10 deletions lib/mixins/dropdown.js
Expand Up @@ -14,8 +14,6 @@ function filterVisible(els) {


// Dropdown item CSS selectors // Dropdown item CSS selectors
const ITEM_SELECTOR = '.dropdown-item:not(.disabled):not([disabled])'; const ITEM_SELECTOR = '.dropdown-item:not(.disabled):not([disabled])';
const HEADER_SELECTOR = '.dropdown-header';
const ALL_SELECTOR = [ITEM_SELECTOR, HEADER_SELECTOR].join(',');


export default { export default {
mixins: [listenOnRootMixin], mixins: [listenOnRootMixin],
Expand Down Expand Up @@ -149,6 +147,16 @@ export default {
this.$nextTick(() => { this.focusToggler() }); this.$nextTick(() => { this.focusToggler() });
} }
}, },
onMouseOver(evt) {
// Focus the item on hover
const item = evt.target;
if (item.classList.contains('dropdown-item')
&& !item.disabled
&& !item.classList.contains('disabled')
&& item.focus) {
item.focus();
}
},
focusNext(e, up) { focusNext(e, up) {
if (!this.visible) { if (!this.visible) {
return; return;
Expand Down Expand Up @@ -179,16 +187,12 @@ export default {
} }
}, },
getItems() { getItems() {
// Get all items and headers // Get all items
return filterVisible(arrayFrom(this.$refs.menu.querySelectorAll(ALL_SELECTOR))); return filterVisible(arrayFrom(this.$refs.menu.querySelectorAll(ITEM_SELECTOR)));
}, },
getFirstItem() { getFirstItem() {
// Get the first non-header non-disabled item // Get the first non-disabled item
let item = filterVisible(arrayFrom(this.$refs.menu.querySelectorAll(ITEM_SELECTOR)))[0]; let item = this.getItems()[0];
if (!item) {
// If no items then try a header
item = filterVisible(arrayFrom(this.$refs.menu.querySelectorAll(HEADER_SELECTOR)))[0];
}
return item || null; return item || null;
}, },
focusFirstItem() { focusFirstItem() {
Expand Down

0 comments on commit 2e863d9

Please sign in to comment.