Skip to content

Commit

Permalink
Feat/#4 공용 버튼 컴포넌트를 추가하였습니다. (#23)
Browse files Browse the repository at this point in the history
* feat: react-native 전용 룰 제외를 추가합니다.

* feat: 공용 컴포넌트 버튼을 수정합니다.

* refactor: flexItemCenter를 추가합니다.

* fix: storybook workflow 적용 오류를 수정합니다.
  • Loading branch information
Zero-1016 committed Sep 12, 2024
1 parent 395d1e1 commit cf5587f
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 138 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ name: 'Chromatic Deployment'
# Event for the workflow
on:
push:
tags:
- 'Storybook*'

# List of jobs
jobs:
Expand Down
19 changes: 18 additions & 1 deletion .stylelintrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
{
"extends": ["stylelint-config-standard", "stylelint-config-recess-order"],
"plugins": ["stylelint-order"],
"customSyntax": "postcss-styled-syntax"
"customSyntax": "postcss-styled-syntax",
"rules": {
"property-no-unknown": [
true,
{
"ignoreProperties": [
"padding-vertical",
"padding-horizontal",
"shadow-color",
"shadow-offset",
"shadow-radius",
"shadow-opacity",
"shadow-blur",
"elevation"
]
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { Meta, StoryObj } from '@storybook/react';

import OutLineButton from '@/components/common/button/outlineButton/index';

const OutLineButtonMeta: Meta<typeof OutLineButton> = {
title: 'common/Button/OutLineButton',
component: OutLineButton,
argTypes: {
children: { controls: 'text' },
},
args: {
children: '버튼',
},
};

export default OutLineButtonMeta;

export const CreateProjectButton: StoryObj<typeof OutLineButton> = {
name: '프로젝트 등록하기 버튼',
args: {
children: '프로젝트 등록하기',
width: 180,
},
};

export const FullSize: StoryObj<typeof OutLineButton> = {
name: '가로 폭에 맞춘 버튼',
args: {
width: '100%',
},
};

export const HalfSize: StoryObj<typeof OutLineButton> = {
name: '가로 폭의 50%인 버튼',
args: {
width: '50%',
},
};
86 changes: 86 additions & 0 deletions src/components/common/button/outlineButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import type { ReactNativeStyle } from '@emotion/native';
import { css } from '@emotion/native';
import styled from '@emotion/native';
import { Platform, type PressableProps } from 'react-native';

import Typography from '@/components/common/typography';
import { flexItemCenter } from '@/styles/common';
import type { PropsNeedChildren } from '@/types';

type Props = {
width?: ReactNativeStyle['width'];
height?: ReactNativeStyle['height'];
} & PressableProps;

/**
* PrimaryButton
* @param width 가로의 길이를 입력합니다.
* @param height 세로의 길이를 입력합니다.
* @param status 버튼의 상태를 정의합니다.
* @param children 버튼에 표시할 텍스트를 입력합니다.
* @param rest 나머지 추가 속성들을 받아옵니다.
* @constructor
*/
function OutLineButton({
width = '100%',
height = 52,
children,
...rest
}: PropsNeedChildren<Props>) {
return (
<Container
style={{ width, height }}
{...rest}>
<ShadowBackGroundTop />
<ShadowBackGroundBottom />
<Typography
variant='Body1/Normal'
fontWeight='semiBold'
color='black'>
{children}
</Typography>
</Container>
);
}

const absoluteObjectFullShadow = css`
position: absolute;
width: 100%;
height: 100%;
border-radius: 32px;
`;

const iosTopShadow = css`
shadow-offset: -7px -2px;
shadow-opacity: 0.15;
shadow-blur: 8px;
shadow-radius: 32px;
`;
const iosBottomShadow = css`
shadow-offset: 2px 5px;
shadow-opacity: 0.15;
shadow-blur: 10px;
shadow-radius: 32px;
`;

const Container = styled.Pressable`
position: relative;
${flexItemCenter};
padding: 6px 32px;
background: white;
border-radius: 32px;
`;

const ShadowBackGroundTop = styled.View`
${absoluteObjectFullShadow};
shadow-color: rgb(122 74 255 / 1500%);
${Platform.OS !== 'ios' ?? iosTopShadow}
`;

const ShadowBackGroundBottom = styled.View`
${absoluteObjectFullShadow};
shadow-color: rgb(26 117 255 / 1500%);
${Platform.OS === 'android' ? 'elevation: 5' : iosBottomShadow}
`;

export default OutLineButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { Meta, StoryObj } from '@storybook/react';

import PrimaryButton from '@/components/common/button/primaryButton/index';

const PrimaryButtonMeta: Meta<typeof PrimaryButton> = {
title: 'common/Button/PrimaryButton',
component: PrimaryButton,
argTypes: {
status: {
controls: {
type: 'select',
options: ['active', 'disabled'],
},
},
width: {
controls: {
type: 'number',
},
},
height: {
controls: {
type: 'number',
},
},
children: { controls: 'text' },
},
args: {
children: '버튼',
status: 'active',
},
};

export default PrimaryButtonMeta;

export const FullSize: StoryObj<typeof PrimaryButton> = {
name: '가로 폭에 맞춘 버튼',
args: {
status: 'active',
width: '100%',
},
};

export const HalfSize: StoryObj<typeof PrimaryButton> = {
name: '가로 폭의 50%인 버튼',
args: {
status: 'active',
width: '50%',
},
};

export const DisabledButton: StoryObj<typeof PrimaryButton> = {
name: '제한된 버튼',
args: {
status: 'disabled',
width: '100%',
},
};
78 changes: 78 additions & 0 deletions src/components/common/button/primaryButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { ReactNativeStyle } from '@emotion/native';
import styled, { css } from '@emotion/native';
import { LinearGradient } from 'expo-linear-gradient';
import type { PressableProps } from 'react-native';

import Typography from '@/components/common/typography';
import { flexItemCenter } from '@/styles/common';
import { theme } from '@/styles/theme';
import type { PropsNeedChildren } from '@/types';

type Props = {
width?: ReactNativeStyle['width'];
height?: ReactNativeStyle['height'];
status?: keyof typeof VariantStyle;
} & PressableProps;

const VariantStyle = {
active: css({
padding: 10,
}),
disabled: css({
backgroundColor: theme.color.Background.Alternative,
}),
};

/**
* PrimaryButton
* @param width 가로의 길이를 입력합니다.
* @param height 세로의 길이를 입력합니다.
* @param status 버튼의 상태를 정의합니다.
* @param children 버튼에 표시할 텍스트를 입력합니다.
* @param rest 나머지 추가 속성들을 받아옵니다.
* @constructor
*/
function PrimaryButton({
width = '100%',
height = 56,
status = 'active',
children,
...rest
}: PropsNeedChildren<Props>) {
return (
<Container
disabled={status === 'disabled'}
style={{ width, height }}
status={status}
{...rest}>
{status === 'active' && (
<BackGround
colors={['#7C71F5', '#6E9DF5']}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
/>
)}
<Typography
variant='Body1/Normal'
fontWeight='semiBold'
color={status === 'active' ? 'white' : '#C2C4C8'}>
{children}
</Typography>
</Container>
);
}

const Container = styled.Pressable<Required<Pick<Props, 'status'>>>`
${({ status }) => VariantStyle[status]}
${flexItemCenter};
overflow: hidden;
border-radius: 100px;
`;

const BackGround = styled(LinearGradient)`
position: absolute;
width: 100%;
height: 100%;
`;

export default PrimaryButton;
62 changes: 0 additions & 62 deletions src/components/common/customButton/CustomButton.stories.tsx

This file was deleted.

Loading

0 comments on commit cf5587f

Please sign in to comment.