Skip to content

Commit

Permalink
feat: 합성 컴포넌트 방식으로 Input 컴포넌트 구현 및 스토리북 UI 테스트 진행
Browse files Browse the repository at this point in the history
  • Loading branch information
Largopie committed Nov 19, 2024
1 parent a1d38f4 commit b6c7406
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 0 deletions.
62 changes: 62 additions & 0 deletions src/components/_common/Input/Input.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { Meta, StoryObj } from '@storybook/react';
import { useArgs } from '@storybook/preview-api';
import { Input } from './InputContainer';
import type { ChangeEvent } from 'react';

const meta: Meta<typeof Input.Text> = {
title: 'Common/Input/Text',
component: Input.Text,
tags: ['autodocs'],
argTypes: {
id: { control: 'text', description: 'label과 연결하기 위한 id값 입니다.' },
value: { control: 'text', description: 'input에 입력되는 값 입니다.' },
placeholder: { control: 'text', description: 'input 내부에 사용되는 placeholder입니다.' },
width: { control: 'text', description: 'input의 너비를 입력할 수 있습니다.' },
onChange: { description: '입력되는 값을 변경하기 위한 핸들러 함수입니다.' },
},
args: {
placeholder: '이름을 입력하세요',
value: '',
width: '40rem',
},
};

export default meta;
type Story = StoryObj<typeof Input.Text>;

export const DefaultInput: Story = {
render: (args) => {
const [, setArgs] = useArgs();

setArgs({ id: 'input-text' });

const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
setArgs({ value: e.target.value });
};

return (
<Input>
<Input.Text {...args} onChange={handleOnChange} />
</Input>
);
},
};

export const InputWithLabel: Story = {
render: (args) => {
const [, setArgs] = useArgs();

setArgs({ id: 'input-text-with-label' });

const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
setArgs({ value: e.target.value });
};

return (
<Input>
<Input.Label id={args.id} description='이름' />
<Input.Text {...args} onChange={handleOnChange} />
</Input>
);
},
};
19 changes: 19 additions & 0 deletions src/components/_common/Input/InputContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { PropsWithChildren } from 'react';
import styled from 'styled-components';
import InputText from './InputText';
import Label from './Label';

const InputContainer = ({ children }: PropsWithChildren) => {
return <StyledInputContainer>{children}</StyledInputContainer>;
};

const StyledInputContainer = styled.div`
display: flex;
flex-direction: column;
gap: 1.2rem;
`;

export const Input = Object.assign(InputContainer, {
Text: InputText,
Label: Label,
});
36 changes: 36 additions & 0 deletions src/components/_common/Input/InputText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { CSSProperties } from 'styled-components';
import styled from 'styled-components';
import { colorPalette } from '../../../styles/colorPalette';
import type { ChangeEvent } from 'react';

interface InputProps {
id: string;
width: CSSProperties['width'];
placeholder: string;
value: string;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
}

const InputText = ({ id, width, placeholder = '', value, onChange }: InputProps) => {
return <StyledInput placeholder={placeholder} width={width} id={id} type='text' value={value} onChange={onChange} />;
};

export default InputText;

const StyledInput = styled.input<{ width: CSSProperties['width'] }>`
width: ${({ width }) => width};
height: 4.4rem;
padding: 0.8rem;
font-size: 1.6rem;
color: ${({ theme }) => theme.colors.color};
border: 2px solid ${({ theme }) => theme.colors.main};
border-radius: 4px;
&::placeholder {
color: ${colorPalette.darkblue};
}
&:focus {
outline: none;
}
`;
17 changes: 17 additions & 0 deletions src/components/_common/Input/Label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import styled from 'styled-components';

interface LabelProps {
id: string;
description: string;
}

const Label = ({ id, description }: LabelProps) => {
return <StyledLabel htmlFor={id}>{description}</StyledLabel>;
};

const StyledLabel = styled.label`
font-size: 2rem;
font-weight: 600;
`;

export default Label;

0 comments on commit b6c7406

Please sign in to comment.