Files
flipper/src/ui/components/Panel.tsx
Anton Nikolaev c0f902f81a Upgrade to emotion v10
Summary: React 16 is not compatible with react-emotion 9 (it prints warnings, see also https://github.com/emotion-js/emotion/issues/644). So we should upgrade to 10.

Reviewed By: mweststrate

Differential Revision: D18905889

fbshipit-source-id: c00d2dbbadb1c08544632cb9bfcd63f2b1818a25
2019-12-11 09:43:24 -08:00

181 lines
4.3 KiB
TypeScript

/**
* 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 (
<Panel.PanelContainer
className={className}
floating={floating}
grow={grow}
collapsed={collapsed}>
<Panel.PanelHeader
floating={floating}
padded={padded || typeof heading === 'string'}
onClick={this.onClick}>
<span>
{collapsable && (
<Chevron
color={colors.macOSTitleBarIcon}
name={collapsed ? 'triangle-right' : 'triangle-down'}
size={12}
/>
)}
{heading}
</span>
{accessory}
</Panel.PanelHeader>
{children == null || (collapsable && collapsed) ? null : (
<Panel.PanelBody
scrollable
grow={grow}
padded={padded == null ? true : padded}
floating={floating}>
{children}
</Panel.PanelBody>
)}
</Panel.PanelContainer>
);
}
}