Skip to content

Commit

Permalink
feat(foundation): added Badge component
Browse files Browse the repository at this point in the history
  • Loading branch information
bang9 committed Mar 2, 2022
1 parent 1bc173a commit 7b63d90
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 22 deletions.
15 changes: 9 additions & 6 deletions packages/uikit-react-native-foundation/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ export { default as LightUIKitTheme } from './theme/LightUIKitTheme';
export { default as UIKitThemeProvider } from './theme/UIKitThemeProvider';

/** UI **/
export { default as Icon } from './ui/Icon';
export { default as Text } from './ui/Text';
export { default as Modal } from './ui/Modal';
export { default as ActionMenu } from './ui/ActionMenu';
export { default as Alert } from './ui/Alert';
export { default as Button } from './ui/Button';
export { default as Header } from './ui/Header';
export { default as Avatar } from './ui/Avatar';
export { default as ActionMenu } from './ui/ActionMenu';
export { default as Badge } from './ui/Badge';
export { default as Button } from './ui/Button';
export { DialogProvider, useActionMenu, useAlert, usePrompt } from './ui/Dialog';
export { default as Header } from './ui/Header';
export { default as Icon } from './ui/Icon';
export { default as Modal } from './ui/Modal';
export { default as Prompt } from './ui/Prompt';
export { default as Text } from './ui/Text';
export { default as TextInput } from './ui/TextInput';

/** Styles **/
export { default as useHeaderStyle } from './styles/useHeaderStyle';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ const DarkUIKitTheme: UIKitTheme = {
},
},
},

input: {
default: {
active: {
Expand Down Expand Up @@ -105,6 +104,14 @@ const DarkUIKitTheme: UIKitTheme = {
},
},
},
badge: {
default: {
none: {
text: Palette.background600,
background: Palette.primary200,
},
},
},
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ const LightUIKitTheme: UIKitTheme = {
},
},
},
badge: {
default: {
none: {
text: Palette.background50,
background: Palette.primary300,
},
},
},
},
},
};
Expand Down
6 changes: 5 additions & 1 deletion packages/uikit-react-native-foundation/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface UIKitTheme extends AppearanceHelper {
typography: Typography;
}

type Component = 'Header' | 'Button' | 'Dialog' | 'Input';
type Component = 'Header' | 'Button' | 'Dialog' | 'Input' | 'Badge';
type GetColorTree<
Tree extends {
Variant: {
Expand All @@ -49,18 +49,21 @@ export type ComponentColorTree = GetColorTree<{
Button: 'contained' | 'text';
Dialog: 'default';
Input: 'default' | 'underline';
Badge: 'default';
};
State: {
Header: 'none';
Button: 'enabled' | 'pressed' | 'disabled';
Dialog: 'none';
Input: 'active' | 'disabled';
Badge: 'none';
};
ColorPart: {
Header: 'background' | 'borderBottom';
Button: 'background' | 'content';
Dialog: 'background' | 'text' | 'message' | 'highlight' | 'destructive';
Input: 'text' | 'placeholder' | 'background' | 'highlight';
Badge: 'text' | 'background';
};
}>;
type ComponentColors<T extends Component> = {
Expand Down Expand Up @@ -100,6 +103,7 @@ export type UIKitColors = {
button: ComponentColors<'Button'>;
dialog: ComponentColors<'Dialog'>;
input: ComponentColors<'Input'>;
badge: ComponentColors<'Badge'>;
};
};

Expand Down
63 changes: 63 additions & 0 deletions packages/uikit-react-native-foundation/src/ui/Badge/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import { Platform, StyleProp, View, ViewStyle } from 'react-native';

import { truncatedBadgeCount } from '@sendbird/uikit-utils';

import createStyleSheet from '../../styles/createStyleSheet';
import useUIKitTheme from '../../theme/useUIKitTheme';
import Text from '../Text';

type Props = {
count: number;
maxCount?: number;
badgeColor?: string;
textColor?: string;
style?: StyleProp<ViewStyle>;
size?: 'small' | 'default';
};

const Badge: React.FC<Props> = ({ count, maxCount, badgeColor, textColor, style, size = 'default' }) => {
const { colors } = useUIKitTheme();
const isSmall = size === 'small';
return (
<View
style={[
isSmall ? styles.badgeSmall : styles.badgeDefault,
{ backgroundColor: badgeColor ?? colors.ui.badge.default.none.background },
count >= 10 && (isSmall ? styles.badgeSmallPadding : styles.badgeDefaultPadding),
style,
]}
>
<Text caption1 color={textColor ?? colors.ui.badge.default.none.text}>
{truncatedBadgeCount(count, maxCount)}
</Text>
</View>
);
};

const styles = createStyleSheet({
badgeDefault: {
paddingTop: Platform.select({ ios: 2, android: 2 }),
minWidth: 20,
minHeight: 20,
borderRadius: 99,
alignItems: 'center',
justifyContent: 'center',
},
badgeDefaultPadding: {
paddingHorizontal: 8,
},
badgeSmall: {
paddingTop: Platform.select({ ios: 3, android: 2 }),
minWidth: 16,
minHeight: 16,
borderRadius: 99,
alignItems: 'center',
justifyContent: 'center',
},
badgeSmallPadding: {
paddingHorizontal: 4,
},
});

export default Badge;
18 changes: 4 additions & 14 deletions packages/uikit-react-native/src/ui/GroupChannelPreview/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { Image, View } from 'react-native';

import { Icon, Text, createStyleSheet, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
import { truncate, truncatedBadgeCount } from '@sendbird/uikit-utils';
import { Badge, Icon, Text, createStyleSheet, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
import { truncate } from '@sendbird/uikit-utils';

type Props = {
coverUrl: string;
Expand All @@ -19,6 +19,7 @@ type Props = {
muted?: boolean;
};

//TODO: Extract colors to theme color-set
const GroupChannelPreview: React.FC<Props> = ({
coverUrl,
memberCount,
Expand Down Expand Up @@ -77,18 +78,7 @@ const GroupChannelPreview: React.FC<Props> = ({
{body}
</Text>
</View>
{badgeCount > 0 && (
<View
style={[
styles.unreadBadge,
{ backgroundColor: colors.primary, paddingTop: 2, paddingHorizontal: badgeCount >= 10 ? 8 : 0 },
]}
>
<Text caption1 color={colors.background}>
{truncatedBadgeCount(badgeCount)}
</Text>
</View>
)}
{badgeCount > 0 && <Badge count={badgeCount} />}
</View>
</View>
<Separator />
Expand Down
1 change: 1 addition & 0 deletions sample/.storybook/storybook.requires.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ argsEnhancers.forEach((enhancer) => addArgsEnhancer(enhancer));
const getStories = () => {
return [
require("../stories/Avatar.stories.tsx"),
require("../stories/Badge.stories.tsx"),
require("../stories/Button.stories.tsx"),
require("../stories/Dialog.stories.tsx"),
require("../stories/GroupChannelPreview.stories.tsx"),
Expand Down
51 changes: 51 additions & 0 deletions sample/stories/Badge.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react-native';
import React from 'react';
import { View } from 'react-native';

import { Badge as BadgeComponent } from '@sendbird/uikit-react-native-foundation';

const BadgeMeta: ComponentMeta<typeof BadgeComponent> = {
title: 'Badge',
component: BadgeComponent,
argTypes: {
maxCount: {
name: 'Max Count',
control: { type: 'number' },
},
badgeColor: {
name: 'Badge Color',
control: { type: 'color' },
},
textColor: {
name: 'Text Color',
control: { type: 'color' },
},
},
args: {
maxCount: 99,
badgeColor: undefined,
textColor: undefined,
},
};

export default BadgeMeta;

type BadgeStory = ComponentStory<typeof BadgeComponent>;
export const Default: BadgeStory = (args) => (
<>
<View style={{ flexDirection: 'row', width: '100%', justifyContent: 'space-evenly', marginBottom: 12 }}>
<BadgeComponent {...args} count={1} />
<BadgeComponent {...args} count={30} />
<BadgeComponent {...args} count={60} />
<BadgeComponent {...args} count={90} />
<BadgeComponent {...args} count={120} />
</View>
<View style={{ flexDirection: 'row', width: '100%', justifyContent: 'space-evenly' }}>
<BadgeComponent {...args} size={'small'} count={1} />
<BadgeComponent {...args} size={'small'} count={30} />
<BadgeComponent {...args} size={'small'} count={60} />
<BadgeComponent {...args} size={'small'} count={90} />
<BadgeComponent {...args} size={'small'} count={120} />
</View>
</>
);

0 comments on commit 7b63d90

Please sign in to comment.