Skip to content

Commit b6557ad

Browse files
authored
feat(tabs): add fill, justified and active-class props (closes #3053, #2518) (#3061)
feat(tabs): add `fill`, `justified` and active class props (closes #3053, #2518)
1 parent d37500e commit b6557ad

File tree

12 files changed

+559
-121
lines changed

12 files changed

+559
-121
lines changed

src/components/nav/README.md

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ variants are mutually exclusive - use only one style or the other.
3030

3131
### Tab style
3232

33-
Make the nav look like tabs by setting the prop `tabs`.
33+
Make the nav look like tabs by setting the `tabs` prop.
3434

3535
```html
3636
<div>
@@ -47,7 +47,7 @@ Make the nav look like tabs by setting the prop `tabs`.
4747

4848
### Pill style
4949

50-
Use the pill style by setting the prop `pills`.
50+
Use the pill style by setting the `pills` prop.
5151

5252
```html
5353
<div>
@@ -62,9 +62,26 @@ Use the pill style by setting the prop `pills`.
6262
<!-- b-nav-pills.vue -->
6363
```
6464

65+
### Small
66+
67+
Make the nav smaller by setting the `small` prop.
68+
69+
```html
70+
<div>
71+
<b-nav small>
72+
<b-nav-item active>Active</b-nav-item>
73+
<b-nav-item>Link</b-nav-item>
74+
<b-nav-item>Another Link</b-nav-item>
75+
<b-nav-item disabled>Disabled</b-nav-item>
76+
</b-nav>
77+
</div>
78+
79+
<!-- b-nav-small.vue -->
80+
```
81+
6582
## Fill and justify
6683

67-
Force your `b-nav` content to extend the full available width.
84+
Force your `<b-nav>` content to extend the full available width.
6885

6986
### Fill
7087

@@ -73,7 +90,7 @@ prop. Notice that all horizontal space is occupied, but not every nav item has t
7390

7491
```html
7592
<div>
76-
<b-nav fill tabs>
93+
<b-nav tabs fill>
7794
<b-nav-item active>Active</b-nav-item>
7895
<b-nav-item>Link</b-nav-item>
7996
<b-nav-item>Link with a long name </b-nav-item>
@@ -86,12 +103,12 @@ prop. Notice that all horizontal space is occupied, but not every nav item has t
86103

87104
### Justified
88105

89-
For equal-width elements, set prop `justified` instead. All horizontal space will be occupied by nav
90-
links, but unlike `fill` above, every `<b-nav-item>` will be the same width.
106+
For equal-width elements, set the `justified` prop instead. All horizontal space will be occupied by
107+
nav links, but unlike `fill` above, every `<b-nav-item>` will be the same width.
91108

92109
```html
93110
<div>
94-
<b-nav justified tabs>
111+
<b-nav tabs justified>
95112
<b-nav-item active>Active</b-nav-item>
96113
<b-nav-item>Link</b-nav-item>
97114
<b-nav-item>Link with a long name </b-nav-item>
@@ -102,6 +119,24 @@ links, but unlike `fill` above, every `<b-nav-item>` will be the same width.
102119
<!-- b-nav-justified.vue -->
103120
```
104121

122+
## Alignment
123+
124+
To align your `<b-nav-item>` components, use the `align` prop. Available values are `left`, `center`
125+
and `right`.
126+
127+
```html
128+
<div>
129+
<b-nav tabs align="center">
130+
<b-nav-item active>Active</b-nav-item>
131+
<b-nav-item>Link</b-nav-item>
132+
<b-nav-item>Link with a long name </b-nav-item>
133+
<b-nav-item disabled>Disabled</b-nav-item>
134+
</b-nav>
135+
</div>
136+
137+
<!-- b-nav-alignment.vue -->
138+
```
139+
105140
## Vertical variation
106141

107142
By default `<b-nav>` appear on a horizontal line. Stack your navigation by setting the `vertical`

src/components/nav/nav-form.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import Vue from 'vue'
2-
import BForm, { props as BFormProps } from '../form/form'
32
import { mergeData } from 'vue-functional-data-merge'
4-
import copyProps from '../../utils/copy-props'
5-
6-
const formProps = copyProps(BFormProps)
7-
delete formProps.inline
3+
import BForm, { props as BFormProps } from '../form/form'
4+
import { omit } from '../../utils/object'
85

9-
export const props = {
10-
...formProps
11-
}
6+
export const props = omit(BFormProps, ['inline'])
127

138
// @vue/component
149
export default Vue.extend({

src/components/nav/nav.js

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import Vue from 'vue'
22
import { mergeData } from 'vue-functional-data-merge'
3-
import warn from '../../utils/warn'
3+
4+
// -- Constants --
5+
6+
const DEPRECATED_MSG =
7+
'Setting prop "is-nav-bar" is deprecated. Use the <b-navbar-nav> component instead.'
48

59
export const props = {
610
tag: {
@@ -15,6 +19,10 @@ export const props = {
1519
type: Boolean,
1620
default: false
1721
},
22+
align: {
23+
type: String,
24+
default: null
25+
},
1826
tabs: {
1927
type: Boolean,
2028
default: false
@@ -27,22 +35,33 @@ export const props = {
2735
type: Boolean,
2836
default: false
2937
},
30-
isNavBar: {
38+
small: {
3139
type: Boolean,
3240
default: false
41+
},
42+
isNavBar: {
43+
type: Boolean,
44+
default: false,
45+
// `deprecated` -> Don't use this prop
46+
// `deprecation` -> Refers to a change in prop usage
47+
deprecated: DEPRECATED_MSG
3348
}
3449
}
3550

51+
// -- Utils --
52+
53+
const computeJustifyContent = value => {
54+
// Normalize value
55+
value = value === 'left' ? 'start' : value === 'right' ? 'end' : value
56+
return `justify-content-${value}`
57+
}
58+
3659
// @vue/component
3760
export default Vue.extend({
3861
name: 'BNav',
3962
functional: true,
4063
props,
4164
render(h, { props, data, children }) {
42-
if (props.isNavBar) {
43-
/* istanbul ignore next */
44-
warn("b-nav: Prop 'is-nav-bar' is deprecated. Please use component '<b-navbar-nav>' instead.")
45-
}
4665
return h(
4766
props.tag,
4867
mergeData(data, {
@@ -52,8 +71,10 @@ export default Vue.extend({
5271
'nav-tabs': props.tabs && !props.isNavBar,
5372
'nav-pills': props.pills && !props.isNavBar,
5473
'flex-column': props.vertical && !props.isNavBar,
55-
'nav-fill': props.fill,
56-
'nav-justified': props.justified
74+
'nav-fill': !props.vertical && props.fill,
75+
'nav-justified': !props.vertical && props.justified,
76+
[computeJustifyContent(props.align)]: !props.vertical && props.align,
77+
small: props.small
5778
}
5879
}),
5980
children

src/components/nav/nav.spec.js

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ describe('nav', () => {
3737
expect(wrapper.text()).toBe('foobar')
3838
})
3939

40+
it('supports "is-navbar-nav" mode', async () => {
41+
const wrapper = mount(BNav, {
42+
propsData: {
43+
isNavBar: true
44+
}
45+
})
46+
47+
expect(wrapper.is('ul')).toBe(true)
48+
expect(wrapper.classes()).toContain('navbar-nav')
49+
expect(wrapper.classes().length).toBe(1)
50+
expect(wrapper.text()).toBe('')
51+
})
52+
4053
it('applies pill style', async () => {
4154
const wrapper = mount(BNav, {
4255
propsData: {
@@ -51,6 +64,20 @@ describe('nav', () => {
5164
expect(wrapper.text()).toBe('')
5265
})
5366

67+
it("doesn't apply pill style when in 'is-navbar-nav' mode", async () => {
68+
const wrapper = mount(BNav, {
69+
propsData: {
70+
pills: true,
71+
isNavBar: true
72+
}
73+
})
74+
75+
expect(wrapper.is('ul')).toBe(true)
76+
expect(wrapper.classes()).toContain('navbar-nav')
77+
expect(wrapper.classes().length).toBe(1)
78+
expect(wrapper.text()).toBe('')
79+
})
80+
5481
it('applies tab style', async () => {
5582
const wrapper = mount(BNav, {
5683
propsData: {
@@ -65,7 +92,21 @@ describe('nav', () => {
6592
expect(wrapper.text()).toBe('')
6693
})
6794

68-
it('applies flex-column style when vertical', async () => {
95+
it("doesn't apply tab style when in 'is-navbar-nav' mode", async () => {
96+
const wrapper = mount(BNav, {
97+
propsData: {
98+
tabs: true,
99+
isNavBar: true
100+
}
101+
})
102+
103+
expect(wrapper.is('ul')).toBe(true)
104+
expect(wrapper.classes()).toContain('navbar-nav')
105+
expect(wrapper.classes().length).toBe(1)
106+
expect(wrapper.text()).toBe('')
107+
})
108+
109+
it('applies vertical style', async () => {
69110
const wrapper = mount(BNav, {
70111
propsData: {
71112
vertical: true
@@ -79,6 +120,20 @@ describe('nav', () => {
79120
expect(wrapper.text()).toBe('')
80121
})
81122

123+
it("doesn't apply vertical style when in 'is-navbar-nav' mode", async () => {
124+
const wrapper = mount(BNav, {
125+
propsData: {
126+
vertical: true,
127+
isNavBar: true
128+
}
129+
})
130+
131+
expect(wrapper.is('ul')).toBe(true)
132+
expect(wrapper.classes()).toContain('navbar-nav')
133+
expect(wrapper.classes().length).toBe(1)
134+
expect(wrapper.text()).toBe('')
135+
})
136+
82137
it('applies justify style when justified', async () => {
83138
const wrapper = mount(BNav, {
84139
propsData: {
@@ -93,6 +148,21 @@ describe('nav', () => {
93148
expect(wrapper.text()).toBe('')
94149
})
95150

151+
it("doesn't apply justify style when vertical", async () => {
152+
const wrapper = mount(BNav, {
153+
propsData: {
154+
justified: true,
155+
vertical: true
156+
}
157+
})
158+
159+
expect(wrapper.is('ul')).toBe(true)
160+
expect(wrapper.classes()).toContain('nav')
161+
expect(wrapper.classes()).toContain('flex-column')
162+
expect(wrapper.classes().length).toBe(2)
163+
expect(wrapper.text()).toBe('')
164+
})
165+
96166
it('applies fill style style when fill set', async () => {
97167
const wrapper = mount(BNav, {
98168
propsData: {
@@ -106,4 +176,62 @@ describe('nav', () => {
106176
expect(wrapper.classes().length).toBe(2)
107177
expect(wrapper.text()).toBe('')
108178
})
179+
180+
it("doesn't apply fill style when vertical", async () => {
181+
const wrapper = mount(BNav, {
182+
propsData: {
183+
fill: true,
184+
vertical: true
185+
}
186+
})
187+
188+
expect(wrapper.is('ul')).toBe(true)
189+
expect(wrapper.classes()).toContain('nav')
190+
expect(wrapper.classes()).toContain('flex-column')
191+
expect(wrapper.classes().length).toBe(2)
192+
expect(wrapper.text()).toBe('')
193+
})
194+
195+
it('applies alignment correctly', async () => {
196+
const wrapper = mount(BNav, {
197+
propsData: {
198+
align: 'center'
199+
}
200+
})
201+
202+
expect(wrapper.is('ul')).toBe(true)
203+
expect(wrapper.classes()).toContain('nav')
204+
expect(wrapper.classes()).toContain('justify-content-center')
205+
expect(wrapper.classes().length).toBe(2)
206+
expect(wrapper.text()).toBe('')
207+
})
208+
209+
it("doesn't apply alignment when vertical", async () => {
210+
const wrapper = mount(BNav, {
211+
propsData: {
212+
align: 'center',
213+
vertical: true
214+
}
215+
})
216+
217+
expect(wrapper.is('ul')).toBe(true)
218+
expect(wrapper.classes()).toContain('nav')
219+
expect(wrapper.classes()).toContain('flex-column')
220+
expect(wrapper.classes().length).toBe(2)
221+
expect(wrapper.text()).toBe('')
222+
})
223+
224+
it('applies small style', async () => {
225+
const wrapper = mount(BNav, {
226+
propsData: {
227+
small: true
228+
}
229+
})
230+
231+
expect(wrapper.is('ul')).toBe(true)
232+
expect(wrapper.classes()).toContain('nav')
233+
expect(wrapper.classes()).toContain('small')
234+
expect(wrapper.classes().length).toBe(2)
235+
expect(wrapper.text()).toBe('')
236+
})
109237
})

src/components/nav/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "1.0.0",
44
"meta": {
55
"title": "Nav",
6+
"enhanced": true,
67
"description": "Navigation components that share general markup and styles, from the base <b-nav> class to the active and disabled states. Swap modifier props to switch between each style.",
78
"plugins": [
89
"Dropdown"

0 commit comments

Comments
 (0)