# Text Field Input URL: /lynx/components/text-field-input Source: https://github.com/daangn/seed-design/blob/dev/docs/content/lynx/components/text-field-input.mdx 한 줄 텍스트를 입력받고 Field의 레이블·설명·오류 상태와 조합하는 컴포넌트입니다. Lynx Engine 최소 버전: 3.6 사용 XElement: 사용 가능 버전: @seed-design/lynx-react@0.4.0, @seed-design/lynx-css@0.7.0 ## Preview ```tsx import "./styles"; import { root } from "@lynx-js/react"; import { Field, TextField, VStack, useSeedClassName } from "@seed-design/lynx-react"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( 제목 한 줄로 제목을 입력해 주세요. ); } root.render(); ``` ## Installation - npm: npx @seed-design/cli add ui:text-field - pnpm: pnpm dlx @seed-design/cli add ui:text-field - yarn: yarn dlx @seed-design/cli add ui:text-field - bun: bun x @seed-design/cli add ui:text-field ## Props ### `TextField` ### `TextFieldInput` ## Examples ### State #### Enabled ```tsx import "./styles"; import { root } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( ); } root.render(); ``` #### Disabled ```tsx import "./styles"; import { root } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( ); } root.render(); ``` #### Read Only ```tsx import "./styles"; import { root } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( ); } root.render(); ``` ### Size `size`로 TextField의 크기를 정합니다. (default: `large`) Lynx에서는 `large`와 `medium`을 지원합니다. CSS viewport breakpoint가 없어 `responsive`는 지원하지 않습니다. ```tsx import "./styles"; import { root } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( ); } root.render(); ``` ### Customizable Parts 아이콘만으로 맥락을 전달할 때는 `description` 또는 `label`에 아이콘의 의미를 설명하는 텍스트를 포함하세요. 아이콘 자체를 읽어야 한다면 `accessibility-label`을 지정하세요. #### Prefix ```tsx import "./styles"; import IconMagnifyingglassLine from "@karrotmarket/lynx-monochrome-icon/IconMagnifyingglassLine"; import { root } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( } > } > ); } root.render(); ``` #### Suffix ```tsx import "./styles"; import IconWonLine from "@karrotmarket/lynx-monochrome-icon/IconWonLine"; import { root } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( }> }> ); } root.render(); ``` #### Both Affixes ```tsx import "./styles"; import IconPlusCircleLine from "@karrotmarket/lynx-monochrome-icon/IconPlusCircleLine"; import IconWonLine from "@karrotmarket/lynx-monochrome-icon/IconWonLine"; import { root } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( } suffixIcon={} > } suffixIcon={} > ); } root.render(); ``` #### Indicator `indicator` 또는 `showRequiredIndicator` prop을 사용할 수 있습니다. ```tsx import "./styles"; import { root } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( ); } root.render(); ``` #### Grapheme Count ```tsx import "./styles"; import { root } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( ); } root.render(); ``` `value`를 사용자 인식 문자(grapheme cluster) 단위로 나눈 결과를 `onValueChange` 콜백의 `graphemes`와 `slicedGraphemes`로 제공합니다. 문자 분리는 [unicode-segmenter](https://github.com/cometkim/unicode-segmenter)를 통해 이루어집니다. ```tsx import "./styles"; import { root, useState } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); const [value, setValue] = useState(""); const [graphemes, setGraphemes] = useState([]); return ( { setValue(slicedValue); setGraphemes(slicedGraphemes); }} > graphemes.length: {JSON.stringify(graphemes.length)} value.length: {JSON.stringify(value.length)} graphemes: {JSON.stringify(graphemes)} value: {value} ); } root.render(); ``` ### Use Cases #### Controlled State Lynx는 HTML Form을 지원하지 않습니다. `value`와 `onValueChange`를 사용해 입력값을 React state로 관리할 수 있습니다. ```tsx import "./styles"; import { root, useState } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); const [value, setValue] = useState("안녕하세요"); return ( setValue(nextValue)} > 입력값: {value} ); } root.render(); ``` #### Number Formatting ```tsx import "./styles"; import { root, useState } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function formatNumber(value: string) { const digits = value.replace(/\D/g, ""); return digits.replace(/\B(?=(\d{3})+(?!\d))/g, ","); } function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); const [value, setValue] = useState("1,000"); return ( setValue(formatNumber(nextValue))} > ); } root.render(); ``` #### Slicing ```tsx import "./styles"; import { root, useState } from "@lynx-js/react"; import { useSeedClassName, VStack } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); const [value, setValue] = useState(""); return ( setValue(slicedValue)} > ); } root.render(); ``` ### Lynx Usage #### Keyboard Avoidance `KeyboardAvoidingScrollView` 안에 배치하면 `TextFieldInput`이 focus될 때 자동으로 등록되어 키보드에 가려지지 않는 위치로 스크롤됩니다. ```tsx import { KeyboardAvoidingScrollView } from "@seed-design/lynx-react"; import { TextField, TextFieldInput } from "@/components/ui/text-field"; export function KeyboardAwareFields() { return ( ); } ``` ## Web Version Differences - 편집 가능한 상태에서는 HTML `` 대신 Lynx native `` element를 렌더링합니다. - `readOnly` 상태에서는 native focus·selection·잘라내기 메뉴를 제거하기 위해 `` element로 렌더링합니다. 이 상태의 ref는 ``를 가리키며 input 전용 UI method와 이벤트는 사용할 수 없습니다. - `onChange` 대신 snippet `TextField`의 `onValueChange`를 사용합니다. 원문과 grapheme 단위로 자른 값을 함께 제공합니다. - native `bindinput`은 `TextFieldInput`에 추가로 전달할 수 있습니다. - `Field.Label`과 입력의 DOM id 연결이 없으므로 `accessibility-label`을 입력에 직접 제공합니다. - 포커스 시 키보드가 나타나도록 `show-soft-input-on-focus`의 기본값은 `true`입니다. `undefined`가 native attribute로 전달되지 않도록 컴포넌트가 이 기본값을 명시적으로 적용합니다. 커스텀 키보드를 사용하는 경우에는 `false`로 재정의할 수 있습니다. - `android-set-soft-input-mode`의 기본값은 `"unspecified"`입니다. Android에서 `undefined`가 native attribute로 전달되면 오류가 발생할 수 있어 컴포넌트가 이 기본값을 명시적으로 적용합니다. - `android-set-soft-input-mode`는 입력 요소가 포함된 host window 전역에 영향을 줍니다. 기본값인 `"unspecified"`도 기존 Activity 설정을 그대로 보존하는 값이 아니라 시스템 판단 모드로 다시 설정합니다. `KeyboardAvoidingScrollView`가 키보드 회피를 전담하는 화면에서는 별도 pan/resize를 막기 위해 `"nothing"`으로 재정의합니다. 같은 window에 있는 입력 요소에는 가능한 한 같은 값을 사용합니다. - `size="responsive"`는 CSS viewport breakpoint가 없는 Lynx에서 지원하지 않습니다. `large` 또는 `medium`을 명시합니다. ## Unsupported Lynx Features - HTML form submit, browser validation, React Hook Form, `aria-describedby` id 연결은 지원하지 않습니다.