2019-04-28 02:43:38 +02:00
|
|
|
/**
|
|
|
|
* React component to create an accordion element
|
|
|
|
*/
|
|
|
|
import * as React from "react";
|
|
|
|
|
|
|
|
type IProps = {
|
2019-05-16 08:05:36 +02:00
|
|
|
headerClass?: string; // Override default class
|
2019-04-28 02:43:38 +02:00
|
|
|
headerContent: React.ReactElement;
|
2019-05-16 08:05:36 +02:00
|
|
|
panelClass?: string; // Override default class
|
2019-04-28 02:43:38 +02:00
|
|
|
panelContent: React.ReactElement;
|
2019-04-30 05:54:20 +02:00
|
|
|
panelInitiallyOpened?: boolean;
|
2019-05-17 22:41:16 +02:00
|
|
|
style?: string;
|
2019-04-28 02:43:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type IState = {
|
|
|
|
panelOpened: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export class Accordion extends React.Component<IProps, IState> {
|
|
|
|
constructor(props: IProps) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.handleHeaderClick = this.handleHeaderClick.bind(this);
|
|
|
|
|
|
|
|
this.state = {
|
2021-06-16 06:28:20 +02:00
|
|
|
panelOpened: props.panelInitiallyOpened ? props.panelInitiallyOpened : false,
|
2019-04-28 02:43:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-16 08:10:47 +02:00
|
|
|
handleHeaderClick(): void {
|
2021-06-16 06:28:20 +02:00
|
|
|
this.setState({
|
|
|
|
panelOpened: !this.state.panelOpened,
|
|
|
|
});
|
2019-04-28 02:43:38 +02:00
|
|
|
}
|
|
|
|
|
2021-05-01 09:17:31 +02:00
|
|
|
render(): React.ReactNode {
|
2019-05-16 08:05:36 +02:00
|
|
|
let className = "accordion-header";
|
|
|
|
if (typeof this.props.headerClass === "string") {
|
|
|
|
className = this.props.headerClass;
|
|
|
|
}
|
|
|
|
|
2021-06-16 06:28:20 +02:00
|
|
|
if(this.state.panelOpened) className += " active"
|
|
|
|
|
2019-04-28 02:43:38 +02:00
|
|
|
return (
|
2019-05-15 09:15:07 +02:00
|
|
|
<>
|
2019-05-16 08:05:36 +02:00
|
|
|
<button className={className} onClick={this.handleHeaderClick}>
|
2019-05-15 09:15:07 +02:00
|
|
|
{this.props.headerContent}
|
|
|
|
</button>
|
2019-05-16 08:05:36 +02:00
|
|
|
<AccordionPanel
|
|
|
|
opened={this.state.panelOpened}
|
|
|
|
panelClass={this.props.panelClass}
|
|
|
|
panelContent={this.props.panelContent}
|
|
|
|
/>
|
2019-05-15 09:15:07 +02:00
|
|
|
</>
|
2019-04-28 02:43:38 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type IPanelProps = {
|
|
|
|
opened: boolean;
|
2019-05-16 08:05:36 +02:00
|
|
|
panelClass?: string; // Override default class
|
2019-04-28 02:43:38 +02:00
|
|
|
panelContent: React.ReactElement;
|
|
|
|
}
|
|
|
|
|
|
|
|
class AccordionPanel extends React.Component<IPanelProps, any> {
|
2021-05-01 09:17:31 +02:00
|
|
|
shouldComponentUpdate(nextProps: IPanelProps): boolean {
|
2019-04-28 02:43:38 +02:00
|
|
|
return this.props.opened || nextProps.opened;
|
|
|
|
}
|
|
|
|
|
2021-05-01 09:17:31 +02:00
|
|
|
render(): React.ReactNode {
|
2019-05-16 08:05:36 +02:00
|
|
|
let className = "accordion-panel"
|
|
|
|
if (typeof this.props.panelClass === "string") {
|
|
|
|
className = this.props.panelClass;
|
|
|
|
}
|
|
|
|
|
2021-08-27 21:26:12 +02:00
|
|
|
if(!this.props.opened) return (<></>);
|
|
|
|
|
2021-06-16 06:28:20 +02:00
|
|
|
|
2019-04-28 02:43:38 +02:00
|
|
|
return (
|
2021-08-27 21:26:12 +02:00
|
|
|
<div className={className} style={{display: "block"}}>
|
2019-04-28 02:43:38 +02:00
|
|
|
{this.props.panelContent}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|