feat: add Chip component

This commit is contained in:
Grzegorz Gawrysiak
2018-05-05 21:59:45 +02:00
committed by Satyajit Sahoo
parent 9fd6db4ec7
commit b9aa79503c
10 changed files with 556 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
example/assets/avatar.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -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);

View File

@@ -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';
@@ -35,6 +36,7 @@ export const examples = {
button: ButtonExample,
card: CardExample,
checkbox: CheckboxExample,
chip: ChipExample,
dialog: DialogExample,
divider: DividerExample,
fab: FABExample,

121
src/components/Chip.js Normal file
View File

@@ -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);

View File

@@ -37,7 +37,7 @@ export type IconSource =
type IconProps = {
color: string,
size?: number,
size: number,
};
type Props = IconProps & {

View File

@@ -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();
});

View File

@@ -0,0 +1,344 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders chip with icon 1`] = `
<View
accessibilityComponentType={undefined}
accessibilityLabel={undefined}
accessibilityTraits={undefined}
accessible={true}
hitSlop={undefined}
nativeID={undefined}
onLayout={undefined}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Array [
Object {
"alignItems": "center",
"borderRadius": 16,
"flexDirection": "row",
"justifyContent": "space-around",
"margin": 4,
},
Object {
"backgroundColor": "rgba(0, 0, 0, 0.12)",
},
undefined,
]
}
testID={undefined}
>
<Text
accessible={true}
allowFontScaling={false}
ellipsizeMode="tail"
pointerEvents="none"
style={
Array [
Object {
"color": "rgba(0, 0, 0, 0.54)",
"fontSize": 32,
},
Object {
"backgroundColor": "transparent",
},
Object {
"fontFamily": "Material Icons",
"fontStyle": "normal",
"fontWeight": "normal",
},
]
}
>
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#000000",
"fontFamily": "Helvetica Neue",
},
Array [
Object {
"marginVertical": 8,
},
Object {
"color": "rgba(0, 0, 0, 0.87)",
"marginLeft": 8,
"marginRight": 12,
},
],
]
}
theme={
Object {
"colors": Object {
"accent": "#ff4081",
"background": "#fafafa",
"disabled": "rgba(0, 0, 0, 0.26)",
"error": "#ff1744",
"paper": "#ffffff",
"placeholder": "rgba(0, 0, 0, 0.38)",
"primary": "#3f51b5",
"text": "#000000",
},
"dark": false,
"fonts": Object {
"light": "HelveticaNeue-Light",
"medium": "HelveticaNeue-Medium",
"regular": "Helvetica Neue",
"thin": "HelveticaNeue-Thin",
},
"roundness": 2,
}
}
>
Example Chip
</Text>
</View>
`;
exports[`renders chip with onPress 1`] = `
<View
accessibilityComponentType={undefined}
accessibilityLabel={undefined}
accessibilityTraits={undefined}
accessible={true}
hitSlop={undefined}
nativeID={undefined}
onLayout={undefined}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Array [
Object {
"alignItems": "center",
"borderRadius": 16,
"flexDirection": "row",
"justifyContent": "space-around",
"margin": 4,
},
Object {
"backgroundColor": "rgba(0, 0, 0, 0.12)",
},
undefined,
]
}
testID={undefined}
>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#000000",
"fontFamily": "Helvetica Neue",
},
Array [
Object {
"marginVertical": 8,
},
Object {
"color": "rgba(0, 0, 0, 0.87)",
"marginLeft": 12,
"marginRight": 12,
},
],
]
}
theme={
Object {
"colors": Object {
"accent": "#ff4081",
"background": "#fafafa",
"disabled": "rgba(0, 0, 0, 0.26)",
"error": "#ff1744",
"paper": "#ffffff",
"placeholder": "rgba(0, 0, 0, 0.38)",
"primary": "#3f51b5",
"text": "#000000",
},
"dark": false,
"fonts": Object {
"light": "HelveticaNeue-Light",
"medium": "HelveticaNeue-Medium",
"regular": "Helvetica Neue",
"thin": "HelveticaNeue-Thin",
},
"roundness": 2,
}
}
>
Example Chip
</Text>
</View>
`;
exports[`renders deletable chip 1`] = `
<View
accessibilityComponentType={undefined}
accessibilityLabel={undefined}
accessibilityTraits={undefined}
accessible={true}
hitSlop={undefined}
nativeID={undefined}
onLayout={undefined}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Array [
Object {
"alignItems": "center",
"borderRadius": 16,
"flexDirection": "row",
"justifyContent": "space-around",
"margin": 4,
},
Object {
"backgroundColor": "rgba(0, 0, 0, 0.12)",
},
undefined,
]
}
testID={undefined}
>
<Text
accessible={true}
allowFontScaling={false}
ellipsizeMode="tail"
pointerEvents="none"
style={
Array [
Object {
"color": "rgba(0, 0, 0, 0.54)",
"fontSize": 32,
},
Object {
"backgroundColor": "transparent",
},
Object {
"fontFamily": "Material Icons",
"fontStyle": "normal",
"fontWeight": "normal",
},
]
}
>
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#000000",
"fontFamily": "Helvetica Neue",
},
Array [
Object {
"marginVertical": 8,
},
Object {
"color": "rgba(0, 0, 0, 0.87)",
"marginLeft": 8,
"marginRight": 0,
},
],
]
}
theme={
Object {
"colors": Object {
"accent": "#ff4081",
"background": "#fafafa",
"disabled": "rgba(0, 0, 0, 0.26)",
"error": "#ff1744",
"paper": "#ffffff",
"placeholder": "rgba(0, 0, 0, 0.38)",
"primary": "#3f51b5",
"text": "#000000",
},
"dark": false,
"fonts": Object {
"light": "HelveticaNeue-Light",
"medium": "HelveticaNeue-Medium",
"regular": "Helvetica Neue",
"thin": "HelveticaNeue-Thin",
},
"roundness": 2,
}
}
>
Example Chip
</Text>
<View
accessibilityComponentType={undefined}
accessibilityLabel={undefined}
accessibilityTraits={undefined}
accessible={true}
hitSlop={undefined}
nativeID={undefined}
onLayout={undefined}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"padding": 6,
}
}
testID={undefined}
>
<Text
accessible={true}
allowFontScaling={false}
ellipsizeMode="tail"
pointerEvents="none"
style={
Array [
Object {
"color": "rgba(0, 0, 0, 0.54)",
"fontSize": 20,
},
Object {
"backgroundColor": "transparent",
},
Object {
"fontFamily": "Material Icons",
"fontStyle": "normal",
"fontWeight": "normal",
},
]
}
>
</Text>
</View>
</View>
`;

View File

@@ -17,6 +17,7 @@ export { default as CardActions } from './components/Card/CardActions';
export { default as CardContent } from './components/Card/CardContent';
export { default as CardCover } from './components/Card/CardCover';
export { default as Checkbox } from './components/Checkbox';
export { default as Chip } from './components/Chip';
export { default as Dialog } from './components/Dialog/Dialog';
export { default as DialogActions } from './components/Dialog/DialogActions';
export { default as DialogContent } from './components/Dialog/DialogContent';