Skip to content

Commit

Permalink
Merge pull request #93 from sopt-makers/feat/#89-chip
Browse files Browse the repository at this point in the history
feat(Chip): Chip 컴포넌트 개발
  • Loading branch information
sohee-K authored Jun 13, 2024
2 parents dd4ab2d + 1778fe0 commit 3a4651c
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 8 deletions.
58 changes: 58 additions & 0 deletions apps/docs/src/stories/Chip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Meta, StoryObj } from '@storybook/react';
import { Chip } from '@sopt-makers/ui';
import { IconCheck, IconAlarmClock } from '@sopt-makers/icons';

interface ChipOwnProps {
iconColor?: string;
size?: 'sm' | 'md';
active?: boolean;
LeftIcon?: React.ComponentType;
RightIcon?: React.ComponentType;
}

type ChipStoryProps = ChipOwnProps & { children: string };

export default {
title: 'Components/Chip',
component: Chip,
tags: ['autodocs'],
} as Meta<ChipStoryProps>;

// 기본 chip 스토리
export const Default: StoryObj<ChipStoryProps> = {
args: {
children: 'Default Chip',
size: 'sm',
active: false,
},
};

// active chip 스토리
export const Active: StoryObj<ChipStoryProps> = {
args: {
children: 'Active Chip',
size: 'md',
active: true,
},
};

// left icon (with color) chip 스토리
export const LeftIcon: StoryObj<ChipStoryProps> = {
args: {
children: 'Chip with a LeftIcon',
size: 'sm',
active: false,
LeftIcon: IconCheck,
},
};

// colored right icon chip 스토리
export const RightIconWithColor: StoryObj<ChipStoryProps> = {
args: {
children: 'Chip with a colored RightIcon',
iconColor: '#cd24ea',
size: 'sm',
active: false,
RightIcon: IconAlarmClock,
},
};
62 changes: 62 additions & 0 deletions packages/ui/Chip/Chip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { ButtonHTMLAttributes, CSSProperties, ComponentType } from 'react';
import { root, activeStyle, sprinkles } from './style.css';

interface IconProps {
color?: string;
style?: CSSProperties;
}

interface BaseChipProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children?: string | number;
className?: string;
iconColor?: string;
size?: 'sm' | 'md';
active?: boolean;
}

interface LeftIconChipProps extends BaseChipProps {
LeftIcon?: ComponentType<IconProps>;
RightIcon?: never;
}

interface RightIconChipProps extends BaseChipProps {
LeftIcon?: never;
RightIcon?: ComponentType<IconProps>;
}

type ChipProps = LeftIconChipProps | RightIconChipProps;

function Chip({
children,
className,
LeftIcon,
RightIcon,
iconColor,
size = 'sm',
active = false,
...buttonElementProps
}: ChipProps) {
return (
<button
className={`${root} ${className} ${sprinkles({
padding: size,
fontStyle: size,
})} ${active && activeStyle}`}
type='button'
{...buttonElementProps}
>
{LeftIcon ? (
<LeftIcon color={iconColor} style={{ width: '16px', height: '16px' }} />
) : null}
<span>{children}</span>
{!LeftIcon && RightIcon ? (
<RightIcon
color={iconColor}
style={{ width: '16px', height: '16px' }}
/>
) : null}
</button>
);
}

export default Chip;
12 changes: 12 additions & 0 deletions packages/ui/Chip/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import theme from '../theme.css';
import type { ChipSizeTheme } from './types';

export const paddings: Record<ChipSizeTheme, string> = {
sm: '9px 14px',
md: '10px 20px',
};

export const fonts = {
sm: theme.fontsObject.LABEL_3_14_SB,
md: theme.fontsObject.LABEL_2_16_SB,
};
1 change: 1 addition & 0 deletions packages/ui/Chip/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Chip';
41 changes: 41 additions & 0 deletions packages/ui/Chip/style.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { createSprinkles, defineProperties } from '@vanilla-extract/sprinkles';
import { style } from '@vanilla-extract/css';
import theme from '../theme.css';
import { fonts, paddings } from './constants';

const active = {
boxShadow: `0 0 0 1px ${theme.colors.gray100} inset`,
color: theme.colors.white,
backgroundColor: theme.colors.gray700,
};

export const root = style({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: 4,
boxShadow: `0 0 0 1px ${theme.colors.gray700} inset`,
borderRadius: 9999,
color: theme.colors.gray300,
backgroundColor: theme.colors.gray800,
cursor: 'pointer',
borderStyle: 'none',

':hover': {
color: theme.colors.white,
backgroundColor: theme.colors.gray700,
},

':active': active,
});

export const activeStyle = style(active);

const sprinkleProperties = defineProperties({
properties: {
padding: paddings,
fontStyle: fonts,
},
});

export const sprinkles = createSprinkles(sprinkleProperties);
1 change: 1 addition & 0 deletions packages/ui/Chip/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type ChipSizeTheme = 'sm' | 'md';
17 changes: 9 additions & 8 deletions packages/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
export * from "./cssVariables";
export * from './cssVariables';

// component exports
export { default as Button } from "./Button";
export { default as CheckBox } from "./CheckBox";
export { Dialog, DialogContext, DialogProvider, useDialog } from "./Dialog";
export type { DialogOptionType } from "./Dialog";
export { ToastProvider, useToast, Toast } from "./Toast";
export type { ToastOptionType } from "./Toast";
export { default as Button } from './Button';
export { default as CheckBox } from './CheckBox';
export { Dialog, DialogContext, DialogProvider, useDialog } from './Dialog';
export type { DialogOptionType } from './Dialog';
export { ToastProvider, useToast, Toast } from './Toast';
export type { ToastOptionType } from './Toast';
export { TextField, TextArea, SearchField } from './Input';
export { default as Chip } from './Chip';

// test component
export { default as Test } from "./Test";
export { default as Test } from './Test';

0 comments on commit 3a4651c

Please sign in to comment.