Skip to content

Commit 10fa210

Browse files
authored
feat(list-group): support horizontal layout (#2536)
1 parent 5c01faf commit 10fa210

File tree

5 files changed

+149
-46
lines changed

5 files changed

+149
-46
lines changed

src/components/list-group/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,44 @@ prop when using cards with `no-body` to make the sides of the list group flush w
197197
<!-- b-list-group-card.vue -->
198198
```
199199

200+
## Horizontal list groups
201+
202+
Set the prop `horizontal` to `true` to change the layout of list group items from vertical to
203+
horizontal across all breakpoints. Alternatively, set `horizontal` to a responsive breakpoint
204+
(`sm`, `md`, `lg` or `xl`) to make a list group horizontal starting at that breakpoint’s min-width.
205+
Currently horizontal list groups cannot be combined with `flush` list groups.
206+
207+
**ProTip:** Want equal-width list group items when horizontal? Add the class `flex-fill` to each
208+
list group item.
209+
210+
**Always horizontal:**
211+
212+
```html
213+
<div>
214+
<b-list-group horizontal>
215+
<b-list-group-item>Cras justo odio</b-list-group-item>
216+
<b-list-group-item>Dapibus ac facilisis in</b-list-group-item>
217+
<b-list-group-item>Morbi leo risus</b-list-group-item>
218+
</b-list-group>
219+
</div>
220+
221+
<!-- b-list-group-horizontal.vue -->
222+
```
223+
224+
**Horizontal at breakpoint md and above:**
225+
226+
```html
227+
<div>
228+
<b-list-group horizontal="md">
229+
<b-list-group-item>Cras justo odio</b-list-group-item>
230+
<b-list-group-item>Dapibus ac facilisis in</b-list-group-item>
231+
<b-list-group-item>Morbi leo risus</b-list-group-item>
232+
</b-list-group>
233+
</div>
234+
235+
<!-- b-list-group-horizontal-md.vue -->
236+
```
237+
200238
## Custom content
201239

202240
Add nearly any HTML or component within, even for linked list groups like the one below, with the

src/components/list-group/fixtures/list-group.html

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/components/list-group/fixtures/list-group.js

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/components/list-group/list-group.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ export const props = {
88
flush: {
99
type: Boolean,
1010
default: false
11+
},
12+
horizontal: {
13+
type: [Boolean, String],
14+
default: false
1115
}
1216
}
1317

@@ -17,10 +21,14 @@ export default {
1721
functional: true,
1822
props,
1923
render(h, { props, data, children }) {
24+
let horizontal = props.horizontal === '' ? true : props.horizontal
25+
horizontal = props.flush ? false : horizontal
2026
const componentData = {
2127
staticClass: 'list-group',
2228
class: {
23-
'list-group-flush': props.flush
29+
'list-group-flush': props.flush,
30+
'list-group-horizontal': horizontal === true,
31+
[`list-group-horizontal-${horizontal}`]: typeof horizontal === 'string'
2432
}
2533
}
2634
return h(props.tag, mergeData(data, componentData), children)
Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,105 @@
1-
import { loadFixture, testVM } from '../../../tests/utils'
1+
import ListGroup from './list-group'
2+
import { mount } from '@vue/test-utils'
23

34
describe('list-group', async () => {
4-
beforeEach(loadFixture(__dirname, 'list-group'))
5-
testVM()
5+
it('default should have tag div', async () => {
6+
const wrapper = mount(ListGroup)
7+
expect(wrapper.is('div')).toBe(true)
8+
})
9+
10+
it('default should contain only single class of list-group', async () => {
11+
const wrapper = mount(ListGroup)
12+
expect(wrapper.classes().length).toBe(1)
13+
expect(wrapper.classes()).toContain('list-group')
14+
expect(wrapper.classes()).not.toContain('list-group-flush')
15+
expect(wrapper.classes()).not.toContain('list-group-horizontal')
16+
})
17+
18+
it('should have tag ul then prop tag=ul', async () => {
19+
const wrapper = mount(ListGroup, {
20+
context: {
21+
props: { tag: 'ul' }
22+
}
23+
})
24+
expect(wrapper.is('ul')).toBe(true)
25+
})
26+
27+
it('should have class list-group-flush when prop flush=true', async () => {
28+
const wrapper = mount(ListGroup, {
29+
context: {
30+
props: { flush: true }
31+
}
32+
})
33+
expect(wrapper.classes().length).toBe(2)
34+
expect(wrapper.classes()).toContain('list-group')
35+
expect(wrapper.classes()).toContain('list-group-flush')
36+
expect(wrapper.classes()).not.toContain('list-group-horizontal')
37+
})
38+
39+
it('should have class list-group-horizontal when prop horizontal=true', async () => {
40+
const wrapper = mount(ListGroup, {
41+
context: {
42+
props: { horizontal: true }
43+
}
44+
})
45+
expect(wrapper.classes().length).toBe(2)
46+
expect(wrapper.classes()).not.toContain('list-group-flush')
47+
expect(wrapper.classes()).toContain('list-group')
48+
expect(wrapper.classes()).toContain('list-group-horizontal')
49+
})
50+
51+
it('should have class list-group-horizontal-md when prop horizontal=md', async () => {
52+
const wrapper = mount(ListGroup, {
53+
context: {
54+
props: { horizontal: 'md' }
55+
}
56+
})
57+
expect(wrapper.classes().length).toBe(2)
58+
expect(wrapper.classes()).not.toContain('list-group-flush')
59+
expect(wrapper.classes()).not.toContain('list-group-horizontal')
60+
expect(wrapper.classes()).toContain('list-group')
61+
expect(wrapper.classes()).toContain('list-group-horizontal-md')
62+
})
63+
64+
it('should not have class list-group-horizontal when prop horizontal=true and flush=true', async () => {
65+
const wrapper = mount(ListGroup, {
66+
context: {
67+
props: {
68+
horizontal: true,
69+
flush: true
70+
}
71+
}
72+
})
73+
expect(wrapper.classes().length).toBe(2)
74+
expect(wrapper.classes()).not.toContain('list-group-horizontal')
75+
expect(wrapper.classes()).toContain('list-group')
76+
expect(wrapper.classes()).toContain('list-group-flush')
77+
})
78+
79+
it('should not have class list-group-horizontal-lg when prop horizontal=lg and flush=true', async () => {
80+
const wrapper = mount(ListGroup, {
81+
context: {
82+
props: {
83+
horizontal: 'lg',
84+
flush: true
85+
}
86+
}
87+
})
88+
expect(wrapper.classes().length).toBe(2)
89+
expect(wrapper.classes()).not.toContain('list-group-horizontal-lg')
90+
expect(wrapper.classes()).not.toContain('list-group-horizontal')
91+
expect(wrapper.classes()).toContain('list-group')
92+
expect(wrapper.classes()).toContain('list-group-flush')
93+
})
94+
95+
it('should accept custom classes', async () => {
96+
const wrapper = mount(ListGroup, {
97+
context: {
98+
class: 'foobar'
99+
}
100+
})
101+
expect(wrapper.classes().length).toBe(2)
102+
expect(wrapper.classes()).toContain('list-group')
103+
expect(wrapper.classes()).toContain('foobar')
104+
})
6105
})

0 commit comments

Comments
 (0)