-
Notifications
You must be signed in to change notification settings - Fork 4
Feat/component/input/DEVING-34 Input 컴포넌트 개발 #15
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 9 commits
474f412
beeda2a
dd268ed
bd8f320
198bd5a
685f9b1
386fd7b
157519e
344177e
ee0b644
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 |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| import { Input } from '@/components/ui/Input'; | ||
|
|
||
| export default function ButtonExamples() { | ||
| return ( | ||
| <div className="w-fill h-full bg-BG p-10 text-white"> | ||
| <h1 className="typo-head1">Normal</h1> | ||
| <h2>large normal</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Default" /> | ||
| </div> | ||
|
|
||
| <h2>large typing</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Default" defaultValue={'Typing'} /> | ||
| </div> | ||
|
|
||
| <h2>large done</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input defaultValue="Done" state="success" /> | ||
| </div> | ||
|
|
||
| <h2>large error</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input defaultValue="Error" errorMessage="필수 입력 사항입니다." /> | ||
| </div> | ||
|
|
||
| <h2>large disable</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Disabled" disabled /> | ||
| </div> | ||
|
|
||
| <h2>small normal</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Default" inputSize="s" /> | ||
| </div> | ||
|
|
||
| <h2>small typing</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Default" defaultValue={'Typing'} inputSize="s" /> | ||
| </div> | ||
|
|
||
| <h2>small done</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input defaultValue="Done" state="success" inputSize="s" /> | ||
| </div> | ||
|
|
||
| <h2>small error</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input | ||
| defaultValue="Error" | ||
| errorMessage="필수 입력 사항입니다." | ||
| inputSize="s" | ||
| /> | ||
| </div> | ||
|
|
||
| <h2>small disable</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Disabled" disabled inputSize="s" /> | ||
| </div> | ||
|
|
||
| <h1 className="typo-head1">Password</h1> | ||
| <h2>large normal</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Default" type="password" /> | ||
| </div> | ||
|
|
||
| <h2>large typing</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Default" defaultValue={'Typing'} type="password" /> | ||
| </div> | ||
|
|
||
| <h2>large done</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input defaultValue="Done" state="success" type="password" /> | ||
| </div> | ||
|
|
||
| <h2>large error</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input | ||
| defaultValue="Error" | ||
| errorMessage="필수 입력 사항입니다." | ||
| type="password" | ||
| /> | ||
| </div> | ||
|
|
||
| <h2>large disable</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Disabled" disabled type="password" /> | ||
| </div> | ||
|
|
||
| <h2>small normal</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Default" inputSize="s" type="password" /> | ||
| </div> | ||
|
|
||
| <h2>small typing</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input | ||
| placeholder="Default" | ||
| defaultValue={'Typing'} | ||
| inputSize="s" | ||
| type="password" | ||
| /> | ||
| </div> | ||
|
|
||
| <h2>small done</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input | ||
| defaultValue="Done" | ||
| state="success" | ||
| inputSize="s" | ||
| type="password" | ||
| /> | ||
| </div> | ||
|
|
||
| <h2>small error</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input | ||
| defaultValue="Error" | ||
| errorMessage="필수 입력 사항입니다." | ||
| inputSize="s" | ||
| type="password" | ||
| /> | ||
| </div> | ||
|
|
||
| <h2>small disable</h2> | ||
| <div className="mb-4 w-[460px]"> | ||
| <Input placeholder="Disabled" disabled inputSize="s" type="password" /> | ||
| </div> | ||
|
|
||
| <h1 className="typo-head1">width 커스텀</h1> | ||
| <div className="mb-4 w-[260px]"> | ||
| <Input placeholder="Default" inputSize="s" /> | ||
| </div> | ||
| <div className="mb-4 w-[500px]"> | ||
| <Input placeholder="Default" inputSize="s" /> | ||
| </div> | ||
|
|
||
| <Input className="w-[200px]" placeholder="Default" inputSize="s" /> | ||
| </div> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,140 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'use client'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { cn } from '@/util/cn'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { VariantProps, cva } from 'class-variance-authority'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Eye, EyeOff } from 'lucide-react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import * as React from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface IInputProps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| extends React.InputHTMLAttributes<HTMLInputElement>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VariantProps<typeof inputVariants> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 입력 필드의 상태 (기본값: `'default'`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * - `'default'` : 기본 상태 (테두리 없음) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * - `'success'` : 성공 상태 (메인 컬러 테두리 적용) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * - `'error'` : 에러 상태 (경고 컬러 테두리 및 텍스트 적용) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| state?: 'default' | 'success' | 'error'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 입력 필드의 크기 (기본값: `'l'`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * - `'s'` : 작은 크기 (36px) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * - `'l'` : 기본 크기 (50px) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputSize?: 'l' | 's'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 에러 메시지 (에러 상태일 때 표시) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| errorMessage?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const inputVariants = cva( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'box-border flex w-full rounded-md border-transparent bg-Cgray200 px-3 px-[16px] py-1 py-[14px] text-base text-Cgray700 caret-Cgray500 shadow-sm transition-colors placeholder:text-Cgray400 focus:outline-none focus-visible:outline-none disabled:cursor-not-allowed disabled:bg-disable disabled:text-disable_text md:text-sm', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| variants: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| state: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: '', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| success: 'border border-main', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| error: 'border border-warning text-warning caret-warning', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputSize: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s: 'typo-button2 h-[36px]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| l: 'typo-button1 h-[50px] py-[10px]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultVariants: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputSize: 'l', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const errorTextVariants = cva('px-[10px] text-warning', { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| variants: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputSize: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s: 'typo-caption2 mt-[8px]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| l: 'typo-caption1 mt-[10px]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultVariants: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputSize: 'l', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * `Input` 컴포넌트 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 기본적인 입력 필드로, 텍스트 및 비밀번호 입력을 지원하며, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 에러 상태 및 성공 상태를 지정할 수 있습니다. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @example | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * // 기본 사용법 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * <Input placeholder="텍스트를 입력하세요" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @example | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * // 에러 상태 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * <Input state="error" errorMessage="필수 입력 사항입니다." /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @example | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * // 성공 상태 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * <Input state="success" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @example | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * // 비밀번호 입력 필드 (눈 아이콘 포함) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * <Input type="password" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param {IInputProps} props - `Input` 컴포넌트의 속성 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @returns {JSX.Element} `Input` 요소 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const Input = React.forwardRef<HTMLInputElement, IInputProps>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| state = 'default', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| errorMessage, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputSize = 'l', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...props | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ref, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [isVisible, setIsVisible] = React.useState(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className={`w-full ${className}`}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="relative focus-within:text-Cgray700"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type={ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type === 'password' ? (isVisible ? 'text' : 'password') : 'text' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={cn( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputVariants({ state, inputSize }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| !!errorMessage && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'border border-warning text-warning caret-warning', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+109
to
+113
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. 🛠️ Refactor suggestion 에러 상태 처리 로직이 중복됩니다.
다음과 같이 수정하는 것을 제안합니다: className={cn(
- inputVariants({ state, inputSize }),
- !!errorMessage &&
- 'border border-warning text-warning caret-warning',
+ inputVariants({
+ state: !!errorMessage ? 'error' : state,
+ inputSize
+ }),
)}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ref={ref} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {...props} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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. 🛠️ Refactor suggestion 입력 필드의 접근성을 개선해야 합니다. 입력 필드에 다음과 같이 수정하는 것을 제안합니다: <input
type={type === 'password' ? (isVisible ? 'text' : 'password') : 'text'}
+ aria-invalid={state === 'error' || !!errorMessage}
+ aria-describedby={errorMessage ? `${props.id}-error` : undefined}
className={cn(
inputVariants({ state, inputSize }),
!!errorMessage && 'border border-warning text-warning caret-warning',
)}
ref={ref}
{...props}
/>그리고 에러 메시지에 ID를 추가합니다: {errorMessage && (
- <p className={cn(errorTextVariants({ inputSize, className }))}>
+ <p id={`${props.id}-error`} className={cn(errorTextVariants({ inputSize, className }))}>
{errorMessage}
</p>
)}📝 Committable suggestion
Suggested change
Contributor
Author
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. aria 라벨 중에서 label, invalid, describedby 는 어떤 역할을 하기에 웹 접근성을 위한 속성이라는거야? 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. @dbswl701 각 ARIA 속성의 역할을 설명해드리겠습니다:
이러한 속성들은 시각 장애인이 스크린 리더를 통해 웹 페이지를 더 잘 이해하고 사용할 수 있도록 도와줍니다. (`・ω・´)ゞ ✏️ Learnings added
Contributor
Author
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. 에러 메시지에 id를 추가하는 이유가 뭐야? 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. @dbswl701 에러 메시지에 ID를 추가하는 이유는 ✏️ Learnings added
Contributor
Author
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. 그럼 id를 props로 꼭 받아야하는거네? 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. @dbswl701 네, 접근성을 위해서는 const Input = React.forwardRef<HTMLInputElement, IInputProps>(
({ className, type, state = 'default', errorMessage, inputSize = 'l', id, ...props }, ref) => {
const [isVisible, setIsVisible] = React.useState(false);
const uniqueId = React.useId(); // 내부적으로 고유한 ID 생성
const inputId = id || uniqueId;
return (
<div className={`w-full ${className}`}>
<div className="relative focus-within:text-Cgray700">
<input
id={inputId}
type={type === 'password' ? (isVisible ? 'text' : 'password') : 'text'}
aria-invalid={state === 'error' || !!errorMessage}
aria-describedby={errorMessage ? `${inputId}-error` : undefined}
// ... 나머지 코드
/>
{errorMessage && (
<p id={`${inputId}-error`} className={cn(errorTextVariants({ inputSize, className }))}>
{errorMessage}
</p>
)}
</div>
</div>
);
}
);✏️ Learnings added
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={() => setIsVisible((prev) => !prev)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={`absolute right-[16px] top-1/2 -translate-y-1/2 text-Cgray500 focus-within:text-Cgray700 ${type !== 'password' && 'hidden'} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {!isVisible ? ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <EyeOff className={`size-5 `} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) : ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Eye className={`size-5 `} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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. 🛠️ Refactor suggestion 접근성 개선이 필요합니다. 비밀번호 표시/숨기기 버튼에 대한 접근성 개선이 필요합니다: 다음과 같이 수정하는 것을 제안합니다: <button
onClick={() => setIsVisible((prev) => !prev)}
+ type="button"
+ aria-label={isVisible ? "비밀번호 숨기기" : "비밀번호 표시"}
className={`absolute right-[16px] top-1/2 -translate-y-1/2 text-Cgray500 focus-within:text-Cgray700 ${type !== 'password' && 'hidden'}`}
>📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {errorMessage && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p className={cn(errorTextVariants({ inputSize, className }))}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {errorMessage} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Input.displayName = 'Input'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export { Input }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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.
오류 텍스트 스타일의 기본값 설정에 버그가 있습니다.
errorTextVariants의defaultVariants설정이 잘못된 위치에 있습니다. 현재는variants객체 내부에 있어 작동하지 않습니다.다음과 같이 수정하는 것을 제안합니다:
const errorTextVariants = cva('px-[10px] text-warning', { variants: { inputSize: { s: 'typo-caption2 mt-[8px]', l: 'typo-caption1 mt-[10px]', }, - defaultVariants: { - inputSize: 'l', - }, }, + defaultVariants: { + inputSize: 'l', + }, });📝 Committable suggestion