본문으로 건너뛰기

ZSTextField

라벨·안내 문구·오류·글자 수를 갖춘 텍스트 입력입니다. 입력은 React Native TextInput이고 둘레 모양은 zs-ui가 그려 iOS·Android에서 같습니다. 라벨은 비어 있으면 칸 안에 있다가 포커스·값이 있으면 떠오릅니다.

기본 사용법​

import { useState } from 'react';
import { ZSTextField } from '@0610studio/zs-ui';

function NameField() {
const [name, setName] = useState('');
return <ZSTextField label="이름" value={name} onChangeText={setName} helperText="실명으로 입력하세요" required />;
}

라벨은 필수입니다(M3·HIG — placeholder로 라벨을 대신하지 않습니다). placeholder는 라벨이 떠오른 뒤에만 보입니다.

Props — ZSTextFieldProps​

PropTypeDefault설명
labelstringRequired항상 보이는 라벨
variantZSTextFieldVariant'outlined''outlined' | 'inbox' | 'underline' — variant
valuestringundefined주면 제어 모드
defaultValuestringundefined비제어 모드 초기값
onChangeText(text: string) => voidundefined값 변경. 지우기 버튼도 이것으로 ''를 넘깁니다
helperTextstringundefined필드 아래 안내 문구
errorTextstringundefined있으면 오류 상태 — 안내 문구 대신 보입니다
requiredbooleanfalse라벨 뒤 *
clearablebooleantrue값이 있고 포커스일 때 지우기 버튼
clearAccessibilityLabelstring'Clear text'지우기 버튼의 스크린 리더 이름. 앱 전체 기본값은 ThemeProvider accessibilityLabels.clearText로 바꿉니다
showCountbooleanfalsemaxLength와 함께 현재/최대 글자 수
disabledbooleanfalse편집 불가(editable={false})와 비활성 색
multilinebooleanfalse여러 줄 입력
minRowsnumber1multiline 최소 줄 수
maxRowsnumberundefinedmultiline 최대 줄 수 — 넘으면 칸 안에서 스크롤합니다. 없으면 계속 늘어납니다
startAdornmentReactNodeundefined입력 앞 요소(아이콘 등). 있으면 라벨이 늘 떠 있습니다
endAdornmentReactNodeundefined입력 뒤 요소(단위·비밀번호 보기 버튼 등)
maxFontSizeMultipliernumber앱 상한글자 확대 상한. 주지 않으면 앱 상한(기본 2배). 라벨·칸 높이도 같은 배율로 맞춥니다
styleStyleProp<ViewStyle>undefined바깥 컨테이너 스타일
inputStyleTextInputProps['style']undefinedTextInput 스타일
...propsTextInputPropsundefinedplaceholder·keyboardType·maxLength·onFocus·onBlur·returnKeyType 등(style·editable 제외)

ref는 TextInput 인스턴스(ZSTextFieldRef)입니다 — ref.current?.focus(). ZSTextFieldProps·ZSTextFieldRef·ZSTextFieldVariant 타입을 내보냅니다.

variant​

높이는 기본 글자 크기에서 한 줄 칸의 높이이고, 글자 크기 설정이 커지면 함께 늘어납니다. 모서리는 두 플랫폼 모두 16(lg)이고, 좌우 안쪽 여백(underline 제외)은 두 플랫폼 모두 16이라 iOS ZSSelect의 라벨·값과 글자 시작선이 맞습니다.

variant모양iOS 높이Android 높이
outlined (기본)테두리 박스. 떠오른 라벨이 위 테두리에 걸리고 그 자리의 선이 비워집니다(배경을 깔지 않아 어떤 배경 위에서도 됩니다)52pt56dp
inbox테두리 박스 + 바탕색 면(background). 라벨이 칸 안 위쪽으로 떠오릅니다56pt56dp
underline아래 선만. 라벨이 입력 줄 위로 떠오르고 좌우 여백이 없습니다52pt52dp

제어·비제어​

value를 주면 제어, 주지 않으면 defaultValue로 시작하는 비제어입니다. 필드가 많은 폼에서는 비제어가 가볍습니다 — 키 입력마다 부모가 다시 그려지지 않습니다. 값은 onChangeText나 onEndEditing으로 받습니다.

<ZSTextField label="이메일" value={email} onChangeText={setEmail} />

const codeRef = useRef('');
<ZSTextField label="인증번호" defaultValue="" onChangeText={(text) => (codeRef.current = text)} maxLength={6} showCount />

상태​

<ZSTextField label="이메일" value={email} onChangeText={setEmail} keyboardType="email-address" errorText={emailError} />

<ZSTextField label="메모" value={memo} onChangeText={setMemo} multiline minRows={2} maxRows={5} maxLength={200} showCount />

<ZSTextField variant="inbox" label="몸무게" keyboardType="decimal-pad" endAdornment={<ZSText color="textSecondary">kg</ZSText>} />

<ZSTextField variant="underline" label="아이디" value="zs-ui" disabled />
상태테두리·선라벨
기본borderStrong 1(세 variant 같음)textSecondary
포커스text 2text
오류error 2 + 끝에 오류 아이콘error
비활성text 12% 1 — 오류 문구가 있어도 같습니다글자·라벨 text 38%

포커스·오류 테두리(2)는 기본 테두리(1) 위에 겹쳐 그립니다. 두께가 끊겨 바뀌지 않고, 위 테두리의 색·불투명도만 짧게 페이드합니다.

  • 포커스 테두리·라벨·커서·선택 손잡이는 text입니다. 얇은 표시라 primary로 그리지 않습니다(색 규칙). 오류면 error입니다. Android 선택 영역은 같은 색 40%입니다.
  • 값·라벨·placeholder는 body1 강조 굵기 하나로 그립니다.
  • placeholder는 textSecondary를 칸 면 쪽으로 조금 옅게 옮긴 회색입니다. 값보다 옅고 라벨과도 갈리며, 칸 면 위 4.5:1을 지킵니다.

접근성​

  • 이름은 accessibilityLabel(기본 label), 힌트는 오류 문구 또는 안내 문구입니다. 그려진 라벨 글자는 스크린 리더에서 숨겨 두 번 읽히지 않습니다.
  • 오류 문구가 새로 생기거나 바뀌면 스크린 리더가 읽습니다. iOS(VoiceOver)는 라벨과 오류 문구를 이어 읽고, 앞 안내를 끊지 않고 차례로 읽어 여러 칸에 한꺼번에 오류가 생겨도 모두 들립니다. 처음 그릴 때부터 있던 문구는 읽지 않습니다. Android(TalkBack)는 accessibilityLiveRegion="polite"로 읽습니다.
  • 지우기 버튼은 보이는 원보다 넓은 터치 영역(iOS 44pt·Android 48dp)을 갖고, 누르면 ZSPressable과 같은 누름 표시(iOS 하이라이트·Android ripple)가 보입니다.

관련 문서​