Skip to content

Commit

Permalink
feat: add Chip component
Browse files Browse the repository at this point in the history
  • Loading branch information
gawrysiak authored and satya164 committed May 6, 2018
1 parent 9fd6db4 commit b9aa795
Show file tree
Hide file tree
Showing 10 changed files with 556 additions and 1 deletion.
Binary file added docs/assets/screenshots/chip-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/chip-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 example/assets/avatar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 56 additions & 0 deletions example/src/ChipExample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* @flow */

import * as React from 'react';
import { View, StyleSheet, Image } from 'react-native';
import { Chip, withTheme } from 'react-native-paper';
import type { Theme } from 'react-native-paper/types';

type Props = {
theme: Theme,
};

class ChipExample extends React.Component<Props> {
static title = 'Chip';

render() {
const {
theme: {
colors: { background },
},
} = this.props;
return (
<View style={[styles.container, { backgroundColor: background }]}>
<View style={styles.row}>
<Chip onPress={() => {}}>Simple Chip</Chip>
<Chip onDelete={() => {}}>Chip with delete button</Chip>
<Chip icon="info">Chip with icon</Chip>
<Chip
icon={({ size }) => (
<Image
source={require('../assets/avatar.jpg')}
style={{ height: size, width: size, borderRadius: size / 2 }}
/>
)}
onDelete={() => {}}
>
Chip with image
</Chip>
</View>
</View>
);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 4,
},

row: {
flexDirection: 'row',
flexWrap: 'wrap',
},
});

export default withTheme(ChipExample);
2 changes: 2 additions & 0 deletions example/src/ExampleList.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import BottomNavigationExample from './BottomNavigationExample';
import ButtonExample from './ButtonExample';
import CardExample from './CardExample';
import CheckboxExample from './CheckboxExample';
import ChipExample from './ChipExample';
import DialogExample from './DialogExample';
import DividerExample from './DividerExample';
import FABExample from './FABExample';
Expand Down Expand Up @@ -35,6 +36,7 @@ export const examples = {
button: ButtonExample,
card: CardExample,
checkbox: CheckboxExample,
chip: ChipExample,
dialog: DialogExample,
divider: DividerExample,
fab: FABExample,
Expand Down
121 changes: 121 additions & 0 deletions src/components/Chip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/* @flow */

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

type Props = {
/**
* Text content of the `Chip`.
*/
children: React.Node,
/**
* Icon to display for the `Chip`.
*/
icon?: IconSource,
/**
* Function to execute on press.
*/
onPress?: () => mixed,
/**
* Function to execute on delete. The delete button appears only when this prop is specified.
*/
onDelete?: () => mixed,
style?: any,
/**
* @optional
*/
theme: Theme,
};

/**
* A Chip can be used to display entities in small blocks.
*
* <div class="screenshots">
* <img src="screenshots/chip-1.png" />
* <img src="screenshots/chip-2.png" />
* </div>
*
* ## Usage
* ```js
* import * as React from 'react';
* import { Chip } from 'react-native-paper';
*
* const MyComponent = () => (
* <Chip icon="info" onPress={() => {}}>Example Chip</Chip>
* );
* ```
*/
class Chip extends React.Component<Props> {
render() {
const { children, icon, onPress, onDelete, style, theme } = this.props;
const { dark, colors } = theme;

const backgroundColor = color(dark ? white : black)
.alpha(0.12)
.rgb()
.string();
const textColor = dark
? colors.text
: color(colors.text)
.alpha(0.87)
.rgb()
.string();
const iconColor = color(colors.text)
.alpha(dark ? 0.7 : 0.54)
.rgb()
.string();

return (
<TouchableWithoutFeedback onPress={onPress}>
<View style={[styles.content, { backgroundColor }, style]}>
{icon ? <Icon name={icon} color={iconColor} size={32} /> : null}
<Text
numberOfLines={1}
style={[
styles.text,
{
color: textColor,
marginLeft: icon ? 8 : 12,
marginRight: onDelete ? 0 : 12,
},
]}
>
{children}
</Text>
{onDelete ? (
<TouchableWithoutFeedback onPress={onDelete}>
<View style={styles.delete}>
<Icon name="cancel" size={20} color={iconColor} />
</View>
</TouchableWithoutFeedback>
) : null}
</View>
</TouchableWithoutFeedback>
);
}
}

const styles = StyleSheet.create({
content: {
borderRadius: 16,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-around',
margin: 4,
},
delete: {
padding: 6,
},
text: {
marginVertical: 8,
},
});

export default withTheme(Chip);
2 changes: 1 addition & 1 deletion src/components/Icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export type IconSource =

type IconProps = {
color: string,
size?: number,
size: number,
};

type Props = IconProps & {
Expand Down
31 changes: 31 additions & 0 deletions src/components/__tests__/Chip.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* @flow */

import * as React from 'react';
import renderer from 'react-test-renderer';
import Chip from '../Chip';

it('renders chip with onPress', () => {
const tree = renderer
.create(<Chip onPress={() => {}}>Example Chip</Chip>)
.toJSON();

expect(tree).toMatchSnapshot();
});

it('renders chip with icon', () => {
const tree = renderer.create(<Chip icon="info">Example Chip</Chip>).toJSON();

expect(tree).toMatchSnapshot();
});

it('renders deletable chip', () => {
const tree = renderer
.create(
<Chip icon="info" onDelete={() => {}}>
Example Chip
</Chip>
)
.toJSON();

expect(tree).toMatchSnapshot();
});
Loading

0 comments on commit b9aa795

Please sign in to comment.