From 7c361b2be3b63e6c6598df9b91f9de65b1f40266 Mon Sep 17 00:00:00 2001 From: Max Goodman Date: Mon, 12 Sep 2016 19:13:02 -0700 Subject: [PATCH 01/10] Add input components to dumb map --- shared/common-adapters/dumb.desktop.js | 90 +++++++++++++++++++++- shared/common-adapters/small-input.js.flow | 2 +- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/shared/common-adapters/dumb.desktop.js b/shared/common-adapters/dumb.desktop.js index 2b38f71a32bd..4563f34b82b8 100644 --- a/shared/common-adapters/dumb.desktop.js +++ b/shared/common-adapters/dumb.desktop.js @@ -3,7 +3,7 @@ import React, {Component} from 'react' import _ from 'lodash' import type {DumbComponentMap} from '../constants/types/more' import type {IconType} from './icon.constants' -import {Avatar, Button, Box, Checkbox, ChoiceList, Icon, ListItem, PopupMenu, StandardScreen, TabBar, Text} from './index' +import {Avatar, Button, Box, Checkbox, ChoiceList, Icon, Input, SmallInput, ListItem, PopupMenu, StandardScreen, TabBar, Text} from './index' import {TabBarButton, TabBarItem} from './tab-bar' import {globalStyles, globalColors} from '../styles' import {iconMeta} from './icon.constants' @@ -65,6 +65,92 @@ const iconMap: DumbComponentMap = { }, } +const inputMap: DumbComponentMap = { + component: Input, + mocks: { + 'Default Empty': {}, + 'Default Filled': { + value: 'Hello, World!', + }, + 'Hint Empty': { + hintText: 'Hello...', + }, + 'Floating Label Empty': { + floatingLabelText: 'Hello...', + }, + 'Floating Label Filled': { + floatingLabelText: 'Hello...', + value: 'Hello, World!', + }, + 'Floating Label Error': { + floatingLabelText: 'Hello...', + value: 'Hello, Worl', + errorText: 'Check your spelling', + }, + 'Floating Label Hint Empty': { + hintText: 'Hello!', + floatingLabelText: 'Hello...', + }, + 'Hint Multiline Empty': { + hintText: 'This is a very long hint that will hopefully wrap to two lines', + multiline: true, + }, + 'Floating Label Multiline Empty': { + floatingLabelText: 'Hello...', + multiline: true, + }, + 'Floating Label Multiline Filled': { + floatingLabelText: 'Hello...', + multiline: true, + value: 'Hello, World!', + }, + 'Floating Label Multiline Filled Long': { + floatingLabelText: 'Hello...', + multiline: true, + value: 'Hello,\nMy name is Max\nHow are you?', + }, + 'Small Empty': { + small: true, + }, + 'Small Filled': { + small: true, + value: 'Hello, World!', + }, + 'Small Hint Empty': { + small: true, + hintText: 'Hello...', + }, + }, +} + +const smallInputMap: DumbComponentMap = { + component: SmallInput, + mocks: { + 'Default Empty': { + label: 'Greet:', + hintText: 'Hello...', + value: null, + }, + 'Default Filled': { + label: 'Greet:', + hintText: 'Hello...', + value: 'Hello, World!', + }, + 'Error Empty': { + label: 'Greet:', + hintText: 'Hello...', + errorState: true, + value: null, + }, + 'Error Filled': { + label: 'Greet:', + hintText: 'Hello...', + value: 'Hello, World!', + errorState: true, + }, + }, +} + const tabBarCustomButtons = selectedIndex => { const IconButton = ({selected, icon, badgeNumber, label}: any) => const AvatarButton = ({selected, avatar, badgeNumber}: any) => @@ -246,6 +332,8 @@ export default { Checkbox: checkboxMap, ChoiceList: choiceListMap, Icon: iconMap, + Input: inputMap, + SmallInput: smallInputMap, ListItem: listItemMap, PopupMenu: popupMenuMap, StandardScreen: standardScreenMap, diff --git a/shared/common-adapters/small-input.js.flow b/shared/common-adapters/small-input.js.flow index c1a02408f6e1..f30999081508 100644 --- a/shared/common-adapters/small-input.js.flow +++ b/shared/common-adapters/small-input.js.flow @@ -6,7 +6,7 @@ export type SmallInputProps = { hintText: string, label: string, value: ?string, - onChange: (next: string) => void, + onChange?: (next: string) => void, errorState?: boolean, style?: Object, autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters', // Native only From ff080cfdd516dc07ba1b079500e4ddefef0d5fcf Mon Sep 17 00:00:00 2001 From: Max Goodman Date: Fri, 9 Sep 2016 18:27:48 -0700 Subject: [PATCH 02/10] Use material-ui multiline TextField for multiline inputs Also clean up alignment of floating labels / hints / text. --- shared/common-adapters/input.desktop.js | 41 +++----- .../multi-line-input.desktop.js | 99 ------------------- .../common-adapters/multi-line-input.js.flow | 14 --- shared/common-adapters/small-input.desktop.js | 4 +- shared/menubar/user-add.desktop.js | 4 +- shared/pinentry/index.render.desktop.js | 2 - 6 files changed, 20 insertions(+), 144 deletions(-) delete mode 100644 shared/common-adapters/multi-line-input.desktop.js delete mode 100644 shared/common-adapters/multi-line-input.js.flow diff --git a/shared/common-adapters/input.desktop.js b/shared/common-adapters/input.desktop.js index 85ef4225901a..78699ae79b6a 100644 --- a/shared/common-adapters/input.desktop.js +++ b/shared/common-adapters/input.desktop.js @@ -1,5 +1,4 @@ // @flow -import MultiLineInput from './multi-line-input.desktop' import React, {Component} from 'react' import type {Props} from './input' import {TextField} from 'material-ui' @@ -65,31 +64,23 @@ class Input extends Component { } render () { - if (this.props.multiline) { - return ( - this.onChange(event)} - onEnterKeyDown={this.props.onEnterKeyDown} - hintText={this.props.hintText} - style={this.props.style} /> - ) - } - const style = this.props.small ? styles.containerSmall : styles.container const textStyle = this.props.small ? styles.inputSmall : styles.input + const textHeight = this.props.small ? 32 : (this.props.floatingLabelText ? 79 : 50) + const hintBottom = this.props.small ? 11 : (this.props.multiline ? 16 : 14) // HACK: We can't reset the text area style, so we need to counteract it by moving the wrapper up const multilineStyleFix = { height: 'auto', position: 'relative', // Other HACK: having a floating label affects position, but only in multiline - bottom: (this.props.floatingLabelText ? 30 : 5), - marginTop: 6, + bottom: (this.props.floatingLabelText ? 30 : 6), + // tweak distance between entered text and floating label to match single-line + marginTop: 1, + // tweak distance between entered text and underline to match single-line + marginBottom: -2, } - const inputStyle = this.props.multiline ? multilineStyleFix : {height: 'auto'} + const inputStyle = this.props.multiline ? multilineStyleFix : {height: 'auto', top: 3} const alignStyle = this.props.style && this.props.style.textAlign ? {textAlign: this.props.style.textAlign} : {textAlign: 'center'} const passwordVisible = this.props.type === 'passwordVisible' @@ -106,10 +97,12 @@ class Input extends Component { floatingLabelStyle={styles.floatingLabelStyle} floatingLabelText={this.props.small ? undefined : this.props.floatingLabelText} fullWidth={true} - hintStyle={{...styles.hintStyle, ...(this.props.multiline ? {textAlign: 'center'} : {top: 3, bottom: 'auto'}), ...this.props.hintStyle}} + hintStyle={{bottom: hintBottom, ...styles.hintStyle, ...this.props.hintStyle}} hintText={this.props.hintText} - inputStyle={{...(this.props.small ? {} : {marginTop: 6}), ...inputStyle, ...alignStyle, ...this.props.inputStyle}} + inputStyle={{...(this.props.small ? {} : {marginTop: 4}), ...inputStyle, ...alignStyle, ...this.props.inputStyle}} + textareaStyle={{...alignStyle, overflow: 'overlay'}} name='name' + multiLine={this.props.multiline} onBlur={() => this.setState({focused: false})} onChange={event => this.onChange(event)} onFocus={() => this.setState({focused: true})} @@ -117,7 +110,7 @@ class Input extends Component { ref={textField => (this._textField = textField)} rows={this.props.rows} rowsMax={this.props.rowsMax} - style={{...textStyle, ...globalStyles.flexBoxColumn, ...this.props.textStyle}} + style={{...textStyle, height: textHeight, transition: 'none', ...globalStyles.flexBoxColumn, ...this.props.textStyle}} type={password ? 'password' : 'text'} underlineFocusStyle={{...styles.underlineFocusStyle, ...this.props.underlineStyle}} underlineShow={this.props.underlineShow} @@ -139,13 +132,11 @@ export const styles = { }, input: { ...specialStyles.textInput, - height: 80, }, inputSmall: { ...TextStyles.textBody, ...TextStyles.textSmallMixin, - height: 40, - lineHeight: '11px', + lineHeight: '16px', }, underlineFocusStyle: { marginTop: 4, @@ -173,7 +164,6 @@ export const styles = { color: globalColors.black_10, width: '100%', textAlign: 'center', - marginTop: -3, }, floatingLabelStyle: { ...globalStyles.fontSemibold, @@ -182,6 +172,7 @@ export const styles = { fontSize: 24, lineHeight: '29px', position: 'inherit', + top: 36, transform: 'scale(1) translate3d(0, 0, 0)', transition: 'color 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms', }, @@ -192,7 +183,7 @@ export const styles = { fontSize: 14, lineHeight: '29px', position: 'inherit', - transform: 'perspective(1px) scale(1) translate3d(2px, -29px, 0)', + transform: 'perspective(1px) scale(1) translate3d(2px, -26px, 0)', transformOrigin: 'center top', }, } diff --git a/shared/common-adapters/multi-line-input.desktop.js b/shared/common-adapters/multi-line-input.desktop.js deleted file mode 100644 index 3e087f1cca2e..000000000000 --- a/shared/common-adapters/multi-line-input.desktop.js +++ /dev/null @@ -1,99 +0,0 @@ -// @flow -import React, {Component} from 'react' -import Text from './text' -import type {Props} from './multi-line-input' -import {globalStyles, globalColors, transition} from '../styles' - -type State = {textContent: string} - -class MultiLineInput extends Component { - state: State; - - constructor (props: Props) { - super(props) - this.state = {textContent: ''} - } - - _handleKeyUp (e: SyntheticEvent) { - // $FlowIssue - this.setState({textContent: e.target.textContent}) - // This is a content editable text, not input. - // People using onChange may expect text to be in target.value - // but on content editable it is in target.textContent - // Copy this to provide a uniform api - // $FlowIssue - e.target.value = e.target.textContent - this.props.onChange && this.props.onChange(e) - } - - _handleKeyDown (e: any) { - // Check enter - if (e.keyCode === 13 && this.props.onEnterKeyDown) { - this.props.onEnterKeyDown(e) - } - } - - _focusTextBox () { - if (this.refs && this.refs.textBox) { - this.refs.textBox.focus() - } - } - - render () { - return ( -
- 0 ? {opacity: 0} : {opacity: 1})}} - onClick={() => this._focusTextBox()} type='HeaderBig'>{this.props.hintText} - this._handleKeyUp(e)} - onKeyDown={e => this._handleKeyDown(e)} - type='HeaderBig'>type - {this.props.errorText && {this.props.errorText}} -
-
- ) - } -} - -const containerStyle = { - ...globalStyles.flexBoxColumn, - position: 'relative', - justifyContent: 'flex-end', -} - -const hintTextStyle = { - ...transition('opacity'), - cursor: 'text', - color: globalColors.black_10, - textAlign: 'center', -} - -const inputStyle = { - position: 'absolute', - bottom: 2, // To align it perfectly with the hintText - left: 0, - right: 0, - outline: 'none', - textAlign: 'center', -} - -const underlineStyle = { - border: 'solid', - borderWidth: 1, - borderColor: 'rgba(0, 0, 0, 0.08)', -} - -const errorTextStyle = { - position: 'absolute', - bottom: -18, - left: 0, - right: 0, - outline: 'none', - textAlign: 'center', -} - -export default MultiLineInput diff --git a/shared/common-adapters/multi-line-input.js.flow b/shared/common-adapters/multi-line-input.js.flow deleted file mode 100644 index 089031cd04da..000000000000 --- a/shared/common-adapters/multi-line-input.js.flow +++ /dev/null @@ -1,14 +0,0 @@ -// @flow -import {Component} from 'react' - -export type Props = $Shape<{ - autoFocus?: bool, - errorText?: ?string, - errorStyle? : Object, - onChange?: (event: Object) => void, - onEnterKeyDown?: (event: Object) => void, - hintText: ?string, - style?: Object -}> - -declare export default class Input extends Component {} diff --git a/shared/common-adapters/small-input.desktop.js b/shared/common-adapters/small-input.desktop.js index d943b5db280f..fb61a24ed674 100644 --- a/shared/common-adapters/small-input.desktop.js +++ b/shared/common-adapters/small-input.desktop.js @@ -31,7 +31,7 @@ const styleContainer = { const styleLabel = (hasError: boolean) => ({ position: 'absolute', - bottom: 6, + bottom: 7, left: 2, color: (hasError ? globalColors.red : globalColors.blue), }) @@ -45,7 +45,7 @@ const styleInputHint = { textAlign: 'left', marginLeft: 60, marginTop: 6, - top: undefined, + bottom: undefined, } const styleInputUser = { diff --git a/shared/menubar/user-add.desktop.js b/shared/menubar/user-add.desktop.js index 4428571e32a9..e6260b2f98ef 100644 --- a/shared/menubar/user-add.desktop.js +++ b/shared/menubar/user-add.desktop.js @@ -115,7 +115,7 @@ const stylesInputContainer = { const stylesInput = { flex: 1, - height: 20, + marginTop: 12, } const stylesInputInput = { @@ -128,7 +128,7 @@ const stylesInputHint = { ...globalStyles.fontSemibold, fontSize: 14, textAlign: 'left', - marginTop: 1, + marginBottom: 2, } const stylesInputUnderline = { diff --git a/shared/pinentry/index.render.desktop.js b/shared/pinentry/index.render.desktop.js index 3dc232f40025..f9634163849a 100644 --- a/shared/pinentry/index.render.desktop.js +++ b/shared/pinentry/index.render.desktop.js @@ -71,8 +71,6 @@ export default class PinentryRender extends Component Date: Fri, 9 Sep 2016 18:27:48 -0700 Subject: [PATCH 03/10] Use multiline text input for profile bio --- shared/profile/edit-profile/render.desktop.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/profile/edit-profile/render.desktop.js b/shared/profile/edit-profile/render.desktop.js index 3d2ed90189f5..f8983f7d54af 100644 --- a/shared/profile/edit-profile/render.desktop.js +++ b/shared/profile/edit-profile/render.desktop.js @@ -27,6 +27,8 @@ class Render extends Component { style={styleEditProfile} floatingLabelText='Bio' value={this.props.bio} + multiline={true} + rowsMax={4} errorText={this.props.bioLengthLeft <= 5 ? this.props.bioLengthLeft + ' characters left.' : ''} onEnterKeyDown={this.props.onSubmit} onChangeText={bio => this.props.onBioChange(bio)} /> From cf6a46dfbbf8dcf80d9fa94538cb9f035e2da461 Mon Sep 17 00:00:00 2001 From: Max Goodman Date: Mon, 12 Sep 2016 18:38:15 -0700 Subject: [PATCH 04/10] Hide spurious scrollbar in menubar folder input area --- shared/menubar/user-add.desktop.js | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/menubar/user-add.desktop.js b/shared/menubar/user-add.desktop.js index e6260b2f98ef..8a1c2c2dc0d6 100644 --- a/shared/menubar/user-add.desktop.js +++ b/shared/menubar/user-add.desktop.js @@ -111,6 +111,7 @@ const stylesInputContainer = { alignItems: 'center', flex: 1, height: 40, + overflow: 'hidden', } const stylesInput = { From aaaf6622d2848dc9ae11c618c03a7ba7c71c41c9 Mon Sep 17 00:00:00 2001 From: Max Goodman Date: Mon, 12 Sep 2016 19:16:33 -0700 Subject: [PATCH 05/10] Constrain input hints to a single line Due to the internals of the material-ui TextField, it is difficult for us to expand the height of an input field to contain the hint. As a quick and dirty workaround, let's compromise by clipping the hint to the size of the input. --- shared/common-adapters/input.desktop.js | 3 +++ shared/login/register/paper-key/index.render.desktop.js | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/shared/common-adapters/input.desktop.js b/shared/common-adapters/input.desktop.js index 78699ae79b6a..5cbc7fffd92f 100644 --- a/shared/common-adapters/input.desktop.js +++ b/shared/common-adapters/input.desktop.js @@ -164,6 +164,9 @@ export const styles = { color: globalColors.black_10, width: '100%', textAlign: 'center', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', }, floatingLabelStyle: { ...globalStyles.fontSemibold, diff --git a/shared/login/register/paper-key/index.render.desktop.js b/shared/login/register/paper-key/index.render.desktop.js index 7c69ec5d09ea..1d60c6542f0c 100644 --- a/shared/login/register/paper-key/index.render.desktop.js +++ b/shared/login/register/paper-key/index.render.desktop.js @@ -44,7 +44,6 @@ const styles = { }, icon: { marginTop: 45, - marginBottom: 65, }, input: { alignSelf: 'stretch', From 8b5cbb84d70414fc0e57e6b3532e271bf7e46463 Mon Sep 17 00:00:00 2001 From: Max Goodman Date: Fri, 9 Sep 2016 18:28:38 -0700 Subject: [PATCH 06/10] Remove submit on enter press when editing bio --- shared/profile/edit-profile/render.desktop.js | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/profile/edit-profile/render.desktop.js b/shared/profile/edit-profile/render.desktop.js index f8983f7d54af..05fd37a42f94 100644 --- a/shared/profile/edit-profile/render.desktop.js +++ b/shared/profile/edit-profile/render.desktop.js @@ -30,7 +30,6 @@ class Render extends Component { multiline={true} rowsMax={4} errorText={this.props.bioLengthLeft <= 5 ? this.props.bioLengthLeft + ' characters left.' : ''} - onEnterKeyDown={this.props.onSubmit} onChangeText={bio => this.props.onBioChange(bio)} />