Tiro
Tiro Design
Components

TextField

라벨, 입력 필드, 보조 텍스트를 하나로 묶은 폼 컴포넌트입니다.

Mobile

Web TextField와 anatomy(Label + Input + HelperText)는 동일, 모바일 키보드 동작이 추가된다.

  • keyboardType: 입력 내용에 맞게 선택
    • 일반 텍스트: default
    • 이메일: email-address (autoCapitalize="none", autoCorrect={false})
    • 숫자: number-pad, 통화는 decimal-pad
    • 전화: phone-pad
    • URL: url (autoCapitalize="none")
  • secureTextEntry: 비밀번호는 secureTextEntry={true} — 우측 inline 토글로 보이기/숨기기 옵션 제공 권장
  • autoCapitalize: 일반 이름·문장은 sentences 또는 words, 이메일·아이디·식별자는 none
  • autoCorrect: 자유 텍스트는 true, 식별자·코드는 false
  • autoComplete / textContentType: OS의 자동 채우기(비밀번호 매니저, OTP)와 연동. 예: autoComplete="one-time-code", textContentType="oneTimeCode"
  • placeholder color: stone-300 (= DesignColors.warmGray[300])
  • return key: 마지막 필드는 returnKeyType="done", 다음 필드로 이동이면 "next". onSubmitEditing으로 명시적 처리
  • 에러 표시: 에러 메시지는 text-rose-600, 입력 테두리는 border-rose-300. 메시지는 입력 아래 caption1Regular
  • 포커스 시 스크롤: 키보드에 가려지지 않도록 ScrollView/BottomSheet가 자동 스크롤 (BottomSheet 키보드 처리는 Dialog Mobile 참조)
  • autoFocus: 사용자가 입력을 기대하는 명시적 진입(예: "이름 입력" 시트)에서만 — 일반 폼에선 사용자 탭 후 focus

Preview

Anatomy

┌──────────────────────────────────┐
│ Label text              [옵션 *]  │  ← Label
│ ┌────────────────────────────────┐│
│ │[prefix] Input value  [suffix]  ││  ← Input (prefix/suffix optional)
│ └────────────────────────────────┘│
│ Helper text or Error message      │  ← HelperText
└──────────────────────────────────┘

세 요소가 하나의 단위로 작동합니다. htmlFor / aria-describedby로 연결하여 스크린리더가 전체 맥락을 읽을 수 있게 합니다.


Variant

VariantStyle사용 시점
outline1px solid stone-200 4면 테두리 + rounded-md기본. 폼에 여러 필드가 있을 때
underlined하단 1px solid stone-200만 + rounded-none + 투명 배경화면에 입력 필드가 하나뿐일 때

States

StateBorderRingBackground
defaultstone-200white
focus (일반)brown-800white
focus (핵심 폼)brown-800ring-2 ring-brown-800/10white
with valuestone-200white
invalidrose-400ring-2 ring-rose-500/10white
disabledstone-100stone-50

Focus ring 사용 기준

Ring 없음Ring 있음
설정, 프로필 수정, 다이얼로그 내 폼 등 보조적 입력로그인, 회원가입, 결제 등 사용자가 집중해야 하는 핵심 폼
화면에 필드가 여러 개 있어 ring이 과도하게 강조될 때필드가 1–2개로 입력에 집중을 유도해야 할 때

disabled는 variant가 아니라 상태입니다. outline disabled, underlined disabled 모두 동일한 token 적용.

Common Behavior

  • Border는 항상 표시합니다. outline variant는 focus 여부와 무관하게 stone-200 border가 보여야 합니다. border 없이 focus glow만 사용하는 스타일(chat input, command palette 등)은 TextField가 아닌 별도 컴포넌트입니다.
  • Prefix icon은 필드의 종류를 빠르게 인지시키는 경우에만 사용합니다. 검색, 비밀번호, 이메일처럼 아이콘이 의미를 더할 때만 넣습니다.
  • Clear suffix는 focus 여부가 아니라 값의 존재에 따라 표시합니다. 값이 없으면 숨기고, 값이 있으면 노출합니다.
  • Focus 강조는 실제 focus일 때만 보여야 합니다. 검색창이라고 해서 항상 highlight된 상태로 두지 않습니다.
  • 검색/커맨드 입력처럼 필드가 하나뿐인 경우 underlined를, 설정/로그인/다이얼로그 폼처럼 여러 필드가 있는 경우 outline을 씁니다.
  • Prefix/Suffix 조합 규칙은 variant와 별개입니다. outline + prefix, underlined + clear 모두 조합 가능합니다.

Sizes

Default: md

SizeHeightpxpyText tokenUseMobile (≥44pt hit area)
sm32px10px6pxlabel1Regular 14/20Dense form, inline filter사용 안 함 (모바일은 md/lg만)
md40px12px10pxlabel1Regular 14/20Default (web)hitSlop 4pt 또는 lg로 승격 권장
lg48px16px12pxlabel1Regular 14/20Mobile primary (default) · 로그인✓ 기본 충족

Radius: rounded-md (sm/md/lg).


왼쪽 아이콘 (Prefix)

입력 필드 왼쪽에 아이콘을 배치합니다. 필드의 목적을 시각적으로 보강할 때 사용합니다.

  • 아이콘 색상: stone-400 (idle) · focus 시에도 유지
  • 아이콘 색상: stone-400 (default) · focus 시에도 유지
  • 아이콘 크기: sm 14px · md 16px · lg 18px
  • 좌측 padding을 아이콘이 대체 — pl-3 유지, 아이콘과 input 사이 gap-2

오른쪽 아이콘 (Suffix)

입력 필드 오른쪽에 인터랙티브 아이콘을 배치합니다. Clear 버튼, 비밀번호 토글 등에 사용합니다.

  • X (Clear) 버튼: 값이 있을 때만 표시 — 비어 있는 기본 상태에서는 숨김
  • 비밀번호 토글: 항상 표시
  • Suffix 아이콘은 모두 터치/클릭 가능한 버튼으로 구현 — aria-label 필수

양쪽 아이콘 (Prefix + Suffix)

검색 필드의 전형적인 조합입니다. 첫 줄은 비어 있는 기본 상태, 둘째 줄은 값이 들어온 상태입니다. Prefix는 항상 표시하고, Suffix(Clear)는 값이 있을 때만 표시합니다. focus ring은 실제 focus 시에만 추가합니다.


Sub-elements

Label

TokenValue
Typographylabel1Medium — 14px / 20 / Medium
Colorstone-700
Color (invalid)rose-600
Required mark*rose-500
Disabledopacity 50%

Label은 항상 Input 위에 위치합니다. Placeholder를 Label 대용으로 사용하지 않습니다.

HelperText

TokenValue
Typographycaption1Regular — 12px / 16 / Regular
Color (default)stone-400
Color (invalid)rose-600
Spacingmt-1.5 (6px) from Input

HelperText와 ErrorText는 같은 위치를 차지합니다. invalid 상태가 되면 ErrorText가 HelperText를 대체합니다.


Token Mapping

Tokenoutlineunderlined
border (default)1px solid stone-200 (4면)border-b 1px solid stone-200
border (focus)brown-800 (4면)brown-800 (하단만)
ring (focus)
border (invalid)rose-400 (4면)rose-400 (하단만)
ring (invalid)ring-2 ring-rose-500/10
radiusrounded-mdrounded-none
backgroundwhitetransparent
paddingpx-3px-0
disabled bgstone-50transparent

공통 토큰:

TokenValue
placeholderstone-200
textbrown-800
disabled textstone-400
error textrose-600
input textlabel1Regular
labellabel1Medium · stone-700
helpercaption1Regular · stone-400
prefix/suffix iconstone-400

Usage

// 기본
<TextField
  label="Workspace Name"
  placeholder="e.g. Q4 Planning"
  helperText="팀 워크스페이스 이름을 입력하세요."
/>

// Required + Error
<TextField
  label="이메일"
  required
  type="email"
  invalid
  errorText="올바른 이메일 형식이 아닙니다."
  value={email}
  onChange={setEmail}
/>

// Prefix 아이콘 (검색)
<TextField
  placeholder="노트 검색..."
  prefixIcon={<SearchIcon />}
  value={query}
  onChange={setQuery}
/>

// Suffix 아이콘 (Clear)
<TextField
  label="검색"
  prefixIcon={<SearchIcon />}
  suffixIcon={query ? <ClearButton onClick={() => setQuery('')} /> : null}
  value={query}
  onChange={setQuery}
/>

// Suffix 아이콘 (비밀번호 토글)
<TextField
  label="비밀번호"
  type={show ? 'text' : 'password'}
  prefixIcon={<LockIcon />}
  suffixIcon={<EyeToggle onClick={() => setShow(!show)} />}
/>

A11y

  • labelhtmlForinputid를 반드시 연결합니다.
  • invalid 상태에서 aria-invalid="true"aria-describedby로 ErrorText를 연결합니다.
  • required 필드는 * 시각 표시 외 aria-required="true"를 병행합니다.
  • disabled 상태에서 레이블도 같이 흐려야 하며, 이유를 tooltip 또는 HelperText로 안내합니다.
  • Suffix 버튼(Clear, 비밀번호 토글 등)은 모두 aria-label 필수.
  • Label 없이 prefix 아이콘만 있는 경우 aria-label 또는 visually hidden Label 제공.

Do / Don't

  • Do: 모든 입력 필드에 Label 제공
  • Do: invalid는 border 색상 + ErrorText 문자로 이중 전달 (색맹 대응)
  • Do: HelperText로 입력 형식 사전 안내 (예: "이름@회사.com 형식")
  • Do: Clear(X) 버튼은 값이 있을 때만 표시
  • Do: 화면에 입력 필드가 하나뿐이면 underlined 사용 — 더 가볍고 집중적
  • Don't: outline 필드에서 기본 border 제거 금지 — 필드 영역이 불명확해짐 (focus glow만 사용 금지)
  • Don't: placeholder를 label 대용으로 사용 — 포커스 시 사라져 맥락을 잃음
  • Don't: Label과 HelperText를 동일 내용으로 중복 작성
  • Don't: 같은 폼에서 크기를 혼용 (sm/lg 혼합 금지)
  • Don't: 여러 필드가 있는 폼에 underlined 혼용 금지 — 경계가 불명확해짐
  • Don't: Suffix 버튼에 aria-label 없이 아이콘만 배치 금지

On this page