Skip to content

Commit

Permalink
Merge pull request #45 from han-kimm/feat/alert,TextField
Browse files Browse the repository at this point in the history
✨feat: Alert, TextField 공통 컴포넌트 제작
  • Loading branch information
han-kimm authored Feb 3, 2024
2 parents 667255f + edd7a1a commit b733b33
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 25 deletions.
9 changes: 5 additions & 4 deletions app/(route)/(bottom-nav)/signin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ const SignInPage = () => {
};

return (
<form ref={formSection} onSubmit={handleSubmit(handleSignin)} className="flex flex-col gap-24 py-60">
<form ref={formSection} onSubmit={handleSubmit(handleSignin)} className="flex flex-col gap-24 px-12 py-60">
<InputText
name="email"
placeholder="example@illo.com"
placeholder="example@opener.com"
control={control}
onKeyDown={handleEnterNext}
rules={{ required: ERROR_MESSAGES.email.emailField, pattern: { value: REG_EXP.CHECK_EMAIL, message: ERROR_MESSAGES.email.emailPattern } }}
Expand All @@ -38,13 +38,14 @@ const SignInPage = () => {
<InputText
name="password"
type="password"
placeholder="8자 이상 입력해주세요."
control={control}
rules={{ required: ERROR_MESSAGES.password.passwordField, pattern: { value: REG_EXP.CHECK_PASSWORD, message: ERROR_MESSAGES.password.passwordPattern } }}
onKeyDown={handleEnterNext}
rules={{ required: ERROR_MESSAGES.password.passwordField, pattern: { value: REG_EXP.CHECK_PASSWORD, message: ERROR_MESSAGES.password.passwordPattern } }}
>
비밀번호
</InputText>
<button className={`"bg-black text-white flex-grow rounded-sm px-16 py-12 text-16`}>로그인</button>
<button className={`flex-grow rounded-sm bg-gray-900 px-16 py-12 text-16 text-white-black`}>로그인</button>
</form>
);
};
Expand Down
25 changes: 25 additions & 0 deletions app/_components/Alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"use client";

import Link from "next/link";
import { usePathname } from "next/navigation";
import RightArrowIcon from "@/public/icon/arrow-right_lg.svg";
import ExclamationIcon from "@/public/icon/exclamation.svg";

interface Props {
message: string;
href?: string;
}

const Alert = ({ message, href }: Props) => {
const path = usePathname();
return (
<Link href={href || path} className="flex items-center justify-between rounded-sm bg-[#F63D3D0D] p-8">
<div className="flex-center gap-4">
<ExclamationIcon />
<p className="text-12 font-500 text-red">{message}</p>
</div>
<RightArrowIcon stroke="#F63D3D" />
</Link>
);
};
export default Alert;
4 changes: 3 additions & 1 deletion app/_components/input/InputArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ const InputArea: Function = ({ children, placeholder, onKeyDown, isEdit, hasLimi
placeholder={placeholder ?? "입력해주세요."}
{...field}
onKeyDown={onKeyDown}
className={classNames("h-120 resize-none rounded-sm bg-gray-50 px-16 py-12", { "border border-blue-500 outline-none": isEdit })}
className={classNames("h-120 resize-none rounded-sm bg-gray-50 px-16 py-12 text-16 placeholder:text-gray-400 focus:outline focus:outline-1 focus:outline-blue", {
"outline outline-1 outline-blue": isEdit,
})}
/>
{hasLimit && <div className={classNames("text-12 text-[#A2A5AA]", { "text-red-600": field.value.length > 100 })}>{field.value.length} / 100</div>}
</div>
Expand Down
51 changes: 32 additions & 19 deletions app/_components/input/InputText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import { KeyboardEvent, ReactNode, useState } from "react";
import { FieldPath, FieldValues, UseControllerProps, useController } from "react-hook-form";

interface Prop {
type?: "text" | "password";
children?: ReactNode;
type?: "text" | "password";
horizontal?: boolean;
placeholder?: string;
autoComplete?: string;
hint?: string;
maxLength?: number;
hidden?: boolean;
readOnly?: boolean;
required?: boolean;
disabled?: boolean;
onKeyDown?: (e: KeyboardEvent) => void;
onClick?: () => void;
Expand All @@ -22,7 +24,23 @@ type Function = <TFieldValues extends FieldValues = FieldValues, TName extends F
prop: UseControllerProps<TFieldValues, TName> & Prop,
) => ReactNode;

const InputText: Function = ({ type: initialType, children, placeholder, autoComplete, hint, maxLength, hidden, readOnly, disabled, onClick, onKeyDown, isEdit, ...control }) => {
const InputText: Function = ({
children,
type: initialType,
horizontal,
placeholder,
autoComplete,
hint,
maxLength,
hidden,
required,
readOnly,
disabled,
onClick,
onKeyDown,
isEdit,
...control
}) => {
const { field, fieldState } = useController(control);
const [type, setType] = useState(initialType ?? "text");

Expand All @@ -35,11 +53,12 @@ const InputText: Function = ({ type: initialType, children, placeholder, autoCom
};

return (
<div>
<label htmlFor={field.name} className="text-14">
<div className={`${horizontal && "flex gap-28"}`}>
<label htmlFor={field.name} className={`text-14 ${horizontal && "mt-20"}`}>
{children}
<span className="ml-4 text-red">{required && "*"}</span>
</label>
<div className="relative">
<div className={`relative ${horizontal && "flex-1"}`}>
<input
id={field.name}
type={type}
Expand All @@ -48,34 +67,28 @@ const InputText: Function = ({ type: initialType, children, placeholder, autoCom
readOnly={readOnly ?? false}
disabled={disabled ?? false}
onClick={onClick}
{...field}
onKeyDown={onKeyDown}
{...field}
className={classNames(
"border-solid-gray body1-normal placeholder:text-gray-4 focus:border-purple mt-10 h-48 w-full rounded-md bg-blue-50 p-16 text-14 text-black outline-none",
"mt-8 h-48 w-full rounded-sm bg-gray-50 px-16 py-12 text-16 text-gray-900 placeholder:text-gray-400 focus:outline focus:outline-1 focus:outline-blue",
{ "outline outline-1 outline-red": fieldState.error },
{ hidden: hidden ?? false },
{ "border border-blue-500 outline-none": isEdit },
{ "border border-blue outline-none": isEdit },
)}
/>
{initialType === "password" && (
<button
onClick={handlePasswordShow}
onKeyDown={onKeyDown}
type="button"
className="absolute right-0 top-44 flex h-24 w-24 -translate-x-1/2 -translate-y-1/2 items-center justify-center"
>
<button onClick={handlePasswordShow} onKeyDown={onKeyDown} type="button" className="flex-center absolute right-16 top-20 h-24 w-24">
{<Image src={type === "password" ? "/icon/closed-eyes_black.svg" : "/icon/opened-eyes_black.svg"} alt="비밀번호 아이콘" width={16} height={16} />}
</button>
)}
{initialType !== "password" && !hidden && (
<button onClick={handleDelete} onKeyDown={onKeyDown} type="button" className="absolute right-16 top-16 h-16 w-16">
<button onClick={handleDelete} onKeyDown={onKeyDown} type="button" className="absolute right-16 top-24 h-16 w-16">
<Image src="/icon/x_gray.svg" alt="초기화 버튼" width={16} height={16} />
</button>
)}
<div className="flex gap-8">
{maxLength ? <span className={classNames("mt-4 h-8", { "text-red-500": field.value.length > maxLength })}>{`(${field.value.length}/${maxLength})`}</span> : null}
<p className={classNames(`font-normal mt-4 h-8 text-12`, { "text-red-500": fieldState.error, "text-gray-400": !fieldState.error })}>
{fieldState?.error?.message || hint}
</p>
{maxLength ? <span className={classNames("mt-4 h-8", { "text-red": field.value.length > maxLength })}>{`(${field.value.length}/${maxLength})`}</span> : null}
<p className={`font-normal mt-4 h-12 text-12 ${fieldState.error ? "text-red" : "text-gray-400"}`}>{fieldState?.error?.message || hint}</p>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion public/icon/arrow-right_lg.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions public/icon/exclamation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b733b33

Please sign in to comment.