@bigfishtv/cockpit
Version:
97 lines (88 loc) • 3.19 kB
JavaScript
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import classnames from 'classnames'
import PanelToolbar from './PanelToolbar'
import Icon from '../../Icon'
// we define this because react-docgen fails when defaultProp directly references an imported component
const DefaultPanelToolbar = props => <PanelToolbar {...props} />
/**
* Wraps children in a panel with PanelToolbar and PanelActions,
* can be controlled or uncontrolled in terms of collapsibility etc.
*/
export default class Panel extends Component {
static propTypes = {
/** String or react node */
title: PropTypes.node,
collapsible: PropTypes.bool,
removable: PropTypes.bool,
collapsed: PropTypes.bool,
/** Callback function for when panel is collapsed / uncollapsed */
onToggleCollapsed: PropTypes.func,
onRemove: PropTypes.func,
panelClassName: PropTypes.string,
/** Whether or not pannel is allowed to control its own collapse state */
uncontrolled: PropTypes.bool,
/** React component for panel toolbar */
PanelToolbar: PropTypes.func,
/** React component for panel actions */
PanelActions: PropTypes.func,
/** React component for panel drawer */
PanelDrawer: PropTypes.func,
/** Panel margin, true for default margin-medium otherwise 'xsmall', 'small' etc. */
margin: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
icon: PropTypes.string,
}
static defaultProps = {
collapsible: false,
removable: false,
collapsed: false,
onToggleCollapsed: () => {},
onRemove: () => {},
panelClassName: 'panel',
uncontrolled: false,
PanelToolbar: DefaultPanelToolbar,
}
constructor(props) {
super()
this.state = { collapsed: props.collapsed }
}
isCollapsed() {
return this.props.uncontrolled ? this.state.collapsed : this.props.collapsed
}
toggleCollapsed() {
const collapsed = this.isCollapsed()
if (this.props.uncontrolled) {
this.setState({ collapsed: !collapsed })
}
this.props.onToggleCollapsed(!collapsed)
}
render() {
const collapsed = this.isCollapsed()
const { PanelToolbar, PanelActions, PanelDrawer, icon, children, panelClassName, margin, ...props } = this.props
const marginClassName = margin === true ? 'margin-medium' : margin ? 'margin-' + margin : ''
return (
<div className={classnames(panelClassName, marginClassName)}>
{(this.props.collapsible || this.props.title || PanelToolbar != DefaultPanelToolbar) && (
<header className="panel-header">
{icon && <Icon name={icon} className="icon" size={18} />}
{this.props.title && (
<h3 className={classnames('panel-title', { truncate: typeof this.props.title !== 'object' })}>
{this.props.title}
</h3>
)}
{PanelToolbar && (
<PanelToolbar {...props} collapsed={collapsed} onToggleCollapsed={() => this.toggleCollapsed()} />
)}
</header>
)}
<div className={classnames('panel-content', { hide: collapsed })}>{children}</div>
{PanelActions && (
<footer className={classnames('panel-footer', { hide: collapsed })}>
<PanelActions {...props} />
</footer>
)}
{!collapsed && PanelDrawer && <PanelDrawer {...props} />}
</div>
)
}
}