Skip to content

Commit

Permalink
New component b-button-toolbar (#367)
Browse files Browse the repository at this point in the history
* [button-toolbar] New component

* [button-toolbar] sizing must be on children

* [components] New button-toolbar

* [components] New button-toolbar

* [components] New button-toolbar

* [button-group] Removed toolbar option & key nav

Moved to new button-toolbar wrapper component

* Update button-group.vue
  • Loading branch information
tmorehouse authored and pi0 committed May 9, 2017
1 parent 45362fb commit 747a801
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 92 deletions.
94 changes: 2 additions & 92 deletions lib/components/button-group.vue
Original file line number Diff line number Diff line change
@@ -1,123 +1,33 @@
<template>
<div :class="classObject"
:role="toolbar ? 'toolbar' : 'group'"
:tabindex="isKeyNav ? '0' : null"
@focusin.self="focusFirst"
@keydown.left="focusNext($event,true)"
@keydown.up="focusNext($event,true)"
@keydown.right="focusNext($event,false)"
@keydown.down="focusNext($event,false)"
@keydown.shift.left="focusFirst($event)"
@keydown.shift.up="focusFirst($event)"
@keydown.shift.right="focusLast($event)"
@keydown.shift.down="focusLast($event)"
>
<div :class="classObject">
<slot></slot>
</div>
</template>

<script>
const ITEM_SELECTOR = [
'.btn:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])',
'.form-control:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])',
'select:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])',
'input[type="checkbox"]:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])',
'input[type="radio"]:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])'
].join(',');
export default {
computed: {
classObject() {
return [
'btn-' + (this.toolbar ? 'toolbar' : 'group'),
'btn-group',
this.vertical ? 'btn-group-vertical' : '',
(this.justify && !this.vertical) ? 'justify-content-between' : '',
this.size ? ('btn-group-' + this.size) : ''
];
},
isKeyNav() {
return this.toolbar && this.toolbarKeyNav;
}
},
props: {
vertical: {
type: Boolean,
default: false
},
toolbar: {
type: Boolean,
default: false
},
justify: {
type: Boolean,
default: false
},
size: {
type: String,
default: null
},
toolbarKeyNav: {
type: Boolean,
default: false
}
},
methods: {
focusNext(e, prev) {
if (!this.isKeyNav) {
return;
}
e.preventDefault();
e.stopPropagation();
const items = this.getItems();
if (items.length < 1) {
return;
}
let index = items.indexOf(e.target);
if (prev && index > 0) {
index--;
} else if (!prev && index < items.length - 1) {
index++;
}
if (index < 0) {
index = 0;
}
items[index].focus();
},
focusFirst(e) {
if (!this.isKeyNav) {
return;
}
e.preventDefault();
e.stopPropagation();
const items = this.getItems();
if (items.length > 0) {
items[0].focus();
}
},
focusLast(e) {
if (!this.isKeyNav) {
return;
}
e.preventDefault();
e.stopPropagation();
const items = this.getItems();
if (items.length > 0) {
items[items.length - 1].focus();
}
},
getItems() {
const items = Array.prototype.slice.call(this.$el.querySelectorAll(ITEM_SELECTOR));
items.forEach(item => {
// Ensure tabfocus is -1 on any new elements
item.tabIndex = -1;
});
return items;
}
},
mounted() {
if (this.isKeyNav) {
// Pre-set the tabindexes if the markup does not include tabindex="-1" on the toolbar items
this.getItems();
}
}
};
Expand Down
107 changes: 107 additions & 0 deletions lib/components/button-toolbar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<template>
<div :class="classObject"
role="toolbar"
:tabindex="keyNav ? '0' : null"
@focusin.self="focusFirst"
@keydown.left="focusNext($event,true)"
@keydown.up="focusNext($event,true)"
@keydown.right="focusNext($event,false)"
@keydown.down="focusNext($event,false)"
@keydown.shift.left="focusFirst($event)"
@keydown.shift.up="focusFirst($event)"
@keydown.shift.right="focusLast($event)"
@keydown.shift.down="focusLast($event)"
>
<slot></slot>
</div>
</template>

<script>
const ITEM_SELECTOR = [
'.btn:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])',
'.form-control:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])',
'select:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])',
'input[type="checkbox"]:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])',
'input[type="radio"]:not(.disabled):not([disabled]):not([style*="display: none"]):not([style*="display:none"])'
].join(',');
export default {
computed: {
classObject() {
return [
'btn-toolbar',
(this.justify && !this.vertical) ? 'justify-content-between' : ''
];
}
},
props: {
justify: {
type: Boolean,
default: false
},
KeyNav: {
type: Boolean,
default: false
}
},
methods: {
focusNext(e, prev) {
if (!this.keyNav) {
return;
}
e.preventDefault();
e.stopPropagation();
const items = this.getItems();
if (items.length < 1) {
return;
}
let index = items.indexOf(e.target);
if (prev && index > 0) {
index--;
} else if (!prev && index < items.length - 1) {
index++;
}
if (index < 0) {
index = 0;
}
items[index].focus();
},
focusFirst(e) {
if (!this.keyNav) {
return;
}
e.preventDefault();
e.stopPropagation();
const items = this.getItems();
if (items.length > 0) {
items[0].focus();
}
},
focusLast(e) {
if (!this.keyNav) {
return;
}
e.preventDefault();
e.stopPropagation();
const items = this.getItems();
if (items.length > 0) {
items[items.length - 1].focus();
}
},
getItems() {
const items = Array.prototype.slice.call(this.$el.querySelectorAll(ITEM_SELECTOR));
items.forEach(item => {
// Ensure tabfocus is -1 on any new elements
item.tabIndex = -1;
});
return items;
}
},
mounted() {
if (this.keyNav) {
// Pre-set the tabindexes if the markup does not include tabindex="-1" on the toolbar items
this.getItems();
}
}
};
</script>
2 changes: 2 additions & 0 deletions lib/components/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import bAlert from './alert.vue';
import bBreadcrumb from './breadcrumb.vue';
import bButton from './button.vue';
import bButtonToolbar from './button-toolbar.vue';
import bButtonGroup from './button-group.vue';
import bButtonGroupDropdown from './button-group-dropdown.vue';
import bInputGroup from './input-group.vue';
Expand Down Expand Up @@ -49,6 +50,7 @@ export {
bBreadcrumb,
bButton,
bButton as bBtn,
bButtonToolbar,
bButtonGroup,
bButtonGroupDropdown,
bInputGroup,
Expand Down

0 comments on commit 747a801

Please sign in to comment.