-
Notifications
You must be signed in to change notification settings - Fork 1
Refactor : input components #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
93ce5f6
2bb347b
cd9be8a
55b14fd
d8608da
19a6003
2acbb69
1794f38
4d9aa6a
18eebb0
35e9641
1699df1
7ea8180
5a66ca6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,19 @@ | ||
| import { ComponentProps } from "react"; | ||
| import clsx from "clsx"; | ||
|
|
||
| export function Input({ className, ...props }: ComponentProps<"input">) { | ||
| type InputProps = ComponentProps<"input"> & { | ||
| inputRef?: React.Ref<HTMLInputElement>; | ||
| }; | ||
|
|
||
| export function Input({ className, inputRef, ...props }: InputProps) { | ||
| return ( | ||
| <input {...props} className={clsx("border rounded px-3 py-2", className)} /> | ||
| <input | ||
| ref={inputRef} | ||
| {...props} | ||
| className={clsx( | ||
| "h-[54px] w-full rounded-[16px] border px-[20px] text-sm outline-none", | ||
| className | ||
| )} | ||
| /> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,29 +1,44 @@ | ||
| import { ReactNode } from "react"; | ||
| import { Input } from "./Input"; | ||
| import { useId, ReactNode } from "react"; | ||
| import clsx from "clsx"; | ||
| import { Input } from "./Input"; | ||
|
|
||
| interface InputFieldProps { | ||
| interface InputFieldProps extends React.ComponentProps<typeof Input> { | ||
| label?: string; | ||
| error?: string; | ||
| helperText?: string; | ||
| inputProps?: React.ComponentProps<typeof Input>; | ||
| children?: ReactNode; | ||
| className?: string; | ||
| } | ||
|
|
||
| export function InputField({ | ||
| label, | ||
| error, | ||
| helperText, | ||
| inputProps, | ||
| children, | ||
| className, | ||
| ...props | ||
| }: InputFieldProps) { | ||
| const id = useId(); | ||
|
|
||
| return ( | ||
| <div className={clsx("flex flex-col gap-1", className)}> | ||
| {label && <label className="text-sm font-medium">{label}</label>} | ||
| <div className="flex w-full flex-col gap-[10px]"> | ||
| {label && ( | ||
| <label htmlFor={id} className="text-[16px] font-medium text-gray-900"> | ||
| {label} | ||
| </label> | ||
| )} | ||
|
|
||
| {children ?? <Input {...inputProps} />} | ||
| {children ?? ( | ||
| <Input | ||
| id={id} | ||
| {...props} | ||
| className={clsx( | ||
| error | ||
| ? "border-red-500 focus:ring-red-500" | ||
| : "border-gray-200 focus:ring-primary-500", | ||
| className | ||
| )} | ||
| /> | ||
| )} | ||
|
Comment on lines
+30
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| {error ? ( | ||
| <p className="text-xs text-red-500">{error}</p> | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -4,30 +4,31 @@ import { useState } from "react"; | |||||
| import Image from "next/image"; | ||||||
| import { Input } from "./Input"; | ||||||
| import type { ComponentProps } from "react"; | ||||||
| import clsx from "clsx"; | ||||||
|
|
||||||
| interface PasswordInputProps extends Omit<ComponentProps<"input">, "type"> { | ||||||
| className?: string; | ||||||
| } | ||||||
| type PasswordInputProps = ComponentProps<typeof Input>; | ||||||
|
|
||||||
| export function PasswordInput({ className, ...props }: PasswordInputProps) { | ||||||
| const [visible, setVisible] = useState(false); | ||||||
|
|
||||||
| return ( | ||||||
| <div className="relative"> | ||||||
| <div className="relative w-full"> | ||||||
| <Input | ||||||
| {...props} | ||||||
| type={visible ? "text" : "password"} | ||||||
| className={`pr-10 ${className ?? ""}`} | ||||||
| className={clsx("pr-12", className)} | ||||||
| /> | ||||||
|
|
||||||
| <button | ||||||
| type="button" | ||||||
| aria-label={visible ? "๋น๋ฐ๋ฒํธ ์จ๊ธฐ๊ธฐ" : "๋น๋ฐ๋ฒํธ ํ์"} | ||||||
| aria-pressed={visible} | ||||||
| onClick={() => setVisible((v) => !v)} | ||||||
| className="absolute right-3 top-1/2 -translate-y-1/2" | ||||||
| className="absolute right-4 top-1/2 -translate-y-1/2 focus:outline-none focus:ring-2 focus:ring-primary-500" | ||||||
| > | ||||||
| <Image | ||||||
| src={visible ? "/icon_active_on.svg" : "/icon_active_off.svg"} | ||||||
| alt={visible ? "๋น๋ฐ๋ฒํธ ์จ๊ธฐ๊ธฐ" : "๋น๋ฐ๋ฒํธ ๋ณด๊ธฐ"} | ||||||
| alt={visible ? "๋น๋ฐ๋ฒํธ ์จ๊ธฐ๊ธฐ ์์ด์ฝ" : "๋น๋ฐ๋ฒํธ ๋ณด๊ธฐ ์์ด์ฝ"} | ||||||
|
||||||
| alt={visible ? "๋น๋ฐ๋ฒํธ ์จ๊ธฐ๊ธฐ ์์ด์ฝ" : "๋น๋ฐ๋ฒํธ ๋ณด๊ธฐ ์์ด์ฝ"} | |
| alt="" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inputRefprop์ ์ฌ์ฉํ๋ ๋์React.forwardRef๋ฅผ ์ฌ์ฉํ์ฌref๋ฅผ ์ง์ ์ ๋ฌํ๋ ๊ฒ์ด ๋ ์ผ๋ฐ์ ์ธ React ํจํด์ด๋ฉฐ, ์ปดํฌ๋ํธ์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋์ ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ถ๋ชจ ์ปดํฌ๋ํธ์์useRef๋ฅผ ์ฌ์ฉํ ๋ ๋ ์ง๊ด์ ์ผ๋กref๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค.import { ComponentProps, forwardRef } from "react";์ ๊ฐ์ดforwardRef๋ฅผ importํด์ผ ํฉ๋๋ค.