+125
-43
lines changedFilter options
+125
-43
lines changed Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
1
1
import Vue from '../../utils/vue'
2
-
import { isBrowser } from '../../utils/env'
2
+
import { BVCollapse } from '../../utils/bv-collapse'
3
3
import { addClass, hasClass, removeClass, closest, matches, getCS } from '../../utils/dom'
4
+
import { isBrowser } from '../../utils/env'
4
5
import { EVENT_OPTIONS_NO_CAPTURE, eventOnOff } from '../../utils/events'
5
-
import { BVCollapse } from '../../utils/bv-collapse'
6
6
import idMixin from '../../mixins/id'
7
7
import listenOnRootMixin from '../../mixins/listen-on-root'
8
8
import normalizeSlotMixin from '../../mixins/normalize-slot'
9
+
import {
10
+
EVENT_TOGGLE,
11
+
EVENT_STATE,
12
+
EVENT_STATE_REQUEST,
13
+
EVENT_STATE_SYNC
14
+
} from '../../directives/toggle/toggle'
15
+
16
+
// --- Constants ---
9
17
10
-
// Events we emit on $root
11
-
const EVENT_STATE = 'bv::collapse::state'
18
+
// Accordion event name we emit on `$root`
12
19
const EVENT_ACCORDION = 'bv::collapse::accordion'
13
-
// Private event we emit on `$root` to ensure the toggle state is
14
-
// always synced. It gets emitted even if the state has not changed!
15
-
// This event is NOT to be documented as people should not be using it
16
-
const EVENT_STATE_SYNC = 'bv::collapse::sync::state'
17
-
// Events we listen to on `$root`
18
-
const EVENT_TOGGLE = 'bv::toggle::collapse'
19
-
const EVENT_STATE_REQUEST = 'bv::request::collapse::state'
20
20
21
+
// --- Main component ---
21
22
// @vue/component
22
23
export const BCollapse = /*#__PURE__*/ Vue.extend({
23
24
name: 'BCollapse',
Original file line number Diff line number Diff line change
@@ -281,6 +281,39 @@ will reverse the placement of the toggler.
281
281
See the first example on this page for reference, and also refer to
282
282
[`<b-collapse>`](/docs/components/collapse) for details on the collapse component.
283
283
284
+
#### Custom navbar toggle
285
+
286
+
`<b-navbar-toggle>` renders the default Bootstrap v4 _hamburger_ (which is a background SVG image).
287
+
You can supply your own content (such as an icon) via the optionally scoped `default` slot. The
288
+
default slot scope contains the property `expanded`, which will be `true` when the collapse is
289
+
expanded, or `false` when the collapse is collapsed. You can use this to swap the toggle content
290
+
based on the collapse state:
291
+
292
+
```html
293
+
<template>
294
+
<b-navbar toggleable type="dark" variant="dark">
295
+
<b-navbar-brand href="#">NavBar</b-navbar-brand>
296
+
297
+
<b-navbar-toggle target="navbar-toggle-collapse">
298
+
<template v-slot:default="{ expanded }">
299
+
<b-icon v-if="expanded" icon="chevron-bar-up"></b-icon>
300
+
<b-icon v-else icon="chevron-bar-down"></b-icon>
301
+
</template>
302
+
</b-navbar-toggle>
303
+
304
+
<b-collapse id="navbar-toggle-collapse" is-nav>
305
+
<b-navbar-nav class="ml-auto">
306
+
<b-nav-item href="#">Link 1</b-nav-item>
307
+
<b-nav-item href="#">Link 2</b-nav-item>
308
+
<b-nav-item href="#" disabled>Disabled</b-nav-item>
309
+
</b-navbar-nav>
310
+
</b-collapse>
311
+
</b-navbar>
312
+
</template>
313
+
314
+
<!-- b-navbar-toggle-slot.vue -->
315
+
```
316
+
284
317
## Printing
285
318
286
319
Navbars are hidden by default when printing. Force them to be printed by setting the `print` prop.
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
1
1
import Vue from '../../utils/vue'
2
+
import { getComponentConfig } from '../../utils/config'
3
+
import { toString } from '../../utils/string'
2
4
import listenOnRootMixin from '../../mixins/listen-on-root'
3
5
import normalizeSlotMixin from '../../mixins/normalize-slot'
4
-
import { getComponentConfig } from '../../utils/config'
6
+
import { EVENT_TOGGLE, EVENT_STATE, EVENT_STATE_SYNC } from '../../directives/toggle/toggle'
5
7
6
-
const NAME = 'BNavbarToggle'
8
+
// TODO:
9
+
// Switch to using `VBToggle` directive, will reduce code footprint
10
+
// Although the `click` event will no longer be cancellable
11
+
// Instead add `disabled` prop, and have `VBToggle` check element
12
+
// disabled state
7
13
8
-
// TODO: Switch to using VBToggle directive, will reduce code footprint
14
+
// --- Constants ---
9
15
10
-
// Events we emit on $root
11
-
const EVENT_TOGGLE = 'bv::toggle::collapse'
12
-
13
-
// Events we listen to on $root
14
-
const EVENT_STATE = 'bv::collapse::state'
15
-
// This private event is NOT to be documented as people should not be using it.
16
-
const EVENT_STATE_SYNC = 'bv::collapse::sync::state'
16
+
const NAME = 'BNavbarToggle'
17
+
const CLASS_NAME = 'navbar-toggler'
17
18
19
+
// --- Main component ---
18
20
// @vue/component
19
21
export const BNavbarToggle = /*#__PURE__*/ Vue.extend({
20
22
name: NAME,
@@ -52,19 +54,23 @@ export const BNavbarToggle = /*#__PURE__*/ Vue.extend({
52
54
}
53
55
},
54
56
render(h) {
57
+
const expanded = this.toggleState
55
58
return h(
56
59
'button',
57
60
{
58
-
class: ['navbar-toggler'],
61
+
staticClass: CLASS_NAME,
59
62
attrs: {
60
63
type: 'button',
61
64
'aria-label': this.label,
62
65
'aria-controls': this.target,
63
-
'aria-expanded': this.toggleState ? 'true' : 'false'
66
+
'aria-expanded': toString(expanded)
64
67
},
65
68
on: { click: this.onClick }
66
69
},
67
-
[this.normalizeSlot('default') || h('span', { class: ['navbar-toggler-icon'] })]
70
+
[
71
+
this.normalizeSlot('default', { expanded }) ||
72
+
h('span', { staticClass: `${CLASS_NAME}-icon` })
73
+
]
68
74
)
69
75
}
70
76
})
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ describe('navbar-toggle', () => {
5
5
it('default has tag "button"', async () => {
6
6
const wrapper = mount(BNavbarToggle, {
7
7
propsData: {
8
-
target: 'target'
8
+
target: 'target-1'
9
9
}
10
10
})
11
11
expect(wrapper.is('button')).toBe(true)
@@ -14,7 +14,7 @@ describe('navbar-toggle', () => {
14
14
it('default has class "navbar-toggler"', async () => {
15
15
const wrapper = mount(BNavbarToggle, {
16
16
propsData: {
17
-
target: 'target'
17
+
target: 'target-2'
18
18
}
19
19
})
20
20
expect(wrapper.classes()).toContain('navbar-toggler')
@@ -24,19 +24,19 @@ describe('navbar-toggle', () => {
24
24
it('default has default attributes', async () => {
25
25
const wrapper = mount(BNavbarToggle, {
26
26
propsData: {
27
-
target: 'target'
27
+
target: 'target-3'
28
28
}
29
29
})
30
30
expect(wrapper.attributes('type')).toBe('button')
31
-
expect(wrapper.attributes('aria-controls')).toBe('target')
31
+
expect(wrapper.attributes('aria-controls')).toBe('target-3')
32
32
expect(wrapper.attributes('aria-expanded')).toBe('false')
33
33
expect(wrapper.attributes('aria-label')).toBe('Toggle navigation')
34
34
})
35
35
36
36
it('default has inner button-close', async () => {
37
37
const wrapper = mount(BNavbarToggle, {
38
38
propsData: {
39
-
target: 'target'
39
+
target: 'target-4'
40
40
}
41
41
})
42
42
expect(wrapper.find('span.navbar-toggler-icon')).toBeDefined()
@@ -45,17 +45,45 @@ describe('navbar-toggle', () => {
45
45
it('accepts custom label when label prop is set', async () => {
46
46
const wrapper = mount(BNavbarToggle, {
47
47
propsData: {
48
-
target: 'target',
48
+
target: 'target-5',
49
49
label: 'foobar'
50
50
}
51
51
})
52
52
expect(wrapper.attributes('aria-label')).toBe('foobar')
53
53
})
54
54
55
+
it('default slot scope works', async () => {
56
+
let scope = null
57
+
const wrapper = mount(BNavbarToggle, {
58
+
propsData: {
59
+
target: 'target-6'
60
+
},
61
+
scopedSlots: {
62
+
default(ctx) {
63
+
scope = ctx
64
+
return this.$createElement('div', 'foobar')
65
+
}
66
+
}
67
+
})
68
+
69
+
expect(scope).not.toBe(null)
70
+
expect(scope.expanded).toBe(false)
71
+
72
+
wrapper.vm.$root.$emit('bv::collapse::state', 'target-6', true)
73
+
74
+
expect(scope).not.toBe(null)
75
+
expect(scope.expanded).toBe(true)
76
+
77
+
wrapper.vm.$root.$emit('bv::collapse::state', 'target-6', false)
78
+
79
+
expect(scope).not.toBe(null)
80
+
expect(scope.expanded).toBe(false)
81
+
})
82
+
55
83
it('emits click event', async () => {
56
84
const wrapper = mount(BNavbarToggle, {
57
85
propsData: {
58
-
target: 'target'
86
+
target: 'target-7'
59
87
}
60
88
})
61
89
let rootClicked = false
@@ -77,22 +105,22 @@ describe('navbar-toggle', () => {
77
105
it('sets aria-expanded when receives root emit for target', async () => {
78
106
const wrapper = mount(BNavbarToggle, {
79
107
propsData: {
80
-
target: 'target'
108
+
target: 'target-8'
81
109
}
82
110
})
83
111
84
112
// Private state event
85
-
wrapper.vm.$root.$emit('bv::collapse::state', 'target', true)
113
+
wrapper.vm.$root.$emit('bv::collapse::state', 'target-8', true)
86
114
expect(wrapper.attributes('aria-expanded')).toBe('true')
87
-
wrapper.vm.$root.$emit('bv::collapse::state', 'target', false)
115
+
wrapper.vm.$root.$emit('bv::collapse::state', 'target-8', false)
88
116
expect(wrapper.attributes('aria-expanded')).toBe('false')
89
117
wrapper.vm.$root.$emit('bv::collapse::state', 'foo', true)
90
118
expect(wrapper.attributes('aria-expanded')).toBe('false')
91
119
92
120
// Private sync event
93
-
wrapper.vm.$root.$emit('bv::collapse::sync::state', 'target', true)
121
+
wrapper.vm.$root.$emit('bv::collapse::sync::state', 'target-8', true)
94
122
expect(wrapper.attributes('aria-expanded')).toBe('true')
95
-
wrapper.vm.$root.$emit('bv::collapse::sync::state', 'target', false)
123
+
wrapper.vm.$root.$emit('bv::collapse::sync::state', 'target-8', false)
96
124
expect(wrapper.attributes('aria-expanded')).toBe('false')
97
125
wrapper.vm.$root.$emit('bv::collapse::sync::state', 'foo', true)
98
126
expect(wrapper.attributes('aria-expanded')).toBe('false')
Original file line number Diff line number Diff line change
@@ -86,6 +86,20 @@
86
86
}
87
87
]
88
88
}
89
+
],
90
+
"slots": [
91
+
{
92
+
"name": "default",
93
+
"description": "Alternate content to replace the default Bootstrap hamburger",
94
+
"scope": [
95
+
{
96
+
"prop": "expanded",
97
+
"version": "2.9.0",
98
+
"type": "Boolean",
99
+
"description": "`true` if the collapse is expanded, `false` otherwise."
100
+
}
101
+
]
102
+
}
89
103
]
90
104
}
91
105
]
Original file line number Diff line number Diff line change
@@ -13,17 +13,17 @@ const BV_TOGGLE_CONTROLS = '__BV_toggle_CONTROLS__'
13
13
const BV_TOGGLE_TARGETS = '__BV_toggle_TARGETS__'
14
14
15
15
// Emitted control event for collapse (emitted to collapse)
16
-
const EVENT_TOGGLE = 'bv::toggle::collapse'
16
+
export const EVENT_TOGGLE = 'bv::toggle::collapse'
17
17
18
18
// Listen to event for toggle state update (emitted by collapse)
19
-
const EVENT_STATE = 'bv::collapse::state'
19
+
export const EVENT_STATE = 'bv::collapse::state'
20
20
21
-
// Private event emitted on $root to ensure the toggle state is always synced.
22
-
// Gets emitted even if the state of b-collapse has not changed.
23
-
// This event is NOT to be documented as people should not be using it.
24
-
const EVENT_STATE_SYNC = 'bv::collapse::sync::state'
21
+
// Private event emitted on `$root` to ensure the toggle state is always synced
22
+
// Gets emitted even if the state of b-collapse has not changed
23
+
// This event is NOT to be documented as people should not be using it
24
+
export const EVENT_STATE_SYNC = 'bv::collapse::sync::state'
25
25
// Private event we send to collapse to request state update sync event
26
-
const EVENT_STATE_REQUEST = 'bv::request::collapse::state'
26
+
export const EVENT_STATE_REQUEST = 'bv::request::collapse::state'
27
27
28
28
// Reset and remove a property from the provided element
29
29
const resetProp = (el, prop) => {
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4