@@ -18,6 +18,10 @@ import AccordionTitle from './AccordionTitle'
18
18
* An accordion allows users to toggle the display of sections of content
19
19
*/
20
20
export default class Accordion extends Component {
21
+ static defaultProps = {
22
+ exclusive : true ,
23
+ }
24
+
21
25
static autoControlledProps = [
22
26
'activeIndex' ,
23
27
]
@@ -27,7 +31,10 @@ export default class Accordion extends Component {
27
31
as : customPropTypes . as ,
28
32
29
33
/** Index of the currently active panel. */
30
- activeIndex : PropTypes . number ,
34
+ activeIndex : PropTypes . oneOfType ( [
35
+ PropTypes . number ,
36
+ PropTypes . arrayOf ( PropTypes . number ) ,
37
+ ] ) ,
31
38
32
39
/** Primary content. */
33
40
children : PropTypes . node ,
@@ -36,7 +43,13 @@ export default class Accordion extends Component {
36
43
className : PropTypes . string ,
37
44
38
45
/** Initial activeIndex value. */
39
- defaultActiveIndex : PropTypes . number ,
46
+ defaultActiveIndex : PropTypes . oneOfType ( [
47
+ PropTypes . number ,
48
+ PropTypes . arrayOf ( PropTypes . number ) ,
49
+ ] ) ,
50
+
51
+ /** Only allow one panel open at a time */
52
+ exclusive : PropTypes . bool ,
40
53
41
54
/** Format to take up the width of it's container. */
42
55
fluid : PropTypes . bool ,
@@ -84,23 +97,33 @@ export default class Accordion extends Component {
84
97
// The default prop should always win on first render.
85
98
// This default check should then be removed.
86
99
if ( typeof this . props . defaultActiveIndex === 'undefined' ) {
87
- this . trySetState ( { activeIndex : - 1 } )
100
+ this . trySetState ( { activeIndex : this . props . exclusive ? - 1 : [ - 1 ] } )
88
101
}
89
102
}
90
103
91
104
handleTitleClick = ( e , index ) => {
92
- const { onTitleClick } = this . props
105
+ const { onTitleClick, exclusive } = this . props
93
106
const { activeIndex } = this . state
94
107
95
- this . trySetState ( {
96
- activeIndex : index === activeIndex ? - 1 : index ,
97
- } )
108
+ let newIndex
109
+ if ( exclusive ) {
110
+ newIndex = index === activeIndex ? - 1 : index
111
+ } else {
112
+ // check to see if index is in array, and remove it, if not then add it
113
+ newIndex = _ . includes ( activeIndex , index ) ? _ . without ( activeIndex , index ) : [ ...activeIndex , index ]
114
+ }
115
+ this . trySetState ( { activeIndex : newIndex } )
98
116
if ( onTitleClick ) onTitleClick ( e , index )
99
117
}
100
118
119
+ isIndexActive = ( index ) => {
120
+ const { exclusive } = this . props
121
+ const { activeIndex } = this . state
122
+ return exclusive ? activeIndex === index : _ . includes ( activeIndex , index )
123
+ }
124
+
101
125
renderChildren = ( ) => {
102
126
const { children } = this . props
103
- const { activeIndex } = this . state
104
127
let titleIndex = 0
105
128
let contentIndex = 0
106
129
@@ -110,7 +133,7 @@ export default class Accordion extends Component {
110
133
111
134
if ( isTitle ) {
112
135
const currentIndex = titleIndex
113
- const isActive = _ . has ( child , 'props.active' ) ? child . props . active : activeIndex === currentIndex
136
+ const isActive = _ . has ( child , 'props.active' ) ? child . props . active : this . isIndexActive ( titleIndex )
114
137
const onClick = ( e ) => {
115
138
this . handleTitleClick ( e , currentIndex )
116
139
if ( child . props . onClick ) child . props . onClick ( e , currentIndex )
@@ -120,8 +143,7 @@ export default class Accordion extends Component {
120
143
}
121
144
122
145
if ( isContent ) {
123
- const currentIndex = contentIndex
124
- const isActive = _ . has ( child , 'props.active' ) ? child . props . active : activeIndex === currentIndex
146
+ const isActive = _ . has ( child , 'props.active' ) ? child . props . active : this . isIndexActive ( contentIndex )
125
147
contentIndex ++
126
148
return cloneElement ( child , { ...child . props , active : isActive } )
127
149
}
@@ -132,12 +154,10 @@ export default class Accordion extends Component {
132
154
133
155
renderPanels = ( ) => {
134
156
const { panels } = this . props
135
- const { activeIndex } = this . state
136
157
const children = [ ]
137
158
138
159
_ . each ( panels , ( panel , i ) => {
139
- const isActive = _ . has ( panel , 'active' ) ? panel . active : activeIndex === i
140
-
160
+ const isActive = _ . has ( panel , 'active' ) ? panel . active : this . isIndexActive ( i )
141
161
const onClick = ( e ) => {
142
162
this . handleTitleClick ( e , i )
143
163
if ( panel . onClick ) panel . onClick ( e , i )
0 commit comments