Skip to content

Commit

Permalink
feat: add ListAccordion component
Browse files Browse the repository at this point in the history
  • Loading branch information
gawrysiak authored and satya164 committed May 5, 2018
1 parent 174af0d commit b6462b7
Show file tree
Hide file tree
Showing 17 changed files with 868 additions and 27 deletions.
Binary file added docs/assets/screenshots/list-accordion-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-accordion-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-accordion-3.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 @@ -10,6 +10,7 @@ import CheckboxExample from './CheckboxExample';
import DialogExample from './DialogExample';
import DividerExample from './DividerExample';
import FABExample from './FABExample';
import ListAccordionExample from './ListAccordionExample';
import ListSectionExample from './ListSectionExample';
import PaperExample from './PaperExample';
import ProgressBarExample from './ProgressBarExample';
Expand Down Expand Up @@ -37,6 +38,7 @@ export const examples = {
dialog: DialogExample,
divider: DividerExample,
fab: FABExample,
listAccordion: ListAccordionExample,
listSection: ListSectionExample,
paper: PaperExample,
progressbar: ProgressBarExample,
Expand Down
63 changes: 63 additions & 0 deletions example/src/ListAccordionExample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* @flow */

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

type Props = {
theme: Theme,
};

class ListAccordionExample extends React.Component<Props> {
static title = 'ListAccordion';

render() {
const {
theme: {
colors: { background },
},
} = this.props;
return (
<ScrollView style={[styles.container, { backgroundColor: background }]}>
<ListSection title="Expandable list item">
<ListAccordion icon="folder" title="Expandable list item">
<ListItem title="List item 1" />
<ListItem title="List item 2" />
</ListAccordion>
</ListSection>
<Divider />
<ListSection title="Expandable & multiline list item">
<ListAccordion
title="Expandable list item"
description="Describes the expandable list item"
>
<ListItem title="List item 1" />
<ListItem title="List item 2" />
</ListAccordion>
</ListSection>
<Divider />
<ListSection title="Expandable list with icons">
<ListAccordion icon="star" title="Accordion item 1">
<ListItem icon="thumb-up" title="List item 1" />
<ListItem icon="thumb-down" title="List item 2" />
</ListAccordion>
</ListSection>
</ScrollView>
);
}
}

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

export default withTheme(ListAccordionExample);
2 changes: 1 addition & 1 deletion src/components/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type Props = {
*/
loading?: boolean,
/**
* Name of the icon. Can be a string, an image source or a react component.
* Icon to display for the `Button`.
*/
icon?: IconSource,
/**
Expand Down
5 changes: 1 addition & 4 deletions src/components/DrawerItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ type Props = {
*/
label: string,
/**
* 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 to display for the `DrawerItem`.
*/
icon?: IconSource,
/**
Expand Down
5 changes: 1 addition & 4 deletions src/components/FAB.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ type Props = {
*/
dark?: boolean,
/**
* 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 to display for the `FAB`.
*/
icon: IconSource,
/**
Expand Down
1 change: 1 addition & 0 deletions src/components/Icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const Icon = ({ name, color, size, ...rest }: Props) => {
},
styles.container,
]}
pointerEvents="box-none"
>
{(name: any)}
</View>
Expand Down
204 changes: 204 additions & 0 deletions src/components/List/ListAccordion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/* @flow */

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

type Props = {
/**
* Title text for the list accordion.
*/
title: React.Node,
/**
* Description text for the list accordion.
*/
description?: React.Node,
/**
* Icon to display for the `ListAccordion`.
*/
icon?: React.Node,

/**
* Content of the section.
*/
children: React.Node,

/**
* @optional
*/
theme: Theme,
style?: any,
};

type State = {
expanded: boolean,
};

/**
* `ListAccordion` can be used to display an expandable list item.
*
* <div class="screenshots">
* <img class="medium" src="screenshots/list-accordion-1.png" />
* <img class="medium" src="screenshots/list-accordion-2.png" />
* <img class="medium" src="screenshots/list-accordion-3.png" />
* </div>
*
* ## Usage
* ```js
* import * as React from 'react';
* import { ListAccordion, ListItem, Checkbox } from 'react-native-paper';
*
* const MyComponent = () => (
* <ListAccordion
* title="Accordion"
* icon="folder"
* >
* <ListItem title="First item" />
* <ListItem title="Second item" />
* </ListAccordion>
* );
* ```
*/
class ListAccordion extends React.Component<Props, State> {
state = {
expanded: false,
};

_handlePress = () =>
this.setState(state => ({
expanded: !state.expanded,
}));

render() {
const { icon, title, description, children, theme, style } = this.props;
const titleColor = color(theme.colors.text)
.alpha(0.87)
.rgb()
.string();
const descriptionColor = color(theme.colors.text)
.alpha(0.54)
.rgb()
.string();

return (
<View>
<TouchableRipple
style={[styles.container, style]}
onPress={this._handlePress}
>
<View style={styles.row} pointerEvents="none">
{icon ? (
<View
style={[
styles.item,
styles.icon,
description && styles.multiline,
]}
>
<Icon
name={icon}
size={24}
color={
this.state.expanded
? theme.colors.primary
: descriptionColor
}
/>
</View>
) : null}
<View style={[styles.item, styles.content]}>
<Text
numberOfLines={1}
style={[
styles.title,
{
color: this.state.expanded
? theme.colors.primary
: titleColor,
},
]}
>
{title}
</Text>
{description && (
<Text
numberOfLines={2}
style={[
styles.description,
{
color: descriptionColor,
},
]}
>
{description}
</Text>
)}
</View>
<View style={[styles.item, description && styles.multiline]}>
<Icon
name={
this.state.expanded
? 'keyboard-arrow-up'
: 'keyboard-arrow-down'
}
color={titleColor}
size={24}
/>
</View>
</View>
</TouchableRipple>
{this.state.expanded
? React.Children.map(children, child => {
if (icon && child && !child.props.icon && !child.props.avatar) {
return React.cloneElement(child, {
style: [styles.child, child.props.style],
});
}

return child;
})
: null}
</View>
);
}
}

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

export default withTheme(ListAccordion);
17 changes: 7 additions & 10 deletions src/components/ListItem.js → src/components/List/ListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
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';
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 = {
/**
Expand All @@ -20,10 +20,7 @@ type Props = {
*/
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 to display for the `ListItem`.
*/
icon?: IconSource,
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
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';
import Text from '../Typography/Text';
import withTheme from '../../core/withTheme';
import type { Theme } from '../../types';

type Props = {
/**
Expand Down
Loading

0 comments on commit b6462b7

Please sign in to comment.