From 5589a1b77b3693b114f31a81e53562fbf52e0444 Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Thu, 21 Nov 2019 06:28:24 -0800 Subject: [PATCH] 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 --- src/ui/components/HBox.tsx | 78 ++++++++++++++++++ src/ui/components/Info.tsx | 81 +++++++++++++++++++ src/ui/components/Input.tsx | 2 - src/ui/components/Labeled.tsx | 4 +- .../components/{BottomSpaced.tsx => VBox.tsx} | 6 +- src/ui/index.tsx | 4 +- src/utils/icons.js | 8 +- 7 files changed, 171 insertions(+), 12 deletions(-) create mode 100644 src/ui/components/HBox.tsx create mode 100644 src/ui/components/Info.tsx rename src/ui/components/{BottomSpaced.tsx => VBox.tsx} (77%) diff --git a/src/ui/components/HBox.tsx b/src/ui/components/HBox.tsx new file mode 100644 index 000000000..d0f18d870 --- /dev/null +++ b/src/ui/components/HBox.tsx @@ -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 ( + +
{left}
+
{right}
+
+ ); + case 'left': + return ( + +
{left}
+
{right}
+
+ ); + default: + return ( + +
{left}
+
{right}
+
+ ); + } +}; +HBox.defaultProps = { + grow: 'right', + childWidth: 0, +}; + +HBox.displayName = 'HBox'; + +export default HBox; diff --git a/src/ui/components/Info.tsx b/src/ui/components/Info.tsx new file mode 100644 index 000000000..71d2cc0b7 --- /dev/null +++ b/src/ui/components/Info.tsx @@ -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 ( + + + {type === 'spinning' ? ( + + ) : ( + + )} + <>{children} + + + ); +} + +Info.defaultProps = { + type: 'info', +}; + +export default Info; diff --git a/src/ui/components/Input.tsx b/src/ui/components/Input.tsx index 26882fb2c..00552b95c 100644 --- a/src/ui/components/Input.tsx +++ b/src/ui/components/Input.tsx @@ -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', diff --git a/src/ui/components/Labeled.tsx b/src/ui/components/Labeled.tsx index f6ac9a677..b7b0d1ee5 100644 --- a/src/ui/components/Labeled.tsx +++ b/src/ui/components/Labeled.tsx @@ -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}) => ( - {children} + {children} ); diff --git a/src/ui/components/BottomSpaced.tsx b/src/ui/components/VBox.tsx similarity index 77% rename from src/ui/components/BottomSpaced.tsx rename to src/ui/components/VBox.tsx index 95f2055ac..44e1f467e 100644 --- a/src/ui/components/BottomSpaced.tsx +++ b/src/ui/components/VBox.tsx @@ -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; diff --git a/src/ui/index.tsx b/src/ui/index.tsx index 93b140063..3e7a62f1e 100644 --- a/src/ui/index.tsx +++ b/src/ui/index.tsx @@ -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'; diff --git a/src/utils/icons.js b/src/utils/icons.js index 254c28e31..6f03bedf8 100644 --- a/src/utils/icons.js +++ b/src/utils/icons.js @@ -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],