Files
flipper/src/ui/components/Sidebar.js
Daniel Büchele 726966fdc0 convert to emotion
Summary:
My benchmarks have shown react-emotion to be faster than the current implementation of `styled`. For this reason, I am converting all styling to [emotion](https://emotion.sh).

Benchmark results:
{F136839093}

The syntax is very similar between the two libraries. The main difference is that emotion only allows a single function for the whole style attribute, whereas the old implementation had functions for every style-attirbute.

Before:
```
{
  color: props => props.color,
  fontSize: props => props.size,
}
```

After:
```
props => ({
  color: props.color,
  fontSize: props.size,
})
```

Reviewed By: jknoxville

Differential Revision: D9479893

fbshipit-source-id: 2c39e4618f7e52ceacb67bbec8ae26114025723f
2018-08-23 09:42:18 -07:00

172 lines
4.5 KiB
JavaScript

/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
import Interactive from './Interactive.js';
import FlexColumn from './FlexColumn.js';
import {colors} from './colors';
import {Component} from 'react';
import styled from '../styled/index.js';
const SidebarInteractiveContainer = styled(Interactive)({
flex: 'none',
});
type SidebarPosition = 'left' | 'top' | 'right' | 'bottom';
const SidebarContainer = styled(FlexColumn)(props => ({
backgroundColor: props.backgroundColor || colors.macOSTitleBarBackgroundBlur,
borderLeft: props.position === 'right' ? '1px solid #b3b3b3' : 'none',
borderTop: props.position === 'bottom' ? '1px solid #b3b3b3' : 'none',
borderRight: props.position === 'left' ? '1px solid #b3b3b3' : 'none',
borderBottom: props.position === 'top' ? '1px solid #b3b3b3' : 'none',
height: '100%',
overflowX: 'hidden',
overflowY: 'auto',
textOverflow: props.overflow ? 'ellipsis' : 'auto',
whiteSpace: props.overflow ? 'nowrap' : 'normal',
}));
type SidebarProps = {
/**
* Position of the sidebar.
*/
position: SidebarPosition,
/**
* Default width of the sidebar. Only used for left/right sidebars.
*/
width?: number,
/**
* Minimum sidebar width. Only used for left/right sidebars.
*/
minWidth?: number,
/**
* Maximum sidebar width. Only used for left/right sidebars.
*/
maxWidth?: number,
/**
* Default height of the sidebar.
*/
height?: number,
/**
* Minimum sidebar height. Only used for top/bottom sidebars.
*/
minHeight?: number,
/**
* Maximum sidebar height. Only used for top/bottom sidebars.
*/
maxHeight?: number,
/**
* Background color.
*/
backgroundColor?: string,
/**
* Callback when the sidebar size ahs changed.
*/
onResize?: (width: number, height: number) => void,
/**
* Contents of the sidebar.
*/
children?: React$Node,
/**
* Class name to customise styling.
*/
className?: string,
};
type SidebarState = {|
width?: number,
height?: number,
userChange: boolean,
|};
/**
* A resizable sidebar.
*/
export default class Sidebar extends Component<SidebarProps, SidebarState> {
constructor(props: SidebarProps, context: Object) {
super(props, context);
this.state = {
userChange: false,
width: props.width,
height: props.height,
};
}
static defaultProps = {
position: 'left',
};
componentWillReceiveProps(nextProps: SidebarProps) {
if (!this.state.userChange) {
this.setState({width: nextProps.width, height: nextProps.height});
}
}
onResize = (width: number, height: number) => {
const {onResize} = this.props;
if (onResize) {
onResize(width, height);
} else {
this.setState({userChange: true, width, height});
}
};
render() {
const {backgroundColor, onResize, position, children} = this.props;
let height, minHeight, maxHeight, width, minWidth, maxWidth;
const resizable: {[key: string]: boolean} = {};
if (position === 'left') {
resizable.right = true;
({width, minWidth, maxWidth} = this.props);
} else if (position === 'top') {
resizable.bottom = true;
({height, minHeight, maxHeight} = this.props);
} else if (position === 'right') {
resizable.left = true;
({width, minWidth, maxWidth} = this.props);
} else if (position === 'bottom') {
resizable.top = true;
({height, minHeight, maxHeight} = this.props);
}
const horizontal = position === 'left' || position === 'right';
if (horizontal) {
width = width == null ? 200 : width;
minWidth = minWidth == null ? 100 : minWidth;
maxWidth = maxWidth == null ? 600 : maxWidth;
} else {
height = height == null ? 200 : height;
minHeight = minHeight == null ? 100 : minHeight;
maxHeight = maxHeight == null ? 600 : maxHeight;
}
return (
<SidebarInteractiveContainer
className={this.props.className}
minWidth={minWidth}
maxWidth={maxWidth}
width={horizontal ? (onResize ? width : this.state.width) : undefined}
minHeight={minHeight}
maxHeight={maxHeight}
height={
!horizontal ? (onResize ? height : this.state.height) : undefined
}
resizable={resizable}
onResize={this.onResize}>
<SidebarContainer position={position} backgroundColor={backgroundColor}>
{children}
</SidebarContainer>
</SidebarInteractiveContainer>
);
}
}