Skip to content

Commit

Permalink
[미션1] feat: TextField 컴포넌트 구현 #1 (#4)
Browse files Browse the repository at this point in the history
* [Mission1] feat: TextField UI 구현

* [Mission1] feat: useInput, useInputs 구현

* [Mission1] refactor: TextField css 수정, 불필요 코드 제거 #1
  • Loading branch information
ShinjungOh authored Dec 20, 2022
1 parent e4391ca commit ae29bf4
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 29 deletions.
3 changes: 2 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import GlobalStyles from './ui/core/GlobalStyles';
import InputContainer from './ui/components/container/InputContainer';

function App() {
return (
<>
<div>
main
<InputContainer />
</div>
<GlobalStyles />
</>
Expand Down
105 changes: 102 additions & 3 deletions src/ui/components/common/TextField.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,113 @@
import React from 'react';
import styled from 'styled-components';
import styled, { css } from 'styled-components';

const TextField = () => (
interface TextFieldProps {
id?: string;
name?: string;
label?: string;
placeholder?: string;
error?: boolean;
errorMessage?: string;
readOnly?: boolean;
disabled?: boolean;
onChange?: (e: any) => void;

[k: string]: any;
}

const TextField = ({
id,
name,
label,
placeholder,
error,
errorMessage,
readOnly,
disabled,
onChange,
...props
}: TextFieldProps) => (
<Container>
TextField
<Label htmlFor={id}>{label}</Label>
<Input
id={id}
name={name}
placeholder={placeholder}
readOnly={readOnly}
disabled={disabled}
error={error}
onChange={onChange}
{...props}
/>
{
error && (
<ErrorMessage>{errorMessage}</ErrorMessage>
)
}
</Container>
);

export default TextField;

const Container = styled.div`
width: 500px;
height: auto;
padding: 0 0 0 40px;
display: flex;
flex-direction: column;
& + & {
margin-top: 32px;
}
`;

const Label = styled.label`
width: 400px;
height: 20px;
border-radius: 4px;
margin-bottom: 10px;
`;

const Input = styled.input<TextFieldProps>`
width: 400px;
height: 48px;
border: 1px solid #E0E0E0;
border-radius: 4px;
padding: 0 16px;
font-size: 14px;
${(props) => props.error
&& css`
color: #EB5757 !important;
border: 1px solid #EB5757 !important;
`};
&::placeholder {
color: #BDBDBD;
}
&:hover {
border: 1px solid #828282;
}
&:focus {
border: 1px solid #333333;
outline: none;
}
&:read-only {
color: #4F4F4F;
border: 1px solid #E0E0E0;
}
&:disabled {
color: #BDBDBD;
border: 1px solid #E0E0E0;
}
`;

const ErrorMessage = styled.div`
color: #EB5757;
font-size: 14px;
margin-top: 8px;
`;
54 changes: 50 additions & 4 deletions src/ui/components/container/InputContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,57 @@
import React from 'react';

import TextField from '../common/TextField';
import useInput from '../../hooks/useInput';
import useInputs from '../../hooks/useInputs';

const InputContainer = () => {
console.log('input Container');
const {
input,
onChange: onChangeInput,
} = useInput('');

const {
inputs,
onChange: onChangeInputs,
} = useInputs<{ label2: string; label3: string; }>({
label2: '',
label3: '',
});

return (
<div style={{ padding: 100 }}>
InputContainer
</div>
<>
<TextField
label="label1"
id="label1"
placeholder="placeholder"
onChange={onChangeInput}
value={input}
/>
<TextField
label="label2"
id="label2"
name="label2"
placeholder="placeholder"
readOnly
onChange={onChangeInputs}
value={inputs.label2}
/>
<TextField
label="label3"
id="label3"
name="label3"
placeholder="placeholder"
disabled
onChange={onChangeInputs}
value={inputs.label3}
/>
<TextField
label="label4"
id="label4"
error
errorMessage="오류가 발생했습니다."
/>
</>
);
};

Expand Down
7 changes: 0 additions & 7 deletions src/ui/components/input/Input.jsx

This file was deleted.

24 changes: 17 additions & 7 deletions src/ui/hooks/useInput.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
const useInput = () => {
// TODO: useInput Hook을 작성하라.
console.log('');
const onChange = () => {
// TODO: onChange 함수를 작성하라.
import { useState } from 'react';

type useInputType = (initialState?: string) => {
input: string;
onChange: (e: any) => void;
reset: () => void;
}

const useInput: useInputType = (initialState = '') => {
const [input, setInput] = useState(initialState);

const onChange = (e: any) => {
setInput(e.target.value);
};

const reset = () => {
// TODO: reset 함수를 작성하라.
setInput('');
};

return {
input: '',
input,
onChange,
reset,
};
Expand Down
28 changes: 21 additions & 7 deletions src/ui/hooks/useInputs.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
const useInputs = () => {
// TODO: useInput Hook을 작성하라.
console.log('');
const onChange = () => {
// TODO: onChange 함수를 작성하라.
import { useState } from 'react';

type useInputsType = <T>(initialState: T) => {
inputs: T;
onChange: (e: any) => void;
reset: () => void;
}

const useInputs: useInputsType = (initialState) => {
const [inputs, setInputs] = useState(initialState);

const onChange = (e: any) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value,
});
};

const reset = () => {
// TODO: reset 함수를 작성하라.
setInputs(initialState);
};

return {
inputs: {},
inputs,
onChange,
reset,
};
Expand Down

0 comments on commit ae29bf4

Please sign in to comment.