Repository: callstack/react-native-paper
Pull request #817 (2019-02-06 12:17:37)

fix: optimize Avatar.Icon look
<!-- Please provide enough information so that others can review your pull request. -->
<!-- Keep pull requests small and focused on a single change. -->

### Motivation

The icons in `Avatar.Icon` look quite small if the size is high.

### Test plan

Before:
![image](https://user-images.githubusercontent.com/5358638/52340953-8a067380-2a11-11e9-847f-45d1e2f1fdf2.png)

After:
![image](https://user-images.githubusercontent.com/5358638/52340963-8ecb2780-2a11-11e9-8994-ec964402c553.png)



callstack-bot: Hey @jaulz, thank you for your pull request 🤗. The documentation from this branch can be viewed [here](https://7778-71323749-gh.circle-artifacts.com/0/docs/index.html). Please remember to update Typescript types if you changed API.

Patch:
diff --git a/package.json b/package.json
index 4ee21816a..73e86343f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "react-native-paper",
-  "version": "2.10.1",
+  "version": "2.11.0",
   "description": "Material design for React Native",
   "main": "src/index.js",
   "typings": "typings/index.d.ts",
diff --git a/src/components/Appbar/Appbar.js b/src/components/Appbar/Appbar.js
index e1c06d94b..f9e7a7ada 100644
--- a/src/components/Appbar/Appbar.js
+++ b/src/components/Appbar/Appbar.js
@@ -8,6 +8,7 @@ import AppbarContent from './AppbarContent';
 import AppbarAction from './AppbarAction';
 import AppbarBackAction from './AppbarBackAction';
 import AppbarHeader from './AppbarHeader';
+import Surface from '../Surface';
 import { withTheme } from '../../core/theming';
 import { black, white } from '../../styles/colors';
 import type { Theme } from '../../types';
@@ -124,7 +125,10 @@ class Appbar extends React.Component<Props> {
     }
 
     return (
-      <View style={[{ backgroundColor }, styles.appbar, restStyle]} {...rest}>
+      <Surface
+        style={[{ backgroundColor }, styles.appbar, restStyle]}
+        {...rest}
+      >
         {shouldAddLeftSpacing ? <View style={styles.spacing} /> : null}
         {React.Children.toArray(children)
           .filter(child => child != null && typeof child !== 'boolean')
@@ -154,7 +158,7 @@ class Appbar extends React.Component<Props> {
             return React.cloneElement(child, props);
           })}
         {shouldAddRightSpacing ? <View style={styles.spacing} /> : null}
-      </View>
+      </Surface>
     );
   }
 }
diff --git a/src/components/Appbar/AppbarHeader.js b/src/components/Appbar/AppbarHeader.js
index 78d5bbc27..2826e4069 100644
--- a/src/components/Appbar/AppbarHeader.js
+++ b/src/components/Appbar/AppbarHeader.js
@@ -4,6 +4,7 @@ import * as React from 'react';
 import { View, Platform, SafeAreaView, StyleSheet } from 'react-native';
 
 import Appbar, { DEFAULT_APPBAR_HEIGHT } from './Appbar';
+import shadow from '../../styles/shadow';
 import { withTheme } from '../../core/theming';
 import type { Theme } from '../../types';
 
@@ -99,6 +100,7 @@ class AppbarHeader extends React.Component<Props> {
     const {
       height = DEFAULT_APPBAR_HEIGHT,
       elevation = 4,
+      zIndex = 0,
       backgroundColor = colors.primary,
       ...restStyle
     } = StyleSheet.flatten(style) || {};
@@ -108,7 +110,9 @@ class AppbarHeader extends React.Component<Props> {
       typeof this.props.statusBarHeight === 'number' ? View : SafeAreaView;
 
     return (
-      <Wrapper style={[{ backgroundColor, elevation }]}>
+      <Wrapper
+        style={[{ backgroundColor, zIndex }, elevation && shadow(elevation)]}
+      >
         {/* $FlowFixMe: There seems to be conflict between Appbar's props and Header's props */}
         <Appbar
           style={[
diff --git a/src/components/Avatar/AvatarIcon.js b/src/components/Avatar/AvatarIcon.js
index 9fb4f2fcf..e3a03223b 100644
--- a/src/components/Avatar/AvatarIcon.js
+++ b/src/components/Avatar/AvatarIcon.js
@@ -77,7 +77,7 @@ class Avatar extends React.Component<Props> {
           restStyle,
         ]}
       >
-        <Icon source={icon} color={textColor} size={size / 2} />
+        <Icon source={icon} color={textColor} size={size * 0.6} />
       </View>
     );
   }
diff --git a/src/components/List/ListAccordion.js b/src/components/List/ListAccordion.js
index 1418f1f13..53dab52bc 100644
--- a/src/components/List/ListAccordion.js
+++ b/src/components/List/ListAccordion.js
@@ -211,6 +211,7 @@ const styles = StyleSheet.create({
   },
   row: {
     flexDirection: 'row',
+    alignItems: 'center',
   },
   multiline: {
     height: 40,
diff --git a/src/components/TextInput.js b/src/components/TextInput.js
index 8ad1d437f..8155d5dac 100644
--- a/src/components/TextInput.js
+++ b/src/components/TextInput.js
@@ -23,6 +23,8 @@ const MINIMIZED_LABEL_FONT_SIZE = 12;
 const LABEL_WIGGLE_X_OFFSET = 4;
 const FOCUS_ANIMATION_DURATION = 150;
 const BLUR_ANIMATION_DURATION = 180;
+const LABEL_PADDING_HORIZONTAL = 12;
+const RANDOM_VALUE_TO_CENTER_LABEL = 4; // Don't know why 4, but it works
 
 type RenderProps = {
   ref: any => void,
@@ -69,6 +71,10 @@ type Props = React.ElementConfig<typeof NativeTextInput> & {|
    * Callback that is called when the text input's text changes. Changed text is passed as an argument to the callback handler.
    */
   onChangeText?: Function,
+  /**
+   * Selection color of the input
+   */
+  selectionColor?: string,
   /**
    * Underline color of the input.
    */
@@ -379,6 +385,7 @@ class TextInput extends React.Component<Props, State> {
       disabled,
       label,
       error,
+      selectionColor,
       underlineColor,
       style,
       theme,
@@ -430,6 +437,12 @@ class TextInput extends React.Component<Props, State> {
       };
     }
 
+    const labelHalfWidth = this.state.labelLayout.width / 2;
+    const baseLabelTranslateX =
+      (I18nManager.isRTL ? 1 : -1) *
+      (1 - MINIMIZED_LABEL_FONT_SIZE / MAXIMIZED_LABEL_FONT_SIZE) *
+      labelHalfWidth;
+
     const labelStyle = {
       fontFamily,
       fontSize: MAXIMIZED_LABEL_FONT_SIZE,
@@ -472,9 +485,13 @@ class TextInput extends React.Component<Props, State> {
           translateX: this.state.labeled.interpolate({
             inputRange: [0, 1],
             outputRange: [
-              (I18nManager.isRTL ? 1 : -1) *
-                (1 - MINIMIZED_LABEL_FONT_SIZE / MAXIMIZED_LABEL_FONT_SIZE) *
-                (this.state.labelLayout.width / 2),
+              baseLabelTranslateX > 0
+                ? baseLabelTranslateX +
+                  labelHalfWidth / LABEL_PADDING_HORIZONTAL -
+                  RANDOM_VALUE_TO_CENTER_LABEL
+                : baseLabelTranslateX -
+                  labelHalfWidth / LABEL_PADDING_HORIZONTAL +
+                  RANDOM_VALUE_TO_CENTER_LABEL,
               0,
             ],
           }),
@@ -489,6 +506,7 @@ class TextInput extends React.Component<Props, State> {
           // This is so that the label can overlap the outline
           // Otherwise the border will cut off the label on Android
           <View
+            pointerEvents="none"
             style={[
               styles.outline,
               {
@@ -627,7 +645,10 @@ class TextInput extends React.Component<Props, State> {
           placeholder: label ? this.state.placeholder : this.props.placeholder,
           placeholderTextColor: placeholderColor,
           editable: !disabled,
-          selectionColor: activeColor,
+          selectionColor:
+            typeof selectionColor === 'undefined'
+              ? activeColor
+              : selectionColor,
           onFocus: this._handleFocus,
           onBlur: this._handleBlur,
           underlineColorAndroid: 'transparent',
@@ -660,7 +681,7 @@ const styles = StyleSheet.create({
     position: 'absolute',
     left: 0,
     fontSize: 16,
-    paddingHorizontal: 12,
+    paddingHorizontal: LABEL_PADDING_HORIZONTAL,
   },
   placeholderFlat: {
     top: 19,
@@ -696,6 +717,7 @@ const styles = StyleSheet.create({
     margin: 0,
     minHeight: 58,
     textAlign: I18nManager.isRTL ? 'right' : 'left',
+    zIndex: 1,
   },
   inputOutlined: {
     paddingTop: 20,


Test patch:
diff --git a/src/components/__tests__/__snapshots__/Avatar.test.js.snap b/src/components/__tests__/__snapshots__/Avatar.test.js.snap
index 87ceab821..e9d8dc16d 100644
--- a/src/components/__tests__/__snapshots__/Avatar.test.js.snap
+++ b/src/components/__tests__/__snapshots__/Avatar.test.js.snap
@@ -27,7 +27,7 @@ exports[`renders avatar with icon 1`] = `
       Array [
         Object {
           "color": "#ffffff",
-          "fontSize": 32,
+          "fontSize": 38.4,
         },
         Array [
           Object {
@@ -82,7 +82,7 @@ exports[`renders avatar with icon and custom background color 1`] = `
       Array [
         Object {
           "color": "#ffffff",
-          "fontSize": 32,
+          "fontSize": 38.4,
         },
         Array [
           Object {
diff --git a/src/components/__tests__/__snapshots__/ListAccordion.test.js.snap b/src/components/__tests__/__snapshots__/ListAccordion.test.js.snap
index 5d09154e4..3c5ab1287 100644
--- a/src/components/__tests__/__snapshots__/ListAccordion.test.js.snap
+++ b/src/components/__tests__/__snapshots__/ListAccordion.test.js.snap
@@ -28,6 +28,7 @@ exports[`renders expanded accordion 1`] = `
       pointerEvents="none"
       style={
         Object {
+          "alignItems": "center",
           "flexDirection": "row",
         }
       }
@@ -215,6 +216,7 @@ exports[`renders list accordion with children 1`] = `
       pointerEvents="none"
       style={
         Object {
+          "alignItems": "center",
           "flexDirection": "row",
         }
       }
@@ -384,6 +386,7 @@ exports[`renders list accordion with left items 1`] = `
       pointerEvents="none"
       style={
         Object {
+          "alignItems": "center",
           "flexDirection": "row",
         }
       }
@@ -553,6 +556,7 @@ exports[`renders multiline list accordion 1`] = `
       pointerEvents="none"
       style={
         Object {
+          "alignItems": "center",
           "flexDirection": "row",
         }
       }