Skip to content

Commit

Permalink
feat(b-dropdown): add block support to toggle button (closes #4266) (
Browse files Browse the repository at this point in the history
…#4269)

* feat(b-dropdown): add `block` support to toggle button

* Update README.md

* Update dropdown.spec.js

* Update README.md
  • Loading branch information
jacobmllr95 committed Oct 17, 2019
1 parent 55787dd commit 30029e3
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 8 deletions.
52 changes: 52 additions & 0 deletions src/components/dropdown/README.md
Expand Up @@ -308,6 +308,58 @@ split button its own variant via the `split-variant` prop.
<!-- b-dropdown-split-variant.vue --> <!-- b-dropdown-split-variant.vue -->
``` ```


### Block level dropdowns

By default dropdowns act like buttons and are displayed inline. To create block level dropdowns
(that span to the full width of a parent) set the `block` prop. Both, regular and split button
dropdowns are supported.

```html
<div>
<b-dropdown text="Block Level Dropdown" block variant="primary" class="m-2">
<b-dropdown-item href="#">Action</b-dropdown-item>
<b-dropdown-item href="#">Another action</b-dropdown-item>
<b-dropdown-item href="#">Something else here</b-dropdown-item>
</b-dropdown>

<b-dropdown
text="Block Level Split Dropdown"
block
split
split-variant="outline-primary"
variant="primary"
class="m-2"
>
<b-dropdown-item href="#">Action</b-dropdown-item>
<b-dropdown-item href="#">Another action</b-dropdown-item>
<b-dropdown-item href="#">Something else here...</b-dropdown-item>
</b-dropdown>
</div>

<!-- b-dropdown-block.vue -->
```

If you want the dropdown menu to span to the full width of the parent container too, add the `w-100`
utility class to the `menu-class` prop.

```html
<div>
<b-dropdown
text="Block Level Dropdown Menu"
block
variant="primary"
class="m-2"
menu-class="w-100"
>
<b-dropdown-item href="#">Action</b-dropdown-item>
<b-dropdown-item href="#">Another action</b-dropdown-item>
<b-dropdown-item href="#">Something else here</b-dropdown-item>
</b-dropdown>
</div>

<!-- b-dropdown-block-menu.vue -->
```

### Dropdown sub-component color variants ### Dropdown sub-component color variants


Many of the supported dropdown [sub-components](#dropdown-supported-sub-components) provide a Many of the supported dropdown [sub-components](#dropdown-supported-sub-components) provide a
Expand Down
29 changes: 21 additions & 8 deletions src/components/dropdown/dropdown.js
Expand Up @@ -24,6 +24,10 @@ export const props = {
type: String, type: String,
default: () => getComponentConfig(NAME, 'variant') default: () => getComponentConfig(NAME, 'variant')
}, },
block: {
type: Boolean,
default: false
},
menuClass: { menuClass: {
type: [String, Array], type: [String, Array],
default: null default: null
Expand Down Expand Up @@ -84,9 +88,16 @@ export const BDropdown = /*#__PURE__*/ Vue.extend({
this.directionClass, this.directionClass,
{ {
show: this.visible, show: this.visible,
// Position `static` is needed to allow menu to "breakout" of the scrollParent boundaries // The 'btn-group' class is required in `split` mode for button alignment
// when boundary is anything other than `scrollParent` // It needs also to be applied when `block` is disabled to allow multiple
// See https://github.com/twbs/bootstrap/issues/24251#issuecomment-341413786 // dropdowns to be aligned one line
'btn-group': this.split || !this.block,
// When `block` is enabled and we are in `split` mode the 'd-flex' class
// needs to be applied to allow the buttons to stretch to full width
'd-flex': this.block && this.split,
// Position `static` is needed to allow menu to "breakout" of the `scrollParent`
// boundaries when boundary is anything other than `scrollParent`
// See: https://github.com/twbs/bootstrap/issues/24251#issuecomment-341413786
'position-static': this.boundary !== 'scrollParent' || !this.boundary 'position-static': this.boundary !== 'scrollParent' || !this.boundary
} }
] ]
Expand Down Expand Up @@ -115,9 +126,10 @@ export const BDropdown = /*#__PURE__*/ Vue.extend({
const buttonContent = this.normalizeSlot('button-content') || this.html || stripTags(this.text) const buttonContent = this.normalizeSlot('button-content') || this.html || stripTags(this.text)
if (this.split) { if (this.split) {
const btnProps = { const btnProps = {
disabled: this.disabled,
variant: this.splitVariant || this.variant, variant: this.splitVariant || this.variant,
size: this.size size: this.size,
block: this.block,
disabled: this.disabled
} }
// We add these as needed due to router-link issues with defined property with undefined/null values // We add these as needed due to router-link issues with defined property with undefined/null values
if (this.splitTo) { if (this.splitTo) {
Expand Down Expand Up @@ -149,10 +161,11 @@ export const BDropdown = /*#__PURE__*/ Vue.extend({
staticClass: 'dropdown-toggle', staticClass: 'dropdown-toggle',
class: this.toggleClasses, class: this.toggleClasses,
props: { props: {
tag: this.toggleTag,
variant: this.variant, variant: this.variant,
size: this.size, size: this.size,
disabled: this.disabled, block: this.block && !this.split,
tag: this.toggleTag disabled: this.disabled
}, },
attrs: { attrs: {
id: this.safeId('_BV_toggle_'), id: this.safeId('_BV_toggle_'),
Expand Down Expand Up @@ -186,7 +199,7 @@ export const BDropdown = /*#__PURE__*/ Vue.extend({
return h( return h(
'div', 'div',
{ {
staticClass: 'dropdown btn-group b-dropdown', staticClass: 'dropdown b-dropdown',
class: this.dropdownClasses, class: this.dropdownClasses,
attrs: { id: this.safeId() } attrs: { id: this.safeId() }
}, },
Expand Down
24 changes: 24 additions & 0 deletions src/components/dropdown/dropdown.spec.js
Expand Up @@ -247,6 +247,30 @@ describe('dropdown', () => {
wrapper.destroy() wrapper.destroy()
}) })


it('should not have "btn-group" class when block is true', async () => {
const wrapper = mount(BDropdown, {
attachToDocument: true,
propsData: {
block: true
}
})
expect(wrapper.classes()).not.toContain('btn-group')
wrapper.destroy()
})

it('should have "btn-group" and "d-flex" classes when block and split are true', async () => {
const wrapper = mount(BDropdown, {
attachToDocument: true,
propsData: {
block: true,
split: true
}
})
expect(wrapper.classes()).toContain('btn-group')
expect(wrapper.classes()).toContain('d-flex')
wrapper.destroy()
})

it('should have "dropdown-toggle-no-caret" class when no-caret is true', async () => { it('should have "dropdown-toggle-no-caret" class when no-caret is true', async () => {
const wrapper = mount(BDropdown, { const wrapper = mount(BDropdown, {
attachToDocument: true, attachToDocument: true,
Expand Down
4 changes: 4 additions & 0 deletions src/components/dropdown/package.json
Expand Up @@ -67,6 +67,10 @@
"prop": "toggleClass", "prop": "toggleClass",
"description": "CSS class (or classes) to add to the toggle button" "description": "CSS class (or classes) to add to the toggle button"
}, },
{
"prop": "block",
"description": "Renders a 100% width toggle button (expands to the width of it's parent container)"
},
{ {
"prop": "noCaret", "prop": "noCaret",
"description": "Hide the caret indicator on the toggle button" "description": "Hide the caret indicator on the toggle button"
Expand Down

0 comments on commit 30029e3

Please sign in to comment.