Skip to content

Commit f89048e

Browse files
feat: implemented input chip
1 parent 46c6b21 commit f89048e

File tree

11 files changed

+122
-5
lines changed

11 files changed

+122
-5
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
Computools react native material components package
44

5+
![Material desgin Figma](https://www.figma.com/design/MY4zoWhMQUMOMIfBGcgSpy/Material-3-Design-Kit-(Community)?node-id=47909-2&p=f&t=Fo0xFwhmWhLMqS8Z-0)
6+
![Material icons design Figma](https://www.figma.com/design/siKJo238QbcA9I2EqYMZ9y/Material-Design-Icons-(Community)?node-id=2402-2207&node-type=canvas&t=xqHD7AwdyHpKWsur-0)
7+
58
## Installation
69

710
1. ```yarn add @computools/react-native-material-components```
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React, {type ReactNode} from 'react';
2+
import {TouchableOpacity, Text, type TouchableOpacityProps, type StyleProp, type TextStyle} from 'react-native';
3+
4+
import {styles} from './base-chip.styles';
5+
import {useTypography} from '../../typography/useTypography.component';
6+
7+
export interface BaseChipProps extends TouchableOpacityProps {
8+
label: string;
9+
10+
leadingIcon?: ReactNode;
11+
trailingIcon?: ReactNode;
12+
labelStyle?: StyleProp<TextStyle>;
13+
}
14+
15+
export const BaseChip: React.FC<BaseChipProps> = ({label, leadingIcon, trailingIcon, style, ...props}) => {
16+
const {labelLarge} = useTypography();
17+
18+
return (
19+
<TouchableOpacity style={[styles.container, style]} hitSlop={8} {...props}>
20+
{leadingIcon}
21+
<Text style={[[styles.label, labelLarge]]}>{label}</Text>
22+
{trailingIcon}
23+
</TouchableOpacity>
24+
);
25+
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {StyleSheet} from 'react-native';
2+
3+
export const styles = StyleSheet.create({
4+
container: {
5+
flexDirection: 'row',
6+
alignItems: 'center',
7+
gap: 4,
8+
9+
borderRadius: 8,
10+
paddingVertical: 6,
11+
paddingHorizontal: 8,
12+
},
13+
label: {
14+
paddingHorizontal: 4,
15+
},
16+
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React, {useMemo} from 'react';
2+
import {Image, StyleSheet} from 'react-native';
3+
4+
import {CloseIcon} from '../../icons';
5+
import {styles} from './input-chip.styles';
6+
import {useTheme} from '../../theme/useTheme.hook';
7+
import {type IconProps} from '../../icons/icon-props';
8+
import {BaseChip, type BaseChipProps} from '../base-chip/BaseChip.component';
9+
10+
interface InputChipProps<T extends IconProps> extends BaseChipProps {
11+
selected?: boolean;
12+
imageUrl?: string;
13+
LeadingIcon?: React.FC<T>;
14+
leadingIconProps?: T;
15+
hasTrailingIcon?: boolean;
16+
}
17+
18+
export const InputChip = <T extends IconProps>({
19+
selected = false,
20+
LeadingIcon,
21+
imageUrl,
22+
hasTrailingIcon = true,
23+
leadingIconProps = {} as T,
24+
style,
25+
...props
26+
}: InputChipProps<T>) => {
27+
const {surface, secondaryContainer, outline, primary} = useTheme();
28+
29+
const onContainerColor = selected ? secondaryContainer.text : surface.textVariant;
30+
31+
const dynamicStyles = useMemo(
32+
() =>
33+
StyleSheet.create({
34+
container: {
35+
borderWidth: Number(!selected),
36+
borderColor: outline,
37+
backgroundColor: selected ? secondaryContainer.background : 'transparent',
38+
},
39+
label: {
40+
color: onContainerColor,
41+
},
42+
}),
43+
[selected, onContainerColor]
44+
);
45+
46+
const renderLeadingAvatar = () => (imageUrl ? <Image style={styles.leadingImage} source={{uri: imageUrl}} /> : null);
47+
48+
return (
49+
<BaseChip
50+
style={[dynamicStyles.container, imageUrl ? styles.chipWithAvatarContainer : [], style]}
51+
labelStyle={dynamicStyles.label}
52+
leadingIcon={LeadingIcon ? <LeadingIcon size={18} color={primary.background} {...leadingIconProps} /> : renderLeadingAvatar()}
53+
trailingIcon={hasTrailingIcon ? <CloseIcon size={18} color={onContainerColor} /> : null}
54+
{...props}
55+
/>
56+
);
57+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import {StyleSheet} from 'react-native';
2+
3+
export const styles = StyleSheet.create({
4+
chipWithAvatarContainer: {
5+
paddingStart: 4,
6+
paddingVertical: 4,
7+
borderRadius: 30,
8+
},
9+
leadingImage: {
10+
width: 24,
11+
height: 24,
12+
borderRadius: 12,
13+
},
14+
});

src/icons/attach-file-icon/AttachFileIcon.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {path} from './path.json';
55
import type {IconProps} from '../icon-props';
66

77
const DEFAULT_SIZE = 24;
8-
const DEFAULT_COLOR = '#ffffff';
8+
const DEFAULT_COLOR = '#000';
99

1010
export const AttachFileIcon: React.FC<IconProps> = ({color = DEFAULT_COLOR, size = DEFAULT_SIZE}) => (
1111
<Svg viewBox="0 0 24 24" width={size} height={size} fill={'none'}>

src/icons/check-small-icon/CheckSmallIcon.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {path} from './path.json';
55
import type {IconProps} from '../icon-props';
66

77
const DEFAULT_SIZE = 24;
8-
const DEFAULT_COLOR = '#ffffff';
8+
const DEFAULT_COLOR = '#000';
99

1010
export const CheckSmallIcon: React.FC<IconProps> = ({color = DEFAULT_COLOR, size = DEFAULT_SIZE}) => (
1111
<Svg viewBox="0 0 24 24" width={size} height={size} fill={'none'}>

src/icons/close-icon/CloseIcon.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {path} from './path.json';
55
import type {IconProps} from '../icon-props';
66

77
const DEFAULT_SIZE = 24;
8-
const DEFAULT_COLOR = '#ffffff';
8+
const DEFAULT_COLOR = '#000';
99

1010
export const CloseIcon: React.FC<IconProps> = ({color = DEFAULT_COLOR, size = DEFAULT_SIZE}) => (
1111
<Svg viewBox="0 0 24 24" width={size} height={size}>

src/icons/more-vert-icon/MoreVertIcon.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {path} from './path.json';
55
import type {IconProps} from '../icon-props';
66

77
const DEFAULT_SIZE = 24;
8-
const DEFAULT_COLOR = '#ffffff';
8+
const DEFAULT_COLOR = '#000';
99

1010
export const MoreVertIcon: React.FC<IconProps> = ({color = DEFAULT_COLOR, size = DEFAULT_SIZE}) => (
1111
<Svg viewBox="0 0 24 24" width={size} height={size} fill={'none'}>

src/icons/today-icon/TodayIcon.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {path} from './path.json';
55
import type {IconProps} from '../icon-props';
66

77
const DEFAULT_SIZE = 24;
8-
const DEFAULT_COLOR = '#ffffff';
8+
const DEFAULT_COLOR = '#000';
99

1010
export const TodayIcon: React.FC<IconProps> = ({color = DEFAULT_COLOR, size = DEFAULT_SIZE}) => (
1111
<Svg viewBox="0 0 24 24" width={size} height={size} fill={'none'}>

0 commit comments

Comments
 (0)