Skip to content

Commit

Permalink
feat: Add ListSection and ListItem components
Browse files Browse the repository at this point in the history
  • Loading branch information
gawrysiak authored and satya164 committed Apr 12, 2018
1 parent 5e38f9c commit 7b2948f
Show file tree
Hide file tree
Showing 11 changed files with 334 additions and 0 deletions.
Binary file added docs/assets/screenshots/list-item-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/screenshots/list-item-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/screenshots/list-item-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/screenshots/list-section.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/assets/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
}

.screenshots img.large {
display: block;
width: 560px;
}

Expand Down
Binary file added example/assets/email-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions example/src/ExampleList.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import DialogExample from './DialogExample';
import DividerExample from './DividerExample';
import ExampleListRow from './ExampleListRow';
import FABExample from './FABExample';
import ListSectionExample from './ListSectionExample';
import PaperExample from './PaperExample';
import ProgressBarExample from './ProgressBarExample';
import RadioButtonExample from './RadioButtonExample';
Expand All @@ -36,6 +37,7 @@ export const examples = {
dialog: DialogExample,
divider: DividerExample,
fab: FABExample,
listSection: ListSectionExample,
paper: PaperExample,
progressbar: ProgressBarExample,
radio: RadioButtonExample,
Expand Down
86 changes: 86 additions & 0 deletions example/src/ListSectionExample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* @flow */

import * as React from 'react';
import { ScrollView, StyleSheet, Image } from 'react-native';
import { ListSection, ListItem, Divider, withTheme } from 'react-native-paper';
import type { Theme } from 'react-native-paper/types';

type Props = {
theme: Theme,
};

class ListSectionExample extends React.Component<Props> {
static title = 'ListSection';

render() {
const { theme: { colors: { background } } } = this.props;
return (
<ScrollView style={[styles.container, { backgroundColor: background }]}>
<ListSection title="Single line">
<ListItem icon="event" title="List item 1" />
<ListItem icon="redeem" title="List item 2" />
</ListSection>
<Divider />
<ListSection title="Two line">
<ListItem
avatar={
<Image
source={require('../assets/email-icon.png')}
style={styles.avatar}
/>
}
title="List item 1"
description="Describes item 1"
/>
<ListItem
icon="info"
avatar={
<Image
source={require('../assets/email-icon.png')}
style={styles.avatar}
/>
}
title="List item 2"
description="Describes item 2"
/>
</ListSection>
<Divider />
<ListSection title="Three line">
<ListItem
avatar={
<Image
source={require('../assets/email-icon.png')}
style={styles.avatar}
/>
}
title="List item 1"
description="Describes item 1. Example of a very very long description."
/>
<ListItem
icon="star-border"
avatar={
<Image
source={require('../assets/email-icon.png')}
style={styles.avatar}
/>
}
title="List item 2"
description="Describes item 2. Example of a very very long description."
/>
</ListSection>
</ScrollView>
);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
},
avatar: {
height: 40,
width: 40,
},
});

export default withTheme(ListSectionExample);
153 changes: 153 additions & 0 deletions src/components/ListItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/* @flow */

import color from 'color';
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import Icon from './Icon';
import TouchableRipple from './TouchableRipple';
import Text from './Typography/Text';
import withTheme from '../core/withTheme';
import type { Theme } from '../types';
import type { IconSource } from './Icon';

type Props = {
/**
* Title text for the list item.
*/
title: React.Node,
/**
* Description text for the list item.
*/
description?: React.Node,
/**
* Name of the icon. Can be a string (name of `MaterialIcon`),
* an object of shape `{ uri: 'https://path.to' }`,
* a local image: `require('../path/to/image.png')`,
* or a valid React Native component.
*/
icon?: IconSource,
/**
* Component to display as avatar image.
*/
avatar?: React.Node,
/**
* Function to execute on press.
*/
onPress?: Function,
/**
* @optional
*/
theme: Theme,
style?: any,
};

/**
* ListItem can be used to show tiles inside a List.
*
* <div class="screenshots">
* <img class="medium" src="screenshots/list-item-1.png" />
* <img class="medium" src="screenshots/list-item-2.png" />
* <img class="medium" src="screenshots/list-item-3.png" />
* </div>
*
* ## Usage
* ```js
* import * as React from 'react';
* import { ListItem } from 'react-native-paper';
*
* const MyComponent = () => (
* <ListItem title="First Item" description="Item description" icon="folder" />
* );
* ```
*/
const ListItem = ({
icon,
avatar,
title,
description,
onPress,
theme,
style,
}: Props) => {
const titleColor = color(theme.colors.text)
.alpha(0.87)
.rgb()
.string();
const descriptionColor = color(theme.colors.text)
.alpha(0.54)
.rgb()
.string();

return (
<TouchableRipple style={[styles.container, style]} onPress={onPress}>
<View style={styles.row}>
{avatar || icon ? (
<View
style={[
styles.item,
styles.avatar,
description && styles.multiline,
]}
>
{avatar || <Icon name={icon} size={24} color={descriptionColor} />}
</View>
) : null}
<View style={[styles.item, styles.content]}>
<Text numberOfLines={1} style={[styles.title, { color: titleColor }]}>
{title}
</Text>
{description && (
<Text
numberOfLines={2}
style={[
styles.description,
{
color: descriptionColor,
},
]}
>
{description}
</Text>
)}
</View>
{avatar && icon ? (
<View style={[styles.item, description && styles.multiline]}>
<Icon name={icon} size={24} color={descriptionColor} />
</View>
) : null}
</View>
</TouchableRipple>
);
};

const styles = StyleSheet.create({
container: {
padding: 8,
},
row: {
flexDirection: 'row',
},
avatar: {
width: 40,
},
multiline: {
height: 40,
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: 16,
},
description: {
fontSize: 14,
},
item: {
margin: 8,
},
content: {
flex: 1,
justifyContent: 'center',
},
});

export default withTheme(ListItem);
90 changes: 90 additions & 0 deletions src/components/ListSection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* @flow */

import color from 'color';
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import Text from './Typography/Text';
import withTheme from '../core/withTheme';
import type { Theme } from '../types';

type Props = {
/**
* Title text for the section.
*/
title?: string,
/**
* Content of the section.
*/
children: React.Node,
/**
* @optional
*/
theme: Theme,
style?: any,
};

/**
* `ListSection` groups items, usually `ListItem`.
*
* <div class="screenshots">
* <img src="screenshots/list-section.png" />
* </div>
*
* ## Usage
* ```js
* import * as React from 'react';
* import { ListSection, ListItem } from 'react-native-paper';
*
* export default class MyComponent extends React.Component {
* render() {
* return (
* <ListSection title="Some title">
* <ListItem
* title="First Item"
* icon="folder"
* />
* <ListItem
* title="Second Item"
* icon="folder"
* />
* </ListSection>
* );
* }
* }
* ```
*/
const ListSection = ({ children, title, theme, style, ...rest }: Props) => {
const { colors, fonts } = theme;

const titleColor = color(colors.text)
.alpha(0.54)
.rgb()
.string();
const fontFamily = fonts.medium;

return (
<View {...rest} style={[styles.container, style]}>
{title && (
<Text
numberOfLines={1}
style={[styles.title, { color: titleColor, fontFamily }]}
>
{title}
</Text>
)}
{children}
</View>
);
};

const styles = StyleSheet.create({
container: {
marginVertical: 8,
},
title: {
marginVertical: 13,
marginHorizontal: 16,
},
});

export default withTheme(ListSection);
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export { default as Divider } from './components/Divider';
export { default as DrawerItem } from './components/DrawerItem';
export { default as DrawerSection } from './components/DrawerSection';
export { default as FAB } from './components/FAB';
export { default as ListSection } from './components/ListSection';
export { default as ListItem } from './components/ListItem';
export { default as Modal } from './components/Modal';
export { default as Paper } from './components/Paper';
export { default as ProgressBar } from './components/ProgressBar/ProgressBar';
Expand Down

0 comments on commit 7b2948f

Please sign in to comment.