Skip to content

Commit

Permalink
feat: textarea 컴포넌트 제작
Browse files Browse the repository at this point in the history
  • Loading branch information
JoStar33 committed Aug 20, 2024
1 parent 63d757b commit 830c2b8
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/components/contents/write/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function ContentsWrite({ onSubmit }: IProps) {
<S.ContentsWrite onSubmit={handleSubmit(onSubmit)}>
<Form.FileDrop<IContentsRegisterForm> name="image" />
<Form.InputA<IContentsRegisterForm> name="title" />
<Form.InputA<IContentsRegisterForm> name="description" />
<Form.TextArea<IContentsRegisterForm> name="description" />
<Button name="positive">등록</Button>
</S.ContentsWrite>
);
Expand Down
3 changes: 1 addition & 2 deletions src/components/hookForm/InputA.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,8 @@ const S = {
background-color: ${(props) => props.theme.colors.white};
height: ${(props) => (props.height ? props.height : '40px')};
padding-left: 10px;
border-radius: 4px;
color: ${(props) => props.theme.colors.modernBlack};
border: ${(props) => (props.readOnly ? 'none' : '1px solid #d0d0d0')};
border: ${(props) => (props.readOnly ? 'none' : `1px solid ${props.theme.colors.black}`)};
${(props) =>
props.disabled &&
css`
Expand Down
135 changes: 135 additions & 0 deletions src/components/hookForm/TextArea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import React from 'react';
import { useFormContext, Path, FieldValues } from 'react-hook-form';
import ErrorText from './ErrorText';
import { css, styled } from 'styled-components';

interface Props<T extends FieldValues> extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement> {
name: Path<T>;
label?: string;
maxLength?: number;
placeholder?: string;
isFocusing?: boolean;
minHeight?: string;
disabled?: boolean;
required?: boolean;
visibleError?: boolean;
}

export default function TextArea<T extends FieldValues>({
name,
label,
maxLength,
placeholder,
isFocusing,
minHeight = '220px',
visibleError = true,
required = false,
disabled,
...rest
}: Props<T>) {
const {
register,
setFocus,
watch,
formState: { errors },
} = useFormContext<T>();

const textAreaWatchValue = watch(name);

React.useEffect(() => {
if (isFocusing) {
setFocus(name);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isFocusing]);

return (
<S.TextArea disabled={disabled}>
<S.Label required={required}>
{label}
<span className="styled-label__required">(필수)</span>
</S.Label>
<S.StyledTextArea
maxLength={maxLength}
placeholder={placeholder}
minHeight={minHeight}
autoComplete="off"
{...rest}
{...register(name)}
disabled={disabled}
/>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
{visibleError && <ErrorText errors={errors} name={name} />}
{maxLength && !disabled && (
<S.StyledTextCount>
{textAreaWatchValue ? textAreaWatchValue.length : 0} / {`${maxLength}자`}
</S.StyledTextCount>
)}
</div>
</S.TextArea>
);
}

const S = {
TextArea: styled.div<{ disabled?: boolean }>`
width: 100%;
`,
StyledTextArea: styled.textarea<{ isError?: boolean; minHeight?: string }>`
width: 100%;
padding: 10px;
border: none;
font-family: 'SUIT';
min-height: ${(props) => props.minHeight};
line-height: 18px;
font-size: 16px;
width: 100%;
background-color: ${(props) => props.theme.colors.white};
border: 1px solid ${(props) => props.theme.colors.modernBlack};
&::placeholder {
color: ${(props) => props.theme.colors.modernBlack};
font-size: 14px;
}
${(props) =>
props.disabled &&
css`
background-color: ${(props) => props.theme.colors.gray};
border: none;
color: ${(props) => props.theme.colors.gray};
-webkit-text-fill-color: currentColor;
opacity: 1;
`};
&:focus {
border-color: ${(props) => props.theme.colors.deepSkyblue};
box-shadow: 0 0 5px -1px ${(props) => props.theme.colors.deepSkyblue};
}
`,
StyledTextCount: styled.div`
margin-top: 5px;
text-align: right;
color: ${(props) => props.theme.colors.gray};
font-size: 12px;
`,
Label: styled.label<{ required: boolean }>`
display: inline-block;
font-weight: 500;
height: 15px;
width: auto;
cursor: default;
color: ${(props) => props.theme.colors.black};
font-size: 16px;
color: ${(props) => props.theme.colors.modernBlack};
margin-bottom: 7px;
font-family: 'SUIT';
.styled-label__required {
display: none;
${(props) =>
props.required &&
css`
display: inline;
`};
color: ${(props) => props.theme.colors.red};
margin-left: 2px;
vertical-align: top;
}
`,
};
2 changes: 2 additions & 0 deletions src/components/hookForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import InputA from '@/components/hookForm/InputA';
import RadioButton from '@/components/hookForm/RadioButton';
import CheckBoxYN from '@/components/hookForm/CheckBoxYN';
import FileDrop from '@/components/hookForm/FileDrop';
import TextArea from '@/components/hookForm/TextArea';

const Form = {
InputA,
ErrorText,
RadioButton,
CheckBoxYN,
FileDrop,
TextArea,
};

export default Form;

0 comments on commit 830c2b8

Please sign in to comment.