From b8fcb2d46ba831cf40328cfc023d9c3b8cac5161 Mon Sep 17 00:00:00 2001 From: etoledom Date: Mon, 18 Feb 2019 20:18:11 +0100 Subject: [PATCH] Mobile: BottomSheet design tweaks v2 (#13855) * Mobile BottomSheet: Added the posibility of selecting the cell separator style. * Mobile BottomSheet: Increased space between top and table * Mobile BottomSheet: Truncating long values at the middle of the string. * Fix lint issues * Fix syntax error to pass CI * Fix lint issue * Mobile Picker: Tweak Android styles. * Mobile BottomSheet: Simplified Android cell styling. * Mobile: Fix swipe to dismiss on BottomSheet * Fix lint issues * Mobile BottomSheet: Fixes sensibility of pan vs tap gestures on swipe to dismiss. * Fix lint issues * Fixed failed tests * Mobile BottomSheet cell: Removed unnecessary variable init. * Fixed set state after component is unmounted * Revert "Fixed set state after component is unmounted" This reverts commit 787df7306ae32acd8b072fd09f475af55f1fea5f. --- .../block-library/src/image/edit.native.js | 7 +- .../mobile/bottom-sheet/cell.native.js | 184 +++++++++++------- .../bottom-sheet/cellStyles.android.scss | 7 + .../mobile/bottom-sheet/cellStyles.ios.scss | 7 + .../mobile/bottom-sheet/index.native.js | 23 ++- .../mobile/bottom-sheet/styles.native.scss | 12 +- .../components/mobile/picker/index.android.js | 4 +- .../mobile/picker/styles.android.scss | 10 - 8 files changed, 165 insertions(+), 89 deletions(-) create mode 100644 packages/editor/src/components/mobile/bottom-sheet/cellStyles.android.scss create mode 100644 packages/editor/src/components/mobile/bottom-sheet/cellStyles.ios.scss delete mode 100644 packages/editor/src/components/mobile/picker/styles.android.scss diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 7e2d097d2498d..73b3eba1ab5fa 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -193,9 +193,9 @@ class ImageEdit extends React.Component { getMediaOptionsItems() { return [ - { icon: 'wordpress-alt', value: MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_CHOOSE_FROM_DEVICE, label: __( 'Choose from device' ) }, + { icon: 'format-image', value: MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_CHOOSE_FROM_DEVICE, label: __( 'Choose from device' ) }, { icon: 'camera', value: MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_TAKE_PHOTO, label: __( 'Take a Photo' ) }, - { icon: 'format-image', value: MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_WORD_PRESS_LIBRARY, label: __( 'WordPress Media Library' ) }, + { icon: 'wordpress-alt', value: MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_WORD_PRESS_LIBRARY, label: __( 'WordPress Media Library' ) }, ]; } @@ -273,12 +273,13 @@ class ImageEdit extends React.Component { label={ __( 'Alt Text' ) } value={ alt || '' } valuePlaceholder={ __( 'None' ) } + separatorType={ 'fullWidth' } onChangeValue={ this.updateAlt } /> diff --git a/packages/editor/src/components/mobile/bottom-sheet/cell.native.js b/packages/editor/src/components/mobile/bottom-sheet/cell.native.js index 1ca7127416e2c..6ac26d2d00ff8 100644 --- a/packages/editor/src/components/mobile/bottom-sheet/cell.native.js +++ b/packages/editor/src/components/mobile/bottom-sheet/cell.native.js @@ -7,85 +7,131 @@ import { TouchableOpacity, Text, View, TextInput, I18nManager } from 'react-nati * WordPress dependencies */ import { Dashicon } from '@wordpress/components'; +import { Component } from '@wordpress/element'; /** * Internal dependencies */ import styles from './styles.scss'; +import platformStyles from './cellStyles.scss'; -export default function Cell( props ) { - const { - onPress, - label, - value, - valuePlaceholder = '', - drawSeparator = true, - icon, - labelStyle = {}, - valueStyle = {}, - onChangeValue, - children, - editable = true, - ...valueProps - } = props; +export default class Cell extends Component { + constructor() { + super( ...arguments ); + this.state = { + isEditingValue: false, + }; + } - const showValue = value !== undefined; - const isValueEditable = editable && onChangeValue !== undefined; - const defaultLabelStyle = showValue ? styles.cellLabel : styles.cellLabelCentered; - const separatorStyle = showValue ? styles.cellSeparator : styles.separator; - let valueTextInput; - - const onCellPress = () => { - if ( isValueEditable ) { - valueTextInput.focus(); - } else if ( onPress !== undefined ) { - onPress(); + componentDidUpdate() { + if ( this.state.isEditingValue ) { + this._valueTextInput.focus(); } - }; + } - const getValueComponent = () => { - const styleRTL = I18nManager.isRTL && styles.cellValueRTL; - const style = { ...styles.cellValue, ...valueStyle, ...styleRTL }; + render() { + const { + onPress, + label, + value, + valuePlaceholder = '', + icon, + labelStyle = {}, + valueStyle = {}, + onChangeValue, + children, + editable = true, + separatorType, + style = {}, + ...valueProps + } = this.props; - return isValueEditable ? ( - valueTextInput = c } - numberOfLines={ 1 } - style={ style } - value={ value } - placeholder={ valuePlaceholder } - placeholderTextColor={ '#87a6bc' } - onChangeText={ onChangeValue } - editable={ isValueEditable } - { ...valueProps } - /> - ) : ( - - { value } - - ); - }; + const showValue = value !== undefined; + const isValueEditable = editable && onChangeValue !== undefined; + const defaultLabelStyle = showValue || icon !== undefined ? styles.cellLabel : styles.cellLabelCentered; + const drawSeparator = ( separatorType && separatorType !== 'none' ) || separatorStyle === undefined; + + const onCellPress = () => { + if ( isValueEditable ) { + this.setState( { isEditingValue: true } ); + } else if ( onPress !== undefined ) { + onPress(); + } + }; + + const finishEditing = () => { + this.setState( { isEditingValue: false } ); + }; - return ( - - - - { icon && ( - - - - - ) } - - { label } - + const separatorStyle = () => { + const leftMarginStyle = { ...styles.cellSeparator, ...platformStyles.separatorMarginLeft }; + switch ( separatorType ) { + case 'leftMargin': + return leftMarginStyle; + case 'fullWidth': + return styles.separator; + case 'none': + return undefined; + case undefined: + return showValue ? leftMarginStyle : styles.separator; + } + }; + + const getValueComponent = () => { + const styleRTL = I18nManager.isRTL && styles.cellValueRTL; + const finalStyle = { ...styles.cellValue, ...valueStyle, ...styleRTL }; + + // To be able to show the `middle` ellipsizeMode on editable cells + // we show the TextInput just when the user wants to edit the value, + // and the Text component to display it. + // We also show the TextInput to display placeholder. + const shouldShowPlaceholder = isValueEditable && value === ''; + return this.state.isEditingValue || shouldShowPlaceholder ? ( + this._valueTextInput = c } + numberOfLines={ 1 } + style={ finalStyle } + value={ value } + placeholder={ valuePlaceholder } + placeholderTextColor={ '#87a6bc' } + onChangeText={ onChangeValue } + editable={ isValueEditable } + pointerEvents={ this.state.isEditingValue ? 'auto' : 'none' } + onBlur={ finishEditing } + { ...valueProps } + /> + ) : ( + + { value } + + ); + }; + + return ( + + + + { icon && ( + + + + + ) } + + { label } + + + { showValue && getValueComponent() } + { children } - { showValue && getValueComponent() } - { children } - - { drawSeparator && ( - - ) } - - ); + { drawSeparator && ( + + ) } + + ); + } } diff --git a/packages/editor/src/components/mobile/bottom-sheet/cellStyles.android.scss b/packages/editor/src/components/mobile/bottom-sheet/cellStyles.android.scss new file mode 100644 index 0000000000000..4feb815ba9bd0 --- /dev/null +++ b/packages/editor/src/components/mobile/bottom-sheet/cellStyles.android.scss @@ -0,0 +1,7 @@ +.labelIconSeparator { + width: 32px; +} + +.separatorMarginLeft { + margin-left: 56px; +} diff --git a/packages/editor/src/components/mobile/bottom-sheet/cellStyles.ios.scss b/packages/editor/src/components/mobile/bottom-sheet/cellStyles.ios.scss new file mode 100644 index 0000000000000..45b97213d1768 --- /dev/null +++ b/packages/editor/src/components/mobile/bottom-sheet/cellStyles.ios.scss @@ -0,0 +1,7 @@ +.labelIconSeparator { + width: 12px; +} + +.separatorMarginLeft { + margin-left: 36px; +} diff --git a/packages/editor/src/components/mobile/bottom-sheet/index.native.js b/packages/editor/src/components/mobile/bottom-sheet/index.native.js index c3cfb24686092..9815463dc19c5 100644 --- a/packages/editor/src/components/mobile/bottom-sheet/index.native.js +++ b/packages/editor/src/components/mobile/bottom-sheet/index.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { Text, View, KeyboardAvoidingView, Platform } from 'react-native'; +import { Text, View, KeyboardAvoidingView, Platform, PanResponder } from 'react-native'; import Modal from 'react-native-modal'; import SafeArea from 'react-native-safe-area'; @@ -50,7 +50,18 @@ class BottomSheet extends Component { } render() { - const { title = '', isVisible, leftButton, rightButton, hideHeader } = this.props; + const { title = '', isVisible, leftButton, rightButton, hideHeader, style = {} } = this.props; + + const panResponder = PanResponder.create( { + onMoveShouldSetPanResponder: ( evt, gestureState ) => { + // Activates swipe down over child Touchables if the swipe is long enough. + // With this we can adjust sensibility on the swipe vs tap gestures. + if ( gestureState.dy > 3 ) { + gestureState.dy = 0; + return true; + } + }, + } ); return ( - { hideHeader || ( + { hideHeader ? ( + + ) : ( diff --git a/packages/editor/src/components/mobile/bottom-sheet/styles.native.scss b/packages/editor/src/components/mobile/bottom-sheet/styles.native.scss index 6255ddfce859c..3f826b35b7dbb 100644 --- a/packages/editor/src/components/mobile/bottom-sheet/styles.native.scss +++ b/packages/editor/src/components/mobile/bottom-sheet/styles.native.scss @@ -8,7 +8,7 @@ .dragIndicator { background-color: $light-gray-400; height: 4px; - width: 10%; + width: 36px; margin: auto; border-radius: 2px; } @@ -19,6 +19,10 @@ width: 100%; } +.emptyHeaderSpace { + height: 14; +} + .content { padding: 6px 16px 0 16px; background-color: $white; @@ -33,6 +37,7 @@ justify-content: space-between; align-items: center; align-content: center; + min-height: 48; } .title { @@ -63,11 +68,14 @@ align-items: center; } +.clipToBounds { + overflow: hidden; +} + .cellSeparator { background-color: $light-gray-400; height: 1px; width: 100%; - margin-left: 36px; } .cellRowContainer { diff --git a/packages/editor/src/components/mobile/picker/index.android.js b/packages/editor/src/components/mobile/picker/index.android.js index 47dd8abb0dc35..a0b85caf96382 100644 --- a/packages/editor/src/components/mobile/picker/index.android.js +++ b/packages/editor/src/components/mobile/picker/index.android.js @@ -40,6 +40,7 @@ export default class Picker extends Component { @@ -48,13 +49,14 @@ export default class Picker extends Component { icon={ option.icon } key={ index } label={ option.label } + separatorType={ 'none' } onPress={ () => this.onCellPress( option.value ) } /> ) } { ! this.props.hideCancelButton && } diff --git a/packages/editor/src/components/mobile/picker/styles.android.scss b/packages/editor/src/components/mobile/picker/styles.android.scss deleted file mode 100644 index 56579b4916535..0000000000000 --- a/packages/editor/src/components/mobile/picker/styles.android.scss +++ /dev/null @@ -1,10 +0,0 @@ -.cellContainer { - min-height: 48; - align-items: flex-start; -} - -.cellLabel { - font-size: 17px; - color: #2e4453; - margin-right: 12px; -}