Repository: callstack/react-native-paper
Pull request #1060 (2019-05-13 14:20:06)

fix: use "active" instead of "text" for ripple color
…with Material Design


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

Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 2e9c2fc2c..9590af0bd 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -65,10 +65,19 @@ jobs:
       steps:
         - attach_workspace:
             at: ~/react-native-paper
-        - run: yarn test -- --coverage
+        - restore_cache:
+            name: Restoring Jest Cache
+            keys:
+            - jest-cache-{{ .Branch }}
+            - jest-cache
+        - run: yarn test --maxWorkers=2 --coverage
         - store_artifacts:
             path: coverage
             destination: coverage
+        - save_cache:
+            paths:
+            - ./cache/jest
+            key: jest-cache-{{ .Branch }}
   build-docs:
       <<: *defaults
       steps:
diff --git a/.gitignore b/.gitignore
index e41488a13..94788a566 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ yarn-error.log
 # jest
 #
 coverage/
+cache/jest/
 
 # BUCK
 #
diff --git a/docs/pages/6.recommended-libraries.md b/docs/pages/6.recommended-libraries.md
new file mode 100644
index 000000000..b8faa73b6
--- /dev/null
+++ b/docs/pages/6.recommended-libraries.md
@@ -0,0 +1,21 @@
+---
+title: Recommended Libraries
+---
+
+# Recommended Libraries
+
+Our mission is to provide a full suite of well-integrated components built with Material Design in mind. However, many components already have better well maintained implementations.
+
+Here are some of the libraries we recommend:
+
+## Tabs
+
+[react-native-community/react-native-tab-view](https://github.com/react-native-community/react-native-tab-view)
+
+Material Design themed [swipeable tabs](https://material.io/design/components/tabs.html), maintained by [@satya164](https://twitter.com/satya164) and [@mosdnk](https://twitter.com/mosdnk).
+
+## Bottom sheet
+
+[osdnk/reanimated-bottom-sheet](https://github.com/osdnk/react-native-reanimated-bottom-sheet)
+
+An implementation [bottom sheet behaviour](https://material.io/design/components/sheets-bottom.html), maintained by [@mosdnk](https://twitter.com/mosdnk).
diff --git a/docs/pages/6.contributing.md b/docs/pages/7.contributing.md
similarity index 100%
rename from docs/pages/6.contributing.md
rename to docs/pages/7.contributing.md
diff --git a/example/src/Examples/ListSectionExample.js b/example/src/Examples/ListSectionExample.js
index a44097ac6..af006cddc 100644
--- a/example/src/Examples/ListSectionExample.js
+++ b/example/src/Examples/ListSectionExample.js
@@ -1,8 +1,8 @@
 /* @flow */
 
 import * as React from 'react';
-import { ScrollView, StyleSheet, Image } from 'react-native';
-import { List, Divider, withTheme, type Theme } from 'react-native-paper';
+import { ScrollView, StyleSheet, Image, View, Text } from 'react-native';
+import { Chip, List, Divider, withTheme, type Theme } from 'react-native-paper';
 
 type Props = {
   theme: Theme,
@@ -80,6 +80,42 @@ class ListSectionExample extends React.Component<Props> {
             description="Describes item 2. Example of a very very long description."
           />
         </List.Section>
+        <Divider />
+        <List.Section>
+          <List.Subheader>Custom description</List.Subheader>
+          <List.Item
+            left={() => (
+              <Image
+                source={require('../../assets/images/email-icon.png')}
+                style={styles.image}
+              />
+            )}
+            right={props => <List.Icon {...props} icon="star-border" />}
+            title="List Item 1"
+            description={({
+              ellipsizeMode,
+              color: descriptionColor,
+              fontSize,
+            }) => (
+              <View style={[styles.container, styles.column]}>
+                <Text
+                  numberOfLines={2}
+                  ellipsizeMode={ellipsizeMode}
+                  style={{ color: descriptionColor, fontSize }}
+                >
+                  React Native Paper is a high-quality, standard-compliant
+                  Material Design library that has you covered in all major
+                  use-cases.
+                </Text>
+                <View style={[styles.container, styles.row, { paddingTop: 8 }]}>
+                  <Chip icon="picture-as-pdf" onPress={() => {}}>
+                    DOCS.pdf
+                  </Chip>
+                </View>
+              </View>
+            )}
+          />
+        </List.Section>
       </ScrollView>
     );
   }
@@ -94,6 +130,12 @@ const styles = StyleSheet.create({
     width: 40,
     margin: 8,
   },
+  row: {
+    flexDirection: 'row',
+  },
+  column: {
+    flexDirection: 'column',
+  },
 });
 
 export default withTheme(ListSectionExample);
diff --git a/package.json b/package.json
index c41ec841c..b7ec322e6 100644
--- a/package.json
+++ b/package.json
@@ -106,6 +106,7 @@
   },
   "jest": {
     "preset": "react-native",
+    "cacheDirectory": "./cache/jest",
     "modulePathIgnorePatterns": [
       "<rootDir>/example/node_modules"
     ],
diff --git a/src/components/BottomNavigation.js b/src/components/BottomNavigation.js
index 28dff89d9..1483254d2 100644
--- a/src/components/BottomNavigation.js
+++ b/src/components/BottomNavigation.js
@@ -595,7 +595,7 @@ class BottomNavigation<T: *> extends React.Component<Props<T>, State> {
             .rgb()
             .string();
 
-    const touchColor = color(textColor)
+    const touchColor = color(activeColor)
       .alpha(0.12)
       .rgb()
       .string();
diff --git a/src/components/DataTable/DataTableRow.js b/src/components/DataTable/DataTableRow.js
index 4cb1a8928..cc8077d2b 100644
--- a/src/components/DataTable/DataTableRow.js
+++ b/src/components/DataTable/DataTableRow.js
@@ -51,11 +51,11 @@ const styles = StyleSheet.create({
     borderStyle: 'solid',
     borderBottomWidth: StyleSheet.hairlineWidth,
     minHeight: 48,
+    paddingHorizontal: 16,
   },
   content: {
     flex: 1,
     flexDirection: 'row',
-    paddingHorizontal: 16,
   },
 });
 
diff --git a/src/components/Drawer/DrawerSection.js b/src/components/Drawer/DrawerSection.js
index 66428878c..d40b3fda4 100644
--- a/src/components/Drawer/DrawerSection.js
+++ b/src/components/Drawer/DrawerSection.js
@@ -2,11 +2,12 @@
 
 import color from 'color';
 import * as React from 'react';
-import { View } from 'react-native';
+import { View, StyleSheet } from 'react-native';
 import Text from '../Typography/Text';
 import Divider from '../Divider';
 import { withTheme } from '../../core/theming';
 import type { Theme } from '../../types';
+import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';
 
 type Props = React.ElementConfig<typeof View> & {
   /**
@@ -17,6 +18,7 @@ type Props = React.ElementConfig<typeof View> & {
    * Content of the `Drawer.Section`.
    */
   children: React.Node,
+  style?: ViewStyleProp,
   /**
    * @optional
    */
@@ -61,7 +63,7 @@ class DrawerSection extends React.Component<Props> {
   static displayName = 'Drawer.Section';
 
   render() {
-    const { children, title, theme, ...rest } = this.props;
+    const { children, title, theme, style, ...rest } = this.props;
     const { colors, fonts } = theme;
     const titleColor = color(colors.text)
       .alpha(0.54)
@@ -70,9 +72,9 @@ class DrawerSection extends React.Component<Props> {
     const fontFamily = fonts.medium;
 
     return (
-      <View {...rest}>
+      <View style={[styles.container, style]} {...rest}>
         {title && (
-          <View style={{ height: 40, justifyContent: 'center' }}>
+          <View style={styles.titleContainer}>
             <Text
               numberOfLines={1}
               style={{ color: titleColor, fontFamily, marginLeft: 16 }}
@@ -82,10 +84,23 @@ class DrawerSection extends React.Component<Props> {
           </View>
         )}
         {children}
-        <Divider style={{ marginVertical: 4 }} />
+        <Divider style={styles.divider} />
       </View>
     );
   }
 }
 
+const styles = StyleSheet.create({
+  container: {
+    marginBottom: 4,
+  },
+  titleContainer: {
+    height: 40,
+    justifyContent: 'center',
+  },
+  divider: {
+    marginTop: 4,
+  },
+});
+
 export default withTheme(DrawerSection);
diff --git a/src/components/List/ListItem.js b/src/components/List/ListItem.js
index 51572a612..177603399 100644
--- a/src/components/List/ListItem.js
+++ b/src/components/List/ListItem.js
@@ -10,7 +10,7 @@ import type {
 import TouchableRipple from '../TouchableRipple';
 import Text from '../Typography/Text';
 import { withTheme } from '../../core/theming';
-import type { Theme, $RemoveChildren } from '../../types';
+import type { Theme, $RemoveChildren, EllipsizeProp } from '../../types';
 
 type Props = $RemoveChildren<typeof TouchableRipple> & {|
   /**
@@ -18,9 +18,15 @@ type Props = $RemoveChildren<typeof TouchableRipple> & {|
    */
   title: React.Node,
   /**
-   * Description text for the list item.
+   * Description text for the list item or callback which returns a React element to display the description.
    */
-  description?: React.Node,
+  description?:
+    | React.Node
+    | ((props: {
+        ellipsizeMode: EllipsizeProp,
+        color: string,
+        fontSize: number,
+      }) => React.Node),
   /**
    * Callback which returns a React element to display on the left side.
    */
@@ -52,11 +58,11 @@ type Props = $RemoveChildren<typeof TouchableRipple> & {|
   /**
    * Ellipsize Mode for the Title
    */
-  titleEllipsizeMode?: 'head' | 'middle' | 'tail' | 'clip',
+  titleEllipsizeMode?: EllipsizeProp,
   /**
    * Ellipsize Mode for the Description
    */
-  descriptionEllipsizeMode?: 'head' | 'middle' | 'tail' | 'clip',
+  descriptionEllipsizeMode?: EllipsizeProp,
 |};
 
 /**
@@ -87,6 +93,31 @@ type Props = $RemoveChildren<typeof TouchableRipple> & {|
 class ListItem extends React.Component<Props> {
   static displayName = 'List.Item';
 
+  renderDescription(description, descriptionColor) {
+    const { descriptionEllipsizeMode, descriptionStyle } = this.props;
+
+    return typeof description === 'string' ? (
+      <Text
+        numberOfLines={2}
+        ellipsizeMode={descriptionEllipsizeMode}
+        style={[
+          styles.description,
+          { color: descriptionColor },
+          descriptionStyle,
+        ]}
+      >
+        {description}
+      </Text>
+    ) : (
+      description &&
+        description({
+          ellipsizeMode: descriptionEllipsizeMode,
+          color: descriptionColor,
+          fontSize: styles.description.fontSize,
+        })
+    );
+  }
+
   render() {
     const {
       left,
@@ -97,9 +128,7 @@ class ListItem extends React.Component<Props> {
       theme,
       style,
       titleStyle,
-      descriptionStyle,
       titleEllipsizeMode,
-      descriptionEllipsizeMode,
       ...rest
     } = this.props;
     const titleColor = color(theme.colors.text)
@@ -127,21 +156,7 @@ class ListItem extends React.Component<Props> {
             >
               {title}
             </Text>
-            {description ? (
-              <Text
-                ellipsizeMode={descriptionEllipsizeMode}
-                numberOfLines={2}
-                style={[
-                  styles.description,
-                  {
-                    color: descriptionColor,
-                  },
-                  descriptionStyle,
-                ]}
-              >
-                {description}
-              </Text>
-            ) : null}
+            {this.renderDescription(description, descriptionColor)}
           </View>
           {right ? right({ color: descriptionColor }) : null}
         </View>
diff --git a/src/types.js b/src/types.js
index e35b15703..ea757180e 100644
--- a/src/types.js
+++ b/src/types.js
@@ -35,3 +35,5 @@ export type $RemoveChildren<T> = $Diff<
   React.ElementConfig<T>,
   { children: any }
 >;
+
+export type EllipsizeProp = 'head' | 'middle' | 'tail' | 'clip';
diff --git a/typings/components/List.d.ts b/typings/components/List.d.ts
index 3b9ca371c..463933ae4 100644
--- a/typings/components/List.d.ts
+++ b/typings/components/List.d.ts
@@ -6,7 +6,7 @@ import {
   TextProps,
   TextStyle,
 } from 'react-native';
-import { ThemeShape, IconSource } from '../types';
+import { ThemeShape, IconSource, EllipsizeProp } from '../types';
 import { TouchableRipplePropsWithoutChildren } from './TouchableRipple';
 
 export interface AccordionProps {
@@ -39,8 +39,8 @@ export interface ItemProps extends TouchableRipplePropsWithoutChildren {
   right?: (props: { color: string }) => React.ReactNode;
   titleStyle?: StyleProp<TextStyle>;
   descriptionStyle?: StyleProp<TextStyle>;
-  titleEllipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';
-  descriptionEllipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';
+  titleEllipsizeMode?: EllipsizeProp;
+  descriptionEllipsizeMode?: EllipsizeProp;
 }
 
 export declare class Item extends React.Component<ItemProps> {}
diff --git a/typings/types.d.ts b/typings/types.d.ts
index d9e93790c..5b0aca554 100644
--- a/typings/types.d.ts
+++ b/typings/types.d.ts
@@ -50,3 +50,5 @@ export declare class Provider extends React.Component<{
   children: React.ReactNode;
   theme?: ThemeShape;
 }> {}
+
+export type EllipsizeProp = 'head' | 'middle' | 'tail' | 'clip';


Test patch:
diff --git a/src/components/__tests__/Drawer/DrawerSection.test.js b/src/components/__tests__/Drawer/DrawerSection.test.js
new file mode 100644
index 000000000..e6874f989
--- /dev/null
+++ b/src/components/__tests__/Drawer/DrawerSection.test.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import { View } from 'react-native';
+import renderer from 'react-test-renderer';
+import DrawerSection from '../../Drawer/DrawerSection';
+
+describe('DrawerSection', () => {
+  it('renders properly', () => {
+    const tree = renderer
+      .create(
+        <DrawerSection>
+          <View />
+        </DrawerSection>
+      )
+      .toJSON();
+
+    expect(tree).toMatchSnapshot();
+  });
+});
diff --git a/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.js.snap b/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.js.snap
new file mode 100644
index 000000000..98bb911c6
--- /dev/null
+++ b/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.js.snap
@@ -0,0 +1,30 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DrawerSection renders properly 1`] = `
+<View
+  style={
+    Array [
+      Object {
+        "marginBottom": 4,
+      },
+      undefined,
+    ]
+  }
+>
+  <View />
+  <View
+    style={
+      Array [
+        Object {
+          "backgroundColor": "rgba(0, 0, 0, 0.12)",
+          "height": 0.5,
+        },
+        undefined,
+        Object {
+          "marginTop": 4,
+        },
+      ]
+    }
+  />
+</View>
+`;
diff --git a/src/components/__tests__/ListItem.test.js b/src/components/__tests__/ListItem.test.js
index 3fd172b17..5be212dec 100644
--- a/src/components/__tests__/ListItem.test.js
+++ b/src/components/__tests__/ListItem.test.js
@@ -2,9 +2,10 @@
 
 import * as React from 'react';
 import renderer from 'react-test-renderer';
-import { Text } from 'react-native';
+import { Text, View } from 'react-native';
 import ListItem from '../List/ListItem';
 import ListIcon from '../List/ListIcon';
+import Chip from '../Chip';
 
 it('renders list item with title and description', () => {
   const tree = renderer
@@ -66,3 +67,32 @@ it('renders list item with custom title and description styles', () => {
 
   expect(tree).toMatchSnapshot();
 });
+
+it('renders list item with custom description', () => {
+  const tree = renderer
+    .create(
+      <ListItem
+        title="List Item with custom description"
+        description={({ ellipsizeMode, color: descriptionColor, fontSize }) => (
+          <View>
+            <Text
+              numberOfLines={2}
+              ellipsizeMode={ellipsizeMode}
+              style={{ color: descriptionColor, fontSize }}
+            >
+              React Native Paper is a high-quality, standard-compliant Design
+              Design library that has you covered in all major use-cases.
+            </Text>
+            <View>
+              <Chip icon="picture-as-pdf" onPress={() => {}}>
+                DOCS.pdf
+              </Chip>
+            </View>
+          </View>
+        )}
+      />
+    )
+    .toJSON();
+
+  expect(tree).toMatchSnapshot();
+});
diff --git a/src/components/__tests__/__snapshots__/ListItem.test.js.snap b/src/components/__tests__/__snapshots__/ListItem.test.js.snap
index f1c52d538..6314b67ca 100644
--- a/src/components/__tests__/__snapshots__/ListItem.test.js.snap
+++ b/src/components/__tests__/__snapshots__/ListItem.test.js.snap
@@ -1,5 +1,212 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`renders list item with custom description 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)",
+              },
+              undefined,
+            ],
+          ]
+        }
+      >
+        List Item with custom description
+      </Text>
+      <View>
+        <Text
+          numberOfLines={2}
+          style={
+            Object {
+              "color": "rgba(0, 0, 0, 0.54)",
+              "fontSize": 14,
+            }
+          }
+        >
+          React Native Paper is a high-quality, standard-compliant Design Design library that has you covered in all major use-cases.
+        </Text>
+        <View>
+          <View
+            style={
+              Object {
+                "backgroundColor": "#ebebeb",
+                "borderColor": "#ebebeb",
+                "borderRadius": 16,
+                "borderStyle": "solid",
+                "borderWidth": 0.5,
+                "elevation": 0,
+              }
+            }
+          >
+            <View
+              accessibilityRole="button"
+              accessibilityStates={Array []}
+              accessible={true}
+              isTVSelectable={true}
+              onResponderGrant={[Function]}
+              onResponderMove={[Function]}
+              onResponderRelease={[Function]}
+              onResponderTerminate={[Function]}
+              onResponderTerminationRequest={[Function]}
+              onStartShouldSetResponder={[Function]}
+              style={
+                Array [
+                  Object {
+                    "overflow": "hidden",
+                  },
+                  Object {
+                    "borderRadius": 16,
+                  },
+                ]
+              }
+            >
+              <View
+                style={
+                  Object {
+                    "alignItems": "center",
+                    "flexDirection": "row",
+                    "paddingHorizontal": 4,
+                  }
+                }
+              >
+                <View
+                  style={
+                    Array [
+                      Object {
+                        "padding": 4,
+                      },
+                      null,
+                    ]
+                  }
+                >
+                  <Text
+                    accessibilityElementsHidden={true}
+                    allowFontScaling={false}
+                    importantForAccessibility="no-hide-descendants"
+                    pointerEvents="none"
+                    style={
+                      Array [
+                        Object {
+                          "color": "rgba(0, 0, 0, 0.54)",
+                          "fontSize": 18,
+                        },
+                        Array [
+                          Object {
+                            "transform": Array [
+                              Object {
+                                "scaleX": 1,
+                              },
+                            ],
+                          },
+                          Object {
+                            "backgroundColor": "transparent",
+                          },
+                        ],
+                        Object {
+                          "fontFamily": "Material Icons",
+                          "fontStyle": "normal",
+                          "fontWeight": "normal",
+                        },
+                        Object {},
+                      ]
+                    }
+                  >
+                    
+                  </Text>
+                </View>
+                <Text
+                  numberOfLines={1}
+                  style={
+                    Array [
+                      Object {
+                        "color": "#000000",
+                        "fontFamily": "Helvetica Neue",
+                        "textAlign": "left",
+                        "writingDirection": "ltr",
+                      },
+                      Array [
+                        Object {
+                          "lineHeight": 24,
+                          "marginVertical": 4,
+                          "minHeight": 24,
+                          "textAlignVertical": "center",
+                        },
+                        Object {
+                          "color": "rgba(0, 0, 0, 0.87)",
+                          "marginLeft": 4,
+                          "marginRight": 8,
+                        },
+                        undefined,
+                      ],
+                    ]
+                  }
+                >
+                  DOCS.pdf
+                </Text>
+              </View>
+            </View>
+          </View>
+        </View>
+      </View>
+    </View>
+  </View>
+</View>
+`;
+
 exports[`renders list item with custom title and description styles 1`] = `
 <View
   accessible={true}