Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Badge & avatar updated #106

Merged
merged 2 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions doc/docs/components/avatar.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ import { View } from 'react-native';
const App = () => (
<View style={{ alignItems: 'center', flexDirection: 'row' }}>
<Avatar
borderStyle="circular"
variant="circular"
size="medium"
badgePosition="bottom"
badgeContent={<Icon name="penguin" type="material-community" size={20} />}
source={{ uri: 'https://randomuser.me/api/portraits/men/62.jpg' }}
/>
</View>
Expand All @@ -38,16 +36,13 @@ export default App;
|-----------------------|-------------------------------------------------|----------|--------------------------------------------------------------------------------------------|
| size | <code>'small' \| 'medium'</code> | No | The size of the avatar. Default value: ``'medium' `` |
| source |[``ImageSourcePropType``](https://reactnative.dev/docs/image#imagesource)| No | Used to specify the image source. |
| borderStyle |<code>'circular' \| 'rounded'</code> | No | Specifies the border type of the avatar. Default value: ``'circular'``|
| variant |<code>'circular' \| 'rounded'</code> | No | Specifies the border type of the avatar. Default value: ``'circular'``|
| avatarIcon |``React.ReactNode `` | No | Used to add icon to avatar. |
| containerStyle |[``StyleProp<ViewStyle>``](https://reactnative.dev/docs/view-style-props)| No | Additional styles to apply to the avatar container. |
| label |``string``| No | Represents the initials of the name to be written on the avatar. |
| labelStyle |[``StyleProp<TextStyle>``](https://reactnative.dev/docs/text-style-props)| No | Additional styles to apply to the label text. |
| badgePosition |<code>'top' \| 'bottom'</code>| No | Badge component location. |
| badgeStyle |``{ containerStyle?: StyleProp<ViewStyle>, textStyle?: StyleProp<TextStyle> } `` | No | Additional styles to apply to the badge component.|
| badgeContent |``React.ReactNode `` | No | Additional content to apply to the badge component. |
| theme |``UITheme `` | No | The theme to use for the component. |
| typography |``UITypography `` | No | The typography to use for the component. |
| typography |``UITypography

## Avatar Group

Expand Down Expand Up @@ -88,7 +83,7 @@ export default App;

| Prop name | Type | Required | Description |
|-----------------------|-------------------------------------------------|----------|--------------------------------------------------------------------------------------------|
| avatarsType | ``Array<{``<br />`` source?: ImageSourcePropType,``<br />`` borderStyle?: 'circular' \| 'rounded',``<br />`` avatarIcon?: React.ReactNode,``<br />`` containerStyle?: StyleProp<ViewStyle>,``<br />`` label?: string,``<br />`` labelStyle?: StyleProp<TextStyle>,``<br />`` badgePosition?: 'top' \| 'bottom',``<br />`` badgeStyle?: { containerStyle?: StyleProp<ViewStyle>,``<br />`` textStyle?: StyleProp<TextStyle> }, ``<br />``badgeContent?: React.ReactNode ``<br />``}> ``| Yes | Takes avatar props into array. |
| avatarsType | ``Array<{``<br />`` source?: ImageSourcePropType,``<br />`` variant?: 'circular' \| 'rounded',``<br />`` avatarIcon?: React.ReactNode,``<br />`` containerStyle?: StyleProp<ViewStyle>,``<br />`` label?: string,``<br />`` labelStyle?: StyleProp<TextStyle>,``<br />`` textStyle?: StyleProp<TextStyle> }, ``<br />``}> ``| Yes | Takes avatar props into array. |
| avatarLimit |``number`` | No | Limit of avatars to be listed. Default value: ``10`` |
| limitContainerStyle |<code>'circular' \| 'rounded'</code> | No | Additional styles to apply to the limit container. |
| theme |``UITheme `` | No | The theme to use for the component. |
Expand Down
6 changes: 3 additions & 3 deletions doc/docs/components/badge.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import Badge from '../../components/Badge';

const App = () => (
<View style={{ alignItems: 'center', flexDirection: 'row' }}>
<Badge containerStyle={{ margin: 10, backgroundColor: '#9A9A9A' }} borderStyle="rectangular" size="medium" icon={<AntDesign name="apple1" color="#fff" />} />
<Badge containerStyle={{ margin: 10, backgroundColor: '#FF3434' }} borderStyle="rectangular" size="medium" icon={<AntDesign name="android1" color="#fff" />} />
<Badge containerStyle={{ margin: 10, backgroundColor: '#9A9A9A' }} variant="rectangular" size="medium" icon={<AntDesign name="apple1" color="#fff" />} />
<Badge containerStyle={{ margin: 10, backgroundColor: '#FF3434' }} variant="rectangular" size="medium" icon={<AntDesign name="android1" color="#fff" />} />
</View>
);

Expand Down Expand Up @@ -65,7 +65,7 @@ export default App;
| size | <code> 'small' \| 'medium'</code> | No | The size of the badge. Default value: ``'medium'`` |
| containerStyle |[``StyleProp<ViewStyle>``](https://reactnative.dev/docs/view-style-props)| No | Additional styles to apply to the badge container. |
| labelStyle |[``StyleProp<TextStyle>``](https://reactnative.dev/docs/text-style-props)| No | Additional styles to apply to the children text. |
| borderStyle |<code>'circular' \| 'rectangular'</code> | No | Specifies the border type of the badge. Default value: ``'circular'`` |
| variant |<code>'circular' \| 'rectangular'</code> | No | Specifies the border type of the badge. Default value: ``'circular'`` |
| icon |[``React.ReactNode``](https://reactnative.dev/docs/react-node) | No | Icon to be added to badge. |
| children |[``React.ReactNode``](https://reactnative.dev/docs/react-node) | Yes | A required prop that represents the content to display within the Badge component. |
| position |<code>'top-right'\| 'top-left' \| 'bottom-left' \| 'bottom-right'</code> | No | Position the Badge component. Default value: ``'top-right'`` |
Expand Down
42 changes: 13 additions & 29 deletions src/components/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,48 @@ import { Image, View, Text } from 'react-native';
import type { AvatarProps, FCCWD } from '../../types';
import { applyDefaults } from '../../core/KitraProvider';
import OcticonsIcon from '../Icons/Octicons';
import Badge from '../Badge/Badge';

const Avatar : FCCWD<AvatarProps> = (
{ typography,
theme,
source,
size = 'medium',
borderStyle,
variant,
containerStyle,
badgeContent = 'circular',
avatarIcon = <OcticonsIcon name="person" size={sizes[size].iconSize} color={theme?.primary} />,
label,
labelStyle,
badgeStyle,
badgePosition },
labelStyle },
) => {
const splitName = (string:string) => {
const avatarText = string.trim().replace(/ {1,9}/g, ' ').split(' ').reduce((accumulator, currentValue:any) => accumulator.concat(currentValue[0]), '');
return avatarText;
};

const labelTypography = {
medium: {
...typography?.heading.h2,
},
small: {
...typography?.body.smedium,
},
};
return (
<View style={[{ width: sizes[size].width,
height: sizes[size].height,
borderRadius: borderStyle === 'rounded' ? 10 : 50,
borderRadius: variant === 'rounded' ? 10 : 50,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: theme?.primary15 }, containerStyle]}
>
{(() => {
if (source) {
return (
<Image source={source} resizeMethod="auto" style={[{ width: sizes[size].width, height: sizes[size].height, borderRadius: borderStyle === 'rounded' ? 10 : 50 }]} />
<Image source={source} resizeMethod="auto" style={[{ width: sizes[size].width, height: sizes[size].height, borderRadius: variant === 'rounded' ? 10 : 50 }]} />
);
}
if (label) {
return (
<Text style={[{ fontSize: size === 'medium' ? typography?.heading.h2.fontSize : typography?.body.smedium.fontSize,
lineHeight: size === 'medium' ? typography?.heading.h2.lineHeight : typography?.body.smedium.lineHeight,
color: theme?.primary }, labelStyle]}
>
<Text style={[{ color: theme?.primary }, labelTypography[size], labelStyle]}>
{splitName(label)}

</Text>
Expand All @@ -53,23 +54,6 @@ const Avatar : FCCWD<AvatarProps> = (
avatarIcon
);
})()}
{badgePosition && (
<View style={[
{ position: 'absolute', borderRadius: 50, padding: size === 'small' ? 2 : 4, right: size === 'small' ? -5 : (borderStyle === 'circular' ? 0 : -10) },
badgePosition === 'bottom' ?
{ bottom: size === 'small' ? -2 : (borderStyle === 'circular' ? 0 : -10) } :
{ top: size === 'small' ? -5 : (borderStyle === 'circular' ? 0 : -10) }]}
>
<Badge
typography={typography}
theme={theme}
size={size === 'small' ? 'small' : 'medium'}
textStyles={badgeStyle?.textStyle}
containerStyle={badgeStyle?.containerStyle}
icon={badgeContent}
/>
</View>
)}

</View>
);
Expand Down
7 changes: 2 additions & 5 deletions src/components/Avatar/AvatarGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,11 @@ const AvatarGroup: FCCWD<AvatarGroupProps> = (
typography={typography}
key={index}
source={item?.source}
borderStyle={item?.borderStyle}
variant={item?.variant}
avatarIcon={item?.avatarIcon}
containerStyle={item?.containerStyle}
size="small"
label={item?.label}
badgePosition={item?.badgePosition}
badgeStyle={item?.badgeStyle}
badgeContent={item?.badgeContent}
/>

</View>
Expand All @@ -43,7 +40,7 @@ const AvatarGroup: FCCWD<AvatarGroupProps> = (
<Avatar
theme={theme}
typography={typography}
borderStyle="circular"
variant="circular"
size="small"
containerStyle={{ backgroundColor: limitContainerStyle?.backgroundColor || '#82B98E' }}
avatarIcon={avatarIcon}
Expand Down
75 changes: 46 additions & 29 deletions src/components/Badge/Badge.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Text, StyleSheet, View } from 'react-native';
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
import React, { useState } from 'react';
import type { BadgeProps, FCCWD } from '../../types';
import { applyDefaults } from '../../core/KitraProvider';

Expand All @@ -15,6 +16,12 @@ const sizes = {
fontSize: 8,
},
};
const badgePositions = {
topRight: { top: 0, right: 0 },
topLeft: { top: 0, left: 0 },
bottomRight: { bottom: 0, right: 0 },
bottomLeft: { bottom: 0, left: 0 },
};
const badgeStyles = StyleSheet.create({
container: {
justifyContent: 'center', alignItems: 'center',
Expand All @@ -27,34 +34,44 @@ const Badge : FCCWD<BadgeProps> = (
size = 'medium',
containerStyle,
textStyles,
borderStyle = 'circular',
icon },
) => (
<View>
{visible ? (
<Animated.View
exiting={FadeOut.duration(300)}
entering={FadeIn.duration(400)}
style={[badgeStyles.container,
[borderStyle === 'circular' ? { width: size === 'medium' ? (label || icon ? 30 : 24) : 10,
height: size === 'medium' ? (label || icon ? 30 : 24) : 10 } :
{ paddingVertical: size === 'medium' ? 4 : 3, paddingHorizontal: size === 'medium' ? 8 : 6 },
{ backgroundColor: theme?.primary, borderRadius: borderStyle === 'circular' ? 50 : 3 }],
containerStyle]}
>
{(() => {
if (label) {
return <Text style={[{ color: theme?.white, fontSize: sizes[size]?.fontSize }, textStyles]}>{label}</Text>;
}
if (icon) {
return icon;
}
return null;
})()}
</Animated.View>
)
: null
variant = 'circular',
icon,
badgePosition = 'bottomRight',
children },
) => {
const [childSize, setChildSize] = useState({ width: 0, height: 0 });
return (
<View style={{ alignItems: 'center', backgroundColor: 'transparent', justifyContent: 'center', width: childSize.width + 10, height: childSize.height + 10 }}>
{visible ? (
<View style={[{ position: 'absolute', zIndex: 10, backgroundColor: theme?.white, borderRadius: 50, padding: variant === 'circular' ? 3 : 0 }, badgePositions[badgePosition]]}>
<Animated.View
exiting={FadeOut.duration(300)}
entering={FadeIn.duration(400)}
style={[badgeStyles.container,
[variant === 'circular' ? { width: size === 'medium' ? (label || icon ? 30 : 24) : 10, height: size === 'medium' ? (label || icon ? 30 : 24) : 10 }
:
{ paddingVertical: size === 'medium' ? 4 : 3, paddingHorizontal: size === 'medium' ? 8 : 6 },
{ backgroundColor: theme?.primary, borderRadius: variant === 'circular' ? 50 : 3 }],
containerStyle]}
>
{(() => {
if (label) {
return <Text style={[{ color: theme?.white, fontSize: sizes[size]?.fontSize }, textStyles]}>{label}</Text>;
}
if (icon) {
return icon;
}
return null;
})()}
</Animated.View>
</View>
)
: null
}
</View>
);
<View onLayout={e => setChildSize({ width: e.nativeEvent.layout.width, height: e.nativeEvent.layout.height })}>
{children}
</View>
</View>
);
};
export default applyDefaults(Badge);
Loading
Loading