/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import React from 'react'; import styled from '@emotion/styled'; import FlexColumn from './FlexColumn'; import FlexBox from './FlexBox'; import {colors} from './colors'; import Glyph from './Glyph'; const BORDER = '1px solid #dddfe2'; const Chevron = styled(Glyph)({ marginRight: 4, marginLeft: -2, marginBottom: 1, }); Chevron.displayName = 'Panel:Chevron'; /** * A Panel component. */ export default class Panel extends React.Component< { /** * Class name to customise styling. */ className?: string; /** * Whether this panel is floating from the rest of the UI. ie. if it has * margin and a border. */ floating?: boolean; /** * Whether the panel takes up all the space it can. Equivalent to the following CSS: * * height: 100%; * width: 100%; */ grow?: boolean; /** * Heading for this panel. If this is anything other than a string then no * padding is applied to the heading. */ heading: React.ReactNode; /** * Contents of the panel. */ children?: React.ReactNode; /** * Whether the panel header and body have padding. */ padded?: boolean; /** * Whether the panel can be collapsed. Defaults to true */ collapsable: boolean; /** * Initial state for panel if it is collapsable */ collapsed?: boolean; /** * Heading for this panel. If this is anything other than a string then no * padding is applied to the heading. */ accessory?: React.ReactNode; }, { collapsed: boolean; } > { static defaultProps: { floating: boolean; grow: boolean; collapsable: boolean; } = { grow: false, floating: true, collapsable: true, }; static PanelContainer = styled(FlexColumn)<{ floating?: boolean; collapsed?: boolean; }>(props => ({ flexShrink: 0, padding: props.floating ? 10 : 0, borderBottom: props.collapsed ? 'none' : BORDER, })); static PanelHeader = styled(FlexBox)<{floating?: boolean; padded?: boolean}>( props => ({ backgroundColor: '#f6f7f9', border: props.floating ? BORDER : 'none', borderBottom: BORDER, borderTopLeftRadius: 2, borderTopRightRadius: 2, justifyContent: 'space-between', lineHeight: '27px', fontWeight: 500, flexShrink: 0, padding: props.padded ? '0 10px' : 0, '&:not(:first-child)': { borderTop: BORDER, }, }), ); static PanelBody = styled(FlexColumn)<{floating?: boolean; padded?: boolean}>( props => ({ backgroundColor: '#fff', border: props.floating ? BORDER : 'none', borderBottomLeftRadius: 2, borderBottomRightRadius: 2, borderTop: 'none', flexGrow: 1, padding: props.padded ? 10 : 0, overflow: 'visible', }), ); state = { collapsed: this.props.collapsed == null ? false : this.props.collapsed, }; onClick = () => this.setState({collapsed: !this.state.collapsed}); render() { const { padded, children, className, grow, floating, heading, collapsable, accessory, } = this.props; const {collapsed} = this.state; return ( {collapsable && ( )} {heading} {accessory} {children == null || (collapsable && collapsed) ? null : ( {children} )} ); } }