Repository: callstack/react-native-paper
Pull request #911 (2019-03-11 12:10:19)

feat: add titleStyle and descriptionStyle props to List.Item
There was no input in #872 for some time, so I decided to create another PR with improved solution.

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

Patch:
diff --git a/example/src/Examples/Dialogs/DialogWithLongText.js b/example/src/Examples/Dialogs/DialogWithLongText.js
index fe76eb684..c2d953b5b 100644
--- a/example/src/Examples/Dialogs/DialogWithLongText.js
+++ b/example/src/Examples/Dialogs/DialogWithLongText.js
@@ -1,7 +1,7 @@
 /* @flow */
 
 import * as React from 'react';
-import { ScrollView } from 'react-native';
+import { Dimensions, ScrollView } from 'react-native';
 import { Paragraph, Button, Portal, Dialog } from 'react-native-paper';
 
 const DialogWithLongText = ({
@@ -12,9 +12,13 @@ const DialogWithLongText = ({
   close: Function,
 }) => (
   <Portal>
-    <Dialog onDismiss={close} visible={visible}>
+    <Dialog
+      onDismiss={close}
+      visible={visible}
+      style={{ maxHeight: 0.6 * Dimensions.get('window').height }}
+    >
       <Dialog.Title>Alert</Dialog.Title>
-      <Dialog.ScrollArea style={{ maxHeight: 220, paddingHorizontal: 0 }}>
+      <Dialog.ScrollArea style={{ paddingHorizontal: 0 }}>
         <ScrollView contentContainerStyle={{ paddingHorizontal: 24 }}>
           <Paragraph>
             Material is the metaphor
@@ -36,6 +40,24 @@ const DialogWithLongText = ({
             conveying how objects move, interact, and exist in space and in
             relation to each other. Realistic lighting shows seams, divides
             space, and indicates moving parts.
+            {'\n'}
+            {'\n'}A material metaphor is the unifying theory of a rationalized
+            space and a system of motion. The material is grounded in tactile
+            reality, inspired by the study of paper and ink, yet technologically
+            advanced and open to imagination and magic.
+            {'\n'}
+            {'\n'}
+            Surfaces and edges of the material provide visual cues that are
+            grounded in reality. The use of familiar tactile attributes helps
+            users quickly understand affordances. Yet the flexibility of the
+            material creates new affordances that supersede those in the
+            physical world, without breaking the rules of physics.
+            {'\n'}
+            {'\n'}
+            The fundamentals of light, surface, and movement are key to
+            conveying how objects move, interact, and exist in space and in
+            relation to each other. Realistic lighting shows seams, divides
+            space, and indicates moving parts.
           </Paragraph>
         </ScrollView>
       </Dialog.ScrollArea>
diff --git a/package.json b/package.json
index d3f5344f9..0501e0de3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "react-native-paper",
-  "version": "2.12.0",
+  "version": "2.13.0",
   "description": "Material design for React Native",
   "main": "src/index.js",
   "typings": "typings/index.d.ts",
diff --git a/src/components/Dialog/DialogScrollArea.js b/src/components/Dialog/DialogScrollArea.js
index 533a124ba..e67466db6 100644
--- a/src/components/Dialog/DialogScrollArea.js
+++ b/src/components/Dialog/DialogScrollArea.js
@@ -64,6 +64,8 @@ const styles = StyleSheet.create({
     borderTopWidth: StyleSheet.hairlineWidth,
     borderBottomWidth: StyleSheet.hairlineWidth,
     paddingHorizontal: 24,
+    flexGrow: 1,
+    flexShrink: 1,
   },
 });
 
diff --git a/src/components/List/ListItem.js b/src/components/List/ListItem.js
index 3bb891b89..2bd5173a5 100644
--- a/src/components/List/ListItem.js
+++ b/src/components/List/ListItem.js
@@ -3,6 +3,10 @@
 import color from 'color';
 import * as React from 'react';
 import { View, StyleSheet } from 'react-native';
+import type {
+  ViewStyleProp,
+  TextStyleProp,
+} from 'react-native/Libraries/StyleSheet/StyleSheet';
 import TouchableRipple from '../TouchableRipple';
 import Text from '../Typography/Text';
 import { withTheme } from '../../core/theming';
@@ -33,7 +37,18 @@ type Props = $RemoveChildren<typeof TouchableRipple> & {|
    * @optional
    */
   theme: Theme,
-  style?: any,
+  /**
+   * Style that is passed to the wrapping TouchableRipple element.
+   */
+  style?: ViewStyleProp,
+  /**
+   * Style that is passed to Title element.
+   */
+  titleStyle?: TextStyleProp,
+  /**
+   * Style that is passed to Description element.
+   */
+  descriptionStyle?: TextStyleProp,
 |};
 
 /**
@@ -73,6 +88,8 @@ class ListItem extends React.Component<Props> {
       onPress,
       theme,
       style,
+      titleStyle,
+      descriptionStyle,
       ...rest
     } = this.props;
     const titleColor = color(theme.colors.text)
@@ -95,7 +112,7 @@ class ListItem extends React.Component<Props> {
           <View style={[styles.item, styles.content]} pointerEvents="none">
             <Text
               numberOfLines={1}
-              style={[styles.title, { color: titleColor }]}
+              style={[styles.title, { color: titleColor }, titleStyle]}
             >
               {title}
             </Text>
@@ -107,6 +124,7 @@ class ListItem extends React.Component<Props> {
                   {
                     color: descriptionColor,
                   },
+                  descriptionStyle,
                 ]}
               >
                 {description}
diff --git a/src/components/Modal.js b/src/components/Modal.js
index 52004fb09..cc58f7382 100644
--- a/src/components/Modal.js
+++ b/src/components/Modal.js
@@ -116,6 +116,7 @@ class Modal extends React.Component<Props, State> {
   };
 
   _showModal = () => {
+    BackHandler.removeEventListener('hardwareBackPress', this._handleBack);
     BackHandler.addEventListener('hardwareBackPress', this._handleBack);
     Animated.timing(this.state.opacity, {
       toValue: 1,
@@ -147,6 +148,10 @@ class Modal extends React.Component<Props, State> {
     });
   };
 
+  componentWillUnmount() {
+    BackHandler.removeEventListener('hardwareBackPress', this._handleBack);
+  }
+
   render() {
     if (!this.state.rendered) return null;
 
diff --git a/typings/components/List.d.ts b/typings/components/List.d.ts
index 993094e00..b232c7921 100644
--- a/typings/components/List.d.ts
+++ b/typings/components/List.d.ts
@@ -1,5 +1,11 @@
 import * as React from 'react';
-import { StyleProp, ViewStyle, ViewProps, TextProps, TextStyle } from 'react-native';
+import {
+  StyleProp,
+  ViewStyle,
+  ViewProps,
+  TextProps,
+  TextStyle,
+} from 'react-native';
 import { ThemeShape, IconSource } from '../types';
 import { TouchableRipplePropsWithoutChildren } from './TouchableRipple';
 
@@ -29,6 +35,8 @@ export interface ItemProps extends TouchableRipplePropsWithoutChildren {
   description?: React.ReactNode;
   left?: (props: { color: string }) => React.ReactNode;
   right?: (props: { color: string }) => React.ReactNode;
+  titleStyle?: StyleProp<TextStyle>;
+  descriptionStyle?: StyleProp<TextStyle>;
 }
 
 export declare class Item extends React.Component<ItemProps> {}
@@ -43,7 +51,7 @@ export declare class Section extends React.Component<SectionProps> {}
 
 export interface SubheaderProps extends TextProps {
   style?: StyleProp<TextStyle>;
-  theme?: ThemeShape
+  theme?: ThemeShape;
 }
 
 export declare class Subheader extends React.Component<SubheaderProps> {}


Test patch:
diff --git a/src/components/__tests__/ListItem.test.js b/src/components/__tests__/ListItem.test.js
index e1869026c..3fd172b17 100644
--- a/src/components/__tests__/ListItem.test.js
+++ b/src/components/__tests__/ListItem.test.js
@@ -51,3 +51,18 @@ it('renders list item with left and right items', () => {
 
   expect(tree).toMatchSnapshot();
 });
+
+it('renders list item with custom title and description styles', () => {
+  const tree = renderer
+    .create(
+      <ListItem
+        title="First Item"
+        description="Item description"
+        titleStyle={{ fontSize: 20 }}
+        descriptionStyle={{ color: 'red' }}
+      />
+    )
+    .toJSON();
+
+  expect(tree).toMatchSnapshot();
+});
diff --git a/src/components/__tests__/__snapshots__/ListAccordion.test.js.snap b/src/components/__tests__/__snapshots__/ListAccordion.test.js.snap
index 3c5ab1287..762c1b7bf 100644
--- a/src/components/__tests__/__snapshots__/ListAccordion.test.js.snap
+++ b/src/components/__tests__/__snapshots__/ListAccordion.test.js.snap
@@ -176,6 +176,7 @@ exports[`renders expanded accordion 1`] = `
                 Object {
                   "color": "rgba(0, 0, 0, 0.87)",
                 },
+                undefined,
               ],
             ]
           }
diff --git a/src/components/__tests__/__snapshots__/ListItem.test.js.snap b/src/components/__tests__/__snapshots__/ListItem.test.js.snap
index 946ebd4cd..f1c52d538 100644
--- a/src/components/__tests__/__snapshots__/ListItem.test.js.snap
+++ b/src/components/__tests__/__snapshots__/ListItem.test.js.snap
@@ -1,5 +1,105 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`renders list item with custom title and description styles 1`] = `
+<View
+  accessible={true}
+  isTVSelectable={true}
+  onResponderGrant={[Function]}
+  onResponderMove={[Function]}
+  onResponderRelease={[Function]}
+  onResponderTerminate={[Function]}
+  onResponderTerminationRequest={[Function]}
+  onStartShouldSetResponder={[Function]}
+  style={
+    Array [
+      false,
+      Array [
+        Object {
+          "padding": 8,
+        },
+        undefined,
+      ],
+    ]
+  }
+>
+  <View
+    style={
+      Object {
+        "flexDirection": "row",
+      }
+    }
+  >
+    <View
+      pointerEvents="none"
+      style={
+        Array [
+          Object {
+            "margin": 8,
+          },
+          Object {
+            "flex": 1,
+            "justifyContent": "center",
+          },
+        ]
+      }
+    >
+      <Text
+        numberOfLines={1}
+        style={
+          Array [
+            Object {
+              "color": "#000000",
+              "fontFamily": "Helvetica Neue",
+              "textAlign": "left",
+              "writingDirection": "ltr",
+            },
+            Array [
+              Object {
+                "fontSize": 16,
+              },
+              Object {
+                "color": "rgba(0, 0, 0, 0.87)",
+              },
+              Object {
+                "fontSize": 20,
+              },
+            ],
+          ]
+        }
+      >
+        First Item
+      </Text>
+      <Text
+        numberOfLines={2}
+        style={
+          Array [
+            Object {
+              "color": "#000000",
+              "fontFamily": "Helvetica Neue",
+              "textAlign": "left",
+              "writingDirection": "ltr",
+            },
+            Array [
+              Object {
+                "fontSize": 14,
+              },
+              Object {
+                "color": "rgba(0, 0, 0, 0.54)",
+              },
+              Object {
+                "color": "red",
+              },
+            ],
+          ]
+        }
+      >
+        Item description
+      </Text>
+    </View>
+  </View>
+</View>
+`;
+
 exports[`renders list item with left and right items 1`] = `
 <View
   accessible={true}
@@ -63,6 +163,7 @@ exports[`renders list item with left and right items 1`] = `
               Object {
                 "color": "rgba(0, 0, 0, 0.87)",
               },
+              undefined,
             ],
           ]
         }
@@ -86,6 +187,7 @@ exports[`renders list item with left and right items 1`] = `
               Object {
                 "color": "rgba(0, 0, 0, 0.54)",
               },
+              undefined,
             ],
           ]
         }
@@ -257,6 +359,7 @@ exports[`renders list item with left item 1`] = `
               Object {
                 "color": "rgba(0, 0, 0, 0.87)",
               },
+              undefined,
             ],
           ]
         }
@@ -328,6 +431,7 @@ exports[`renders list item with right item 1`] = `
               Object {
                 "color": "rgba(0, 0, 0, 0.87)",
               },
+              undefined,
             ],
           ]
         }
@@ -402,6 +506,7 @@ exports[`renders list item with title and description 1`] = `
               Object {
                 "color": "rgba(0, 0, 0, 0.87)",
               },
+              undefined,
             ],
           ]
         }
@@ -425,6 +530,7 @@ exports[`renders list item with title and description 1`] = `
               Object {
                 "color": "rgba(0, 0, 0, 0.54)",
               },
+              undefined,
             ],
           ]
         }
diff --git a/src/components/__tests__/__snapshots__/ListSection.test.js.snap b/src/components/__tests__/__snapshots__/ListSection.test.js.snap
index 9bf48f8c2..829822663 100644
--- a/src/components/__tests__/__snapshots__/ListSection.test.js.snap
+++ b/src/components/__tests__/__snapshots__/ListSection.test.js.snap
@@ -170,6 +170,7 @@ exports[`renders list section with subheader 1`] = `
                 Object {
                   "color": "rgba(0, 0, 0, 0.87)",
                 },
+                undefined,
               ],
             ]
           }
@@ -288,6 +289,7 @@ exports[`renders list section with subheader 1`] = `
                 Object {
                   "color": "rgba(0, 0, 0, 0.87)",
                 },
+                undefined,
               ],
             ]
           }
@@ -444,6 +446,7 @@ exports[`renders list section without subheader 1`] = `
                 Object {
                   "color": "rgba(0, 0, 0, 0.87)",
                 },
+                undefined,
               ],
             ]
           }
@@ -562,6 +565,7 @@ exports[`renders list section without subheader 1`] = `
                 Object {
                   "color": "rgba(0, 0, 0, 0.87)",
                 },
+                undefined,
               ],
             ]
           }