Repository: callstack/react-native-paper
Pull request #1213 (2019-07-15 12:20:04)

feat: add character counter to text input example
### Motivation
Fixes: #1212 

Following the MD guidelines I've added character counter example.
![image](https://user-images.githubusercontent.com/22746080/61215499-5b509f80-a70b-11e9-855c-29ff2c3990a4.png)


### Test plan

<img width="300" src="https://user-images.githubusercontent.com/22746080/61215512-673c6180-a70b-11e9-9c7c-c86693fce91d.gif" />

with longer message | RTL
--- | ---
<img width="510" alt="Screenshot 2019-07-15 at 14 15 13" src="https://user-images.githubusercontent.com/22746080/61215548-8dfa9800-a70b-11e9-8062-2cec916d918f.png"> | <img width="510" alt="Screenshot 2019-07-15 at 14 15 29" src="https://user-images.githubusercontent.com/22746080/61215570-99e65a00-a70b-11e9-97e9-f108477ef6d0.png">





Patch:
diff --git a/example/src/Examples/TextInputExample.tsx b/example/src/Examples/TextInputExample.tsx
index 2a9fae993..9b4701b3e 100644
--- a/example/src/Examples/TextInputExample.tsx
+++ b/example/src/Examples/TextInputExample.tsx
@@ -7,6 +7,8 @@ import {
 } from 'react-native';
 import { TextInput, HelperText, withTheme, Theme } from 'react-native-paper';
 
+const MAX_LENGTH = 20;
+
 type Props = {
   theme: Theme;
 };
@@ -26,6 +28,7 @@ type State = {
   flatTextArea: string;
   outlinedMultiline: string;
   outlinedTextArea: string;
+  maxLengthName: string;
 };
 
 class TextInputExample extends React.Component<Props, State> {
@@ -46,6 +49,7 @@ class TextInputExample extends React.Component<Props, State> {
     flatTextArea: '',
     outlinedMultiline: '',
     outlinedTextArea: '',
+    maxLengthName: '',
   };
 
   _isUsernameValid = (name: string) => /^[a-zA-Z]*$/.test(name);
@@ -198,6 +202,28 @@ class TextInputExample extends React.Component<Props, State> {
               Error: Only letters are allowed
             </HelperText>
           </View>
+          <View style={styles.inputContainerStyle}>
+            <TextInput
+              label="Input with helper text and character counter"
+              placeholder="Enter username, only letters"
+              value={this.state.maxLengthName}
+              error={!this._isUsernameValid(this.state.maxLengthName)}
+              onChangeText={maxLengthName => this.setState({ maxLengthName })}
+              maxLength={MAX_LENGTH}
+            />
+            <View style={styles.helpersWrapper}>
+              <HelperText
+                type="error"
+                visible={!this._isUsernameValid(this.state.maxLengthName)}
+                style={styles.helper}
+              >
+                Error: Numbers and special characters are not allowed
+              </HelperText>
+              <HelperText visible style={styles.counterHelper}>
+                {this.state.maxLengthName.length} / {MAX_LENGTH}
+              </HelperText>
+            </View>
+          </View>
           <View style={styles.inputContainerStyle}>
             <TextInput
               label="Input with no padding"
@@ -227,9 +253,19 @@ const styles = StyleSheet.create({
     flex: 1,
     padding: 8,
   },
+  helpersWrapper: {
+    flexDirection: 'row',
+    justifyContent: 'space-between',
+  },
   wrapper: {
     flex: 1,
   },
+  helper: {
+    flexShrink: 1,
+  },
+  counterHelper: {
+    textAlign: 'right',
+  },
   inputContainerStyle: {
     margin: 8,
   },
diff --git a/src/components/Chip.tsx b/src/components/Chip.tsx
index 0ee92cfb6..09519bfd5 100644
--- a/src/components/Chip.tsx
+++ b/src/components/Chip.tsx
@@ -279,6 +279,7 @@ class Chip extends React.Component<Props, State> {
               style={[
                 styles.text,
                 {
+                  ...theme.fonts.regular,
                   color: textColor,
                   marginRight: onClose ? 4 : 8,
                   marginLeft: avatar || icon || selected ? 4 : 8,
diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx
index 846751966..7c6751ec5 100644
--- a/src/components/Modal.tsx
+++ b/src/components/Modal.tsx
@@ -6,9 +6,9 @@ import {
   StyleProp,
   StyleSheet,
   TouchableWithoutFeedback,
-  View,
   ViewStyle,
 } from 'react-native';
+import SafeAreaView from 'react-native-safe-area-view';
 import Surface from './Surface';
 import { withTheme } from '../core/theming';
 import { Theme } from '../types';
@@ -195,7 +195,7 @@ class Modal extends React.Component<Props, State> {
             ]}
           />
         </TouchableWithoutFeedback>
-        <View pointerEvents="box-none" style={styles.wrapper}>
+        <SafeAreaView style={styles.wrapper}>
           <Surface
             style={
               [
@@ -207,7 +207,7 @@ class Modal extends React.Component<Props, State> {
           >
             {children}
           </Surface>
-        </View>
+        </SafeAreaView>
       </Animated.View>
     );
   }


Test patch:
diff --git a/src/components/__tests__/__snapshots__/Chip.test.js.snap b/src/components/__tests__/__snapshots__/Chip.test.js.snap
index accc96d86..645f696e5 100644
--- a/src/components/__tests__/__snapshots__/Chip.test.js.snap
+++ b/src/components/__tests__/__snapshots__/Chip.test.js.snap
@@ -109,6 +109,8 @@ exports[`renders chip with close button 1`] = `
               },
               Object {
                 "color": "rgba(0, 0, 0, 0.87)",
+                "fontFamily": "System",
+                "fontWeight": "400",
                 "marginLeft": 4,
                 "marginRight": 4,
               },
@@ -284,6 +286,8 @@ exports[`renders chip with icon 1`] = `
               },
               Object {
                 "color": "rgba(0, 0, 0, 0.87)",
+                "fontFamily": "System",
+                "fontWeight": "400",
                 "marginLeft": 4,
                 "marginRight": 8,
               },
@@ -363,6 +367,8 @@ exports[`renders chip with onPress 1`] = `
               },
               Object {
                 "color": "rgba(0, 0, 0, 0.87)",
+                "fontFamily": "System",
+                "fontWeight": "400",
                 "marginLeft": 8,
                 "marginRight": 8,
               },
@@ -446,6 +452,8 @@ exports[`renders outlined disabled chip 1`] = `
               },
               Object {
                 "color": "rgba(0, 0, 0, 0.26)",
+                "fontFamily": "System",
+                "fontWeight": "400",
                 "marginLeft": 8,
                 "marginRight": 8,
               },
@@ -574,6 +582,8 @@ exports[`renders selected chip 1`] = `
               },
               Object {
                 "color": "rgba(0, 0, 0, 0.87)",
+                "fontFamily": "System",
+                "fontWeight": "400",
                 "marginLeft": 4,
                 "marginRight": 8,
               },
diff --git a/src/components/__tests__/__snapshots__/ListItem.test.js.snap b/src/components/__tests__/__snapshots__/ListItem.test.js.snap
index 802bad892..b50b19b71 100644
--- a/src/components/__tests__/__snapshots__/ListItem.test.js.snap
+++ b/src/components/__tests__/__snapshots__/ListItem.test.js.snap
@@ -190,6 +190,8 @@ exports[`renders list item with custom description 1`] = `
                         },
                         Object {
                           "color": "rgba(0, 0, 0, 0.87)",
+                          "fontFamily": "System",
+                          "fontWeight": "400",
                           "marginLeft": 4,
                           "marginRight": 8,
                         },