Accordion.js (2102B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ 4 5 import { cloneElement, Component } from "devtools/client/shared/vendor/react"; 6 import { 7 aside, 8 button, 9 div, 10 h2, 11 } from "devtools/client/shared/vendor/react-dom-factories"; 12 import PropTypes from "devtools/client/shared/vendor/react-prop-types"; 13 14 class Accordion extends Component { 15 static get propTypes() { 16 return { 17 items: PropTypes.array.isRequired, 18 }; 19 } 20 21 handleHeaderClick(i) { 22 const item = this.props.items[i]; 23 const opened = !item.opened; 24 item.opened = opened; 25 26 if (item.onToggle) { 27 item.onToggle(opened); 28 } 29 30 // We force an update because otherwise the accordion 31 // would not re-render 32 this.forceUpdate(); 33 } 34 35 renderContainer = (item, i) => { 36 const { opened } = item; 37 const contentElementId = `${item.id}-content`; 38 39 return aside( 40 { 41 className: item.className, 42 key: item.id, 43 "aria-labelledby": item.id, 44 role: item.role, 45 }, 46 h2( 47 { 48 className: "_header", 49 }, 50 button( 51 { 52 id: item.id, 53 className: "header-label", 54 "aria-expanded": `${opened ? "true" : "false"}`, 55 "aria-controls": opened ? contentElementId : undefined, 56 onClick: () => this.handleHeaderClick(i), 57 }, 58 item.header 59 ), 60 item.buttons 61 ? div( 62 { 63 className: "header-buttons", 64 }, 65 item.buttons 66 ) 67 : null 68 ), 69 opened && 70 div( 71 { 72 className: "_content", 73 id: contentElementId, 74 }, 75 cloneElement(item.component, item.componentProps || {}) 76 ) 77 ); 78 }; 79 render() { 80 return div( 81 { 82 className: "accordion", 83 }, 84 this.props.items.map(this.renderContainer) 85 ); 86 } 87 } 88 89 export default Accordion;