Introduce Info / VBox / HBox / Labeled for more consistent layouting
Summary:
This diff introduces a set of components:
VBox: use this to group things vertically, it little more than a container that fills the full width and adds bottom margin (see screenshot: creating distance between the boxes)
HBox: use to divide a space horizontal in two, and distribute it over two children, supports growing the right side, left side or both equally. In the image used to reserve the necessary width for the image, and give the remaining space to the text
Info: A component that shows a message, prestyled with one of the four types: info, error, warning, pending.
{F222993480}
Reviewed By: jknoxville
Differential Revision: D18595291
fbshipit-source-id: 1957db1b606b2e44e3104b10d32ad8ce75af6adc
This commit is contained in:
committed by
Facebook Github Bot
parent
c976e3ed63
commit
5589a1b77b
78
src/ui/components/HBox.tsx
Normal file
78
src/ui/components/HBox.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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 'react-emotion';
|
||||
import FlexRow from './FlexRow';
|
||||
|
||||
/**
|
||||
* Container that applies a standardized right margin for horizontal spacing
|
||||
* It takes two children, 'left' and 'right'. One is assumed to have a fixed (or minimum) size,
|
||||
* and the other will grow automatically
|
||||
*/
|
||||
const HBoxContainer = styled(FlexRow)({
|
||||
shrink: 0,
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
HBoxContainer.displayName = 'HBoxContainer';
|
||||
|
||||
const HBox: React.FC<{
|
||||
children: [] | [React.ReactNode] | [React.ReactNode, React.ReactNode];
|
||||
grow?: 'left' | 'right' | 'auto';
|
||||
childWidth?: number;
|
||||
}> = ({children, grow, childWidth}) => {
|
||||
if (children.length > 2) {
|
||||
throw new Error('HBox expects at most 2 children');
|
||||
}
|
||||
const left = children[0] || null;
|
||||
const right = children[1] || null;
|
||||
const fixedStyle = {
|
||||
width: childWidth ? `${childWidth}px` : 'auto',
|
||||
grow: 0,
|
||||
shrink: 0,
|
||||
};
|
||||
const growStyle = {
|
||||
width: '100%',
|
||||
shrink: 1,
|
||||
grow: 1,
|
||||
};
|
||||
|
||||
switch (grow) {
|
||||
case 'right':
|
||||
return (
|
||||
<HBoxContainer>
|
||||
<div style={{...fixedStyle, marginRight: 8}}>{left}</div>
|
||||
<div style={growStyle}>{right}</div>
|
||||
</HBoxContainer>
|
||||
);
|
||||
case 'left':
|
||||
return (
|
||||
<HBoxContainer>
|
||||
<div style={growStyle}>{left}</div>
|
||||
<div style={{...fixedStyle, marginLeft: 8}}>{right}</div>
|
||||
</HBoxContainer>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<HBoxContainer>
|
||||
<div style={growStyle}>{left}</div>
|
||||
<div style={{...growStyle, marginLeft: 8}}>{right}</div>
|
||||
</HBoxContainer>
|
||||
);
|
||||
}
|
||||
};
|
||||
HBox.defaultProps = {
|
||||
grow: 'right',
|
||||
childWidth: 0,
|
||||
};
|
||||
|
||||
HBox.displayName = 'HBox';
|
||||
|
||||
export default HBox;
|
||||
81
src/ui/components/Info.tsx
Normal file
81
src/ui/components/Info.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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 styled from 'react-emotion';
|
||||
import React from 'react';
|
||||
|
||||
import {colors} from './colors';
|
||||
import HBox from './HBox';
|
||||
|
||||
import Glyph from './Glyph';
|
||||
import LoadingIndicator from './LoadingIndicator';
|
||||
import FlexColumn from './FlexColumn';
|
||||
|
||||
export type InfoProps = {
|
||||
children: React.ReactNode;
|
||||
type: 'info' | 'spinning' | 'warning' | 'error';
|
||||
};
|
||||
|
||||
const icons = {
|
||||
info: 'info-circle',
|
||||
warning: 'caution-triangle',
|
||||
error: 'cross-circle',
|
||||
};
|
||||
|
||||
const color = {
|
||||
info: colors.aluminumDark3,
|
||||
warning: colors.yellow,
|
||||
error: colors.red,
|
||||
spinning: colors.light30,
|
||||
};
|
||||
|
||||
const bgColor = {
|
||||
info: 'transparent',
|
||||
warning: colors.yellowTint,
|
||||
error: colors.redTint,
|
||||
spinning: 'transparent',
|
||||
};
|
||||
|
||||
const InfoWrapper = styled(FlexColumn)(({type}: {type: InfoProps['type']}) => ({
|
||||
padding: 10,
|
||||
borderRadius: 4,
|
||||
color: color[type],
|
||||
border: `1px solid ${color[type]}`,
|
||||
background: bgColor[type],
|
||||
}));
|
||||
|
||||
/**
|
||||
* Shows an info box with some text and a symbol.
|
||||
* Supported types: info | spinning | warning | error
|
||||
*/
|
||||
function Info({type, children}: InfoProps) {
|
||||
return (
|
||||
<InfoWrapper type={type}>
|
||||
<HBox>
|
||||
{type === 'spinning' ? (
|
||||
<LoadingIndicator size={24} />
|
||||
) : (
|
||||
<Glyph
|
||||
name={icons[type]}
|
||||
color={color[type]}
|
||||
size={24}
|
||||
variant="filled"
|
||||
/>
|
||||
)}
|
||||
<>{children}</>
|
||||
</HBox>
|
||||
</InfoWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Info.defaultProps = {
|
||||
type: 'info',
|
||||
};
|
||||
|
||||
export default Info;
|
||||
@@ -17,8 +17,6 @@ export const inputStyle = (compact: boolean) => ({
|
||||
fontSize: '1em',
|
||||
height: compact ? '17px' : '28px',
|
||||
lineHeight: compact ? '17px' : '28px',
|
||||
marginRight: 5,
|
||||
|
||||
'&:disabled': {
|
||||
backgroundColor: '#ddd',
|
||||
borderColor: '#ccc',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import React from 'react';
|
||||
import FlexColumn from './FlexColumn';
|
||||
import Label from './Label';
|
||||
import BottomSpaced from './BottomSpaced';
|
||||
import VBox from './VBox';
|
||||
|
||||
/**
|
||||
* Vertically arranged section that starts with a label and includes standard margins
|
||||
@@ -18,7 +18,7 @@ import BottomSpaced from './BottomSpaced';
|
||||
const Labeled: React.FC<{title: string}> = ({title, children}) => (
|
||||
<FlexColumn>
|
||||
<Label style={{marginBottom: 6}}>{title}</Label>
|
||||
<BottomSpaced>{children}</BottomSpaced>
|
||||
<VBox>{children}</VBox>
|
||||
</FlexColumn>
|
||||
);
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ import FlexColumn from './FlexColumn';
|
||||
/**
|
||||
* Container that applies a standardized bottom margin for vertical spacing
|
||||
*/
|
||||
const BottomSpaced = styled(FlexColumn)({
|
||||
const VBox = styled(FlexColumn)({
|
||||
marginBottom: 10,
|
||||
});
|
||||
BottomSpaced.displayName = 'BottomSpaced';
|
||||
VBox.displayName = 'VBox';
|
||||
|
||||
export default BottomSpaced;
|
||||
export default VBox;
|
||||
@@ -161,8 +161,10 @@ export {default as Sheet} from './components/Sheet';
|
||||
export {StarButton} from './components/StarButton';
|
||||
export {Markdown} from './components/Markdown';
|
||||
|
||||
export {default as BottomSpaced} from './components/BottomSpaced';
|
||||
export {default as VBox} from './components/VBox';
|
||||
export {default as HBox} from './components/HBox';
|
||||
export {default as SmallText} from './components/SmallText';
|
||||
export {default as Labeled} from './components/Labeled';
|
||||
export {default as RoundedSection} from './components/RoundedSection';
|
||||
export {default as CenteredView} from './components/CenteredView';
|
||||
export {default as Info} from './components/Info';
|
||||
|
||||
@@ -22,15 +22,15 @@ const ICONS = {
|
||||
'bell-null-outline': [12, 24],
|
||||
'bell-null': [12],
|
||||
'caution-octagon': [16],
|
||||
'caution-triangle': [16],
|
||||
'caution-triangle': [16, 24],
|
||||
'chevron-down-outline': [10],
|
||||
'chevron-down': [8, 12],
|
||||
'chevron-up': [8, 12],
|
||||
'chevron-right': [8, 16],
|
||||
'cross-circle': [16],
|
||||
'chevron-right': [8, 12, 16],
|
||||
'cross-circle': [16, 24],
|
||||
'dots-3-circle-outline': [16],
|
||||
'flash-default': [12],
|
||||
'info-circle': [16],
|
||||
'info-circle': [16, 24],
|
||||
'magic-wand': [20],
|
||||
'magnifying-glass': [16, 20],
|
||||
'minus-circle': [12],
|
||||
|
||||
Reference in New Issue
Block a user