mirror of
https://github.com/zhigang1992/react-native-paper.git
synced 2026-06-11 08:13:29 +08:00
feat: add Chip component
This commit is contained in:
committed by
Satyajit Sahoo
parent
9fd6db4ec7
commit
b9aa79503c
BIN
docs/assets/screenshots/chip-1.png
Normal file
BIN
docs/assets/screenshots/chip-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
BIN
docs/assets/screenshots/chip-2.png
Normal file
BIN
docs/assets/screenshots/chip-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
BIN
example/assets/avatar.jpg
Normal file
BIN
example/assets/avatar.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
56
example/src/ChipExample.js
Normal file
56
example/src/ChipExample.js
Normal 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);
|
||||
@@ -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
121
src/components/Chip.js
Normal 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);
|
||||
@@ -37,7 +37,7 @@ export type IconSource =
|
||||
|
||||
type IconProps = {
|
||||
color: string,
|
||||
size?: number,
|
||||
size: number,
|
||||
};
|
||||
|
||||
type Props = IconProps & {
|
||||
|
||||
31
src/components/__tests__/Chip.test.js
Normal file
31
src/components/__tests__/Chip.test.js
Normal 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();
|
||||
});
|
||||
344
src/components/__tests__/__snapshots__/Chip.test.js.snap
Normal file
344
src/components/__tests__/__snapshots__/Chip.test.js.snap
Normal 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>
|
||||
`;
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user