Input
개요
Input은 사용자로부터 텍스트 데이터를 입력받는 기본 폼 컴포넌트입니다. Cals 예약 관리 시스템에서는 고객 정보 입력, 예약 검색, 서비스 메모 작성 등 다양한 상황에서 활용됩니다.
Cals 특화 기능:
- 예약 상태별 색상 시스템으로 입력 필드 상태 표현
- 고객 정보(이름, 연락처, 이메일) 입력 최적화
- 예약 검색 및 필터링을 위한 검색 입력 지원
- 서비스 메모 및 특별 요청사항 입력
설치
npx @vortex/cli add input --package cals기본 사용법
import "@vortex/ui-cals/theme";
import { Input } from "@vortex/ui-cals";
export default function ReservationForm() {
return (
<div>
<Input type="text" placeholder="고객 이름을 입력하세요" />
<Input type="tel" placeholder="연락처 (010-0000-0000)" />
<Input type="email" placeholder="이메일 주소" />
</div>
);
}Types
Text Input
기본 텍스트 입력 필드입니다.
<Input type="text" placeholder="고객 이름" />Email Input
이메일 주소 입력 필드입니다.
<Input type="email" placeholder="example@cals.app" />Tel Input
전화번호 입력 필드입니다.
<Input type="tel" placeholder="010-0000-0000" />Search Input
검색 기능을 위한 입력 필드입니다.
<Input type="search" placeholder="예약 검색..." />Password Input
비밀번호 입력 필드입니다.
<Input type="password" placeholder="비밀번호" />Sizes
Small
작은 크기의 Input입니다. 밀집된 레이아웃에 적합합니다.
<Input size="sm" placeholder="Small input" />Medium (Default)
기본 크기의 Input입니다.
<Input size="md" placeholder="Medium input" />Large
큰 크기의 Input입니다. 중요한 입력 필드에 적합합니다.
<Input size="lg" placeholder="Large input" />States
Disabled
비활성화된 Input입니다.
<Input disabled placeholder="비활성화된 입력" />Read Only
읽기 전용 Input입니다.
<Input readOnly value="읽기 전용 값" />Error
오류 상태의 Input입니다.
<Input error placeholder="잘못된 입력" />🆕 Cals 브랜딩
브랜드 컬러
Cals Input은 기본적으로 Cals의 Primary 색상(Pink #e91e63)을 focus 상태에서 사용합니다.
<div className="space-y-4">
<Input
placeholder="Primary (Pink) - 기본 focus"
className="focus:border-[#e91e63] focus:ring-[#e91e63]"
/>
<Input
placeholder="Secondary (Blue) - 정보성 입력"
className="focus:border-[#03a9f4] focus:ring-[#03a9f4]"
/>
<Input
placeholder="Accent (Purple) - 강조 입력"
className="focus:border-[#9c27b0] focus:ring-[#9c27b0]"
/>
</div>예약 상태 컬러
Cals Input은 예약 관리의 5가지 상태를 반영하여 입력 필드의 시각적 피드백을 제공합니다.
<div className="space-y-4">
{/* Available - 입력 가능 상태 */}
<Input
placeholder="예약 가능 상태 (입력 가능)"
className="border-[#4caf50] focus:ring-[#4caf50]"
/>
{/* Pending - 검증 대기 */}
<Input
placeholder="검증 대기 중..."
className="border-[#ff9800] focus:ring-[#ff9800]"
disabled
/>
{/* Confirmed - 확정된 정보 */}
<Input
value="홍길동 (확정됨)"
className="border-[#03a9f4] focus:ring-[#03a9f4]"
readOnly
/>
{/* Cancelled - 취소된 예약 */}
<Input
value="취소된 예약"
className="border-[#f44336] bg-red-50 focus:ring-[#f44336]"
readOnly
/>
{/* Completed - 완료된 서비스 */}
<Input
value="서비스 완료"
className="border-[#9c27b0] bg-purple-50 focus:ring-[#9c27b0]"
readOnly
/>
</div>Cals 특화 사용 가이드
고객 정보 입력 폼
<div className="space-y-3">
<div>
<label className="text-sm font-medium text-gray-700">
고객 이름 <span className="text-[#e91e63]">*</span>
</label>
<Input
type="text"
placeholder="이름을 입력하세요"
className="mt-1 focus:border-[#e91e63] focus:ring-[#e91e63]"
/>
</div>
<div>
<label className="text-sm font-medium text-gray-700">
연락처 <span className="text-[#e91e63]">*</span>
</label>
<Input
type="tel"
placeholder="010-0000-0000"
className="mt-1 focus:border-[#e91e63] focus:ring-[#e91e63]"
/>
</div>
<div>
<label className="text-sm font-medium text-gray-700">이메일</label>
<Input
type="email"
placeholder="example@cals.app"
className="mt-1 focus:border-[#03a9f4] focus:ring-[#03a9f4]"
/>
</div>
</div>예약 검색
<div className="max-w-md">
<Input
type="search"
placeholder="고객명, 연락처, 예약번호로 검색..."
className="focus:border-[#e91e63] focus:ring-[#e91e63]"
/>
</div>서비스 메모 입력
<div>
<label className="text-sm font-medium text-gray-700">특별 요청사항</label>
<textarea
placeholder="고객의 특별 요청사항을 입력하세요"
className="mt-1 w-full rounded-md border-gray-300 focus:border-[#9c27b0] focus:ring-[#9c27b0]"
rows={4}
/>
</div>🆕 Foundation/iCignal과의 차이점
| 속성 | Foundation | iCignal | Cals |
|---|---|---|---|
| Primary Color | #3B82F6 (Blue) | #2196f3 (Blue) | #e91e63 (Pink) |
| Secondary Color | #10B981 (Green) | #4caf50 (Green) | #03a9f4 (Blue) |
| Accent Color | #8B5CF6 (Purple) | #ff5722 (Deep Orange) | #9c27b0 (Purple) |
| 사용 맥락 | 범용 웹 애플리케이션 | Analytics 대시보드 | 예약 관리 시스템 |
| 예약 상태 | 없음 | 없음 | 5가지 상태 (Available/Pending/Confirmed/Cancelled/Completed) |
| 주요 입력 | 범용 데이터 입력 | 데이터 필터링 | 고객 정보, 예약 검색, 서비스 메모 |
| Focus 스타일 | Blue ring | Blue ring | Pink ring (Primary focus) |
| 상태 피드백 | 기본 validation | 기본 validation | 예약 상태별 시각적 피드백 |
사용 시나리오 비교
Foundation Input: 범용 폼 입력, 사용자 등록, 설정 변경 iCignal Input: 데이터 필터링, 검색, 분석 조건 입력 Cals Input: 고객 정보 입력, 예약 검색, 서비스 메모, 상태별 피드백
Props API
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'text' | 'email' | 'tel' | 'search' | 'password' | 'number' | 'text' | Input 타입 |
size | 'sm' | 'md' | 'lg' | 'md' | Input 크기 |
placeholder | string | - | 플레이스홀더 텍스트 |
value | string | - | Input 값 (제어 컴포넌트) |
defaultValue | string | - | 기본값 (비제어 컴포넌트) |
disabled | boolean | false | 비활성화 여부 |
readOnly | boolean | false | 읽기 전용 여부 |
error | boolean | false | 오류 상태 여부 |
required | boolean | false | 필수 입력 여부 |
onChange | (e: React.ChangeEvent<HTMLInputElement>) => void | - | 값 변경 이벤트 핸들러 |
onFocus | (e: React.FocusEvent<HTMLInputElement>) => void | - | Focus 이벤트 핸들러 |
onBlur | (e: React.FocusEvent<HTMLInputElement>) => void | - | Blur 이벤트 핸들러 |
className | string | - | 추가 CSS 클래스 |
접근성
Input 컴포넌트는 웹 접근성 표준을 준수합니다:
- 시맨틱 HTML:
<input>요소 사용으로 스크린 리더 지원 - Label 연결:
htmlFor와id를 통한 label-input 연결 - Required 표시: 필수 입력 필드에
aria-required="true"및 시각적 표시 (*) - Error 메시지:
aria-invalid와aria-describedby로 오류 메시지 연결 - 키보드 네비게이션: Tab으로 focus 이동, Enter로 폼 제출
- Focus 표시: 명확한 focus ring으로 현재 위치 표시
- Placeholder: 보조 정보로만 사용, label을 대체하지 않음
접근성 예제
<div>
<label htmlFor="customer-name" className="text-sm font-medium text-gray-700">
고객 이름{" "}
<span className="text-[#e91e63]" aria-label="필수">
*
</span>
</label>
<Input
id="customer-name"
type="text"
placeholder="이름을 입력하세요"
required
aria-required="true"
aria-invalid={hasError}
aria-describedby={hasError ? "name-error" : undefined}
/>
{hasError && (
<p id="name-error" className="mt-1 text-sm text-red-600">
고객 이름을 입력해주세요.
</p>
)}
</div>예제
고객 정보 입력 폼
import { Input } from "@vortex/ui-cals";
export default function CustomerForm() {
return (
<form className="space-y-4 max-w-md">
<div>
<label
htmlFor="name"
className="block text-sm font-medium text-gray-700"
>
고객 이름 <span className="text-[#e91e63]">*</span>
</label>
<Input
id="name"
type="text"
placeholder="이름을 입력하세요"
required
className="mt-1 focus:border-[#e91e63] focus:ring-[#e91e63]"
/>
</div>
<div>
<label
htmlFor="phone"
className="block text-sm font-medium text-gray-700"
>
연락처 <span className="text-[#e91e63]">*</span>
</label>
<Input
id="phone"
type="tel"
placeholder="010-0000-0000"
required
className="mt-1 focus:border-[#e91e63] focus:ring-[#e91e63]"
/>
</div>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-gray-700"
>
이메일
</label>
<Input
id="email"
type="email"
placeholder="example@cals.app"
className="mt-1 focus:border-[#03a9f4] focus:ring-[#03a9f4]"
/>
</div>
<button
type="submit"
className="w-full bg-[#e91e63] text-white py-2 px-4 rounded-md hover:bg-[#c2185b]"
>
예약 등록
</button>
</form>
);
}예약 검색
import { Input } from "@vortex/ui-cals";
import { Search } from "lucide-react";
export default function ReservationSearch() {
return (
<div className="max-w-2xl">
<div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-5 w-5 text-gray-400" />
<Input
type="search"
placeholder="고객명, 연락처, 예약번호로 검색..."
className="pl-10 focus:border-[#e91e63] focus:ring-[#e91e63]"
/>
</div>
<div className="mt-2 flex gap-2">
<button className="text-sm px-3 py-1 rounded-full bg-[#4caf50] text-white">
예약 가능
</button>
<button className="text-sm px-3 py-1 rounded-full bg-[#ff9800] text-white">
승인 대기
</button>
<button className="text-sm px-3 py-1 rounded-full bg-[#03a9f4] text-white">
예약 확정
</button>
<button className="text-sm px-3 py-1 rounded-full bg-[#f44336] text-white">
예약 취소
</button>
<button className="text-sm px-3 py-1 rounded-full bg-[#9c27b0] text-white">
서비스 완료
</button>
</div>
</div>
);
}예약 상태별 입력 필드
import { Input } from "@vortex/ui-cals";
export default function ReservationStatusInputs() {
return (
<div className="space-y-4 max-w-md">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
예약 가능 (Available)
</label>
<Input
placeholder="새로운 예약 정보 입력"
className="border-[#4caf50] focus:border-[#4caf50] focus:ring-[#4caf50]"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
승인 대기 (Pending)
</label>
<Input
value="김철수 (승인 대기 중...)"
className="border-[#ff9800] bg-orange-50 focus:ring-[#ff9800]"
readOnly
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
예약 확정 (Confirmed)
</label>
<Input
value="이영희 (2024-01-15 14:00)"
className="border-[#03a9f4] bg-blue-50 focus:ring-[#03a9f4]"
readOnly
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
예약 취소 (Cancelled)
</label>
<Input
value="박민수 (고객 요청으로 취소)"
className="border-[#f44336] bg-red-50 focus:ring-[#f44336]"
readOnly
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
서비스 완료 (Completed)
</label>
<Input
value="정지훈 (2024-01-10 완료)"
className="border-[#9c27b0] bg-purple-50 focus:ring-[#9c27b0]"
readOnly
/>
</div>
</div>
);
}관련 컴포넌트
Last updated on