여러 줄의 긴 텍스트를 입력받고 자동으로 높이를 조절하는 컴포넌트입니다.
@seed-design/lynx-react@0.4.0, @seed-design/lynx-css@0.7.0
import "./styles" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" >
< TextField label = "라벨" >
< TextFieldTextarea accessibility-label = "라벨" />
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
React의 autoFocus에 대응하는 prop은 지원하지 않습니다. 처음부터 포커스해야 한다면 화면이 렌더링된 뒤 TextFieldTextarea ref에서 native focus UI method를 호출합니다.
npx @seed-design/cli add ui:text-field pnpm dlx @seed-design/cli add ui:text-field yarn dlx @seed-design/cli add ui:text-field bun x @seed-design/cli add ui:text-field
의존성 설치
npm install @seed-design/lynx-react yarn add @seed-design/lynx-react pnpm add @seed-design/lynx-react bun add @seed-design/lynx-react 아래 코드를 복사 후 붙여넣고 사용하세요 /**
* @file ui:text-field
* @requires @seed-design/lynx-react@>=0.1.0 <1.0.0
* @requires @seed-design/lynx-css@>=0.1.0 <1.0.0
**/
import * as React from "@lynx-js/react" ;
import {
Field as SeedField,
TextField as SeedTextField,
type UseTextFieldWithGraphemesParams,
useTextFieldWithGraphemes,
} from "@seed-design/lynx-react" ;
type TextFieldRootRef = React . ComponentRef < typeof SeedTextField.Root>;
type FieldRootRef = React . ComponentRef < typeof SeedField.Root>;
export interface TextFieldProps
extends Omit < SeedTextField . RootProps , "children" | "onValueChange" > {
children ?: React . ReactNode ;
label ?: React . ReactNode ;
labelWeight ?: SeedField . LabelProps [ "weight" ];
indicator ?: React . ReactNode ;
prefixIcon ?: SeedTextField . PrefixIconProps [ "icon" ];
prefix ?: React . ReactNode ;
suffixIcon ?: SeedTextField . SuffixIconProps [ "icon" ];
suffix ?: React . ReactNode ;
description ?: React . ReactNode ;
errorMessage ?: React . ReactNode ;
hideCharacterCount ?: boolean ;
maxGraphemeCount ?: number ;
showRequiredIndicator ?: boolean ;
fieldRef ?: React . Ref < FieldRootRef >;
onValueChange ?: UseTextFieldWithGraphemesParams [ "onValueChange" ];
}
/**
* @see https://seed-design.io/lynx/components/text-field-input
*/
export const TextField = React. forwardRef < TextFieldRootRef , TextFieldProps >(
(
{
children,
label,
labelWeight,
indicator,
prefixIcon,
prefix,
suffixIcon,
suffix,
description,
errorMessage,
hideCharacterCount,
maxGraphemeCount,
showRequiredIndicator,
fieldRef,
value,
defaultValue,
onValueChange,
required,
disabled,
invalid,
readOnly,
name,
... rootProps
},
ref,
) => {
const { textFieldRootProps , counterProps } = useTextFieldWithGraphemes ({
value,
defaultValue,
onValueChange,
maxGraphemeCount,
});
const renderHeader = label != null || indicator != null ;
const renderDescription = description != null && ! (invalid && errorMessage != null );
const renderErrorMessage = invalid && errorMessage != null ;
const renderCharacterCount = ! hideCharacterCount && maxGraphemeCount !== undefined ;
const renderFooter = renderDescription || renderErrorMessage || renderCharacterCount;
return (
< SeedField.Root
ref = {fieldRef}
required = {required}
disabled = {disabled}
invalid = {invalid}
readOnly = {readOnly}
>
{renderHeader ? (
< SeedField.Header >
< SeedField.Label weight = {labelWeight}>
{label}
{showRequiredIndicator ? < SeedField.RequiredIndicator /> : null }
{indicator != null ? (
< SeedField.IndicatorText >{indicator}</ SeedField.IndicatorText >
) : null }
</ SeedField.Label >
</ SeedField.Header >
) : null }
< SeedTextField.Root ref = {ref} name = {name} { ... rootProps} { ... textFieldRootProps}>
{prefixIcon ? < SeedTextField.PrefixIcon icon = {prefixIcon} /> : null }
{prefix != null ? < SeedTextField.PrefixText >{prefix}</ SeedTextField.PrefixText > : null }
{children}
{suffix != null ? < SeedTextField.SuffixText >{suffix}</ SeedTextField.SuffixText > : null }
{suffixIcon ? < SeedTextField.SuffixIcon icon = {suffixIcon} /> : null }
</ SeedTextField.Root >
{renderFooter ? (
< SeedField.Footer >
{renderDescription ? (
< SeedField.Description >{description}</ SeedField.Description >
) : null }
{renderErrorMessage ? (
< SeedField.ErrorMessage >{errorMessage}</ SeedField.ErrorMessage >
) : null }
{renderCharacterCount ? < SeedField.CharacterCount { ... counterProps} /> : null }
</ SeedField.Footer >
) : null }
</ SeedField.Root >
);
},
);
TextField.displayName = "TextField" ;
export interface TextFieldInputProps extends SeedTextField . InputProps {}
/**
* @see https://seed-design.io/lynx/components/text-field-input
*/
export const TextFieldInput = SeedTextField.Input;
export interface TextFieldTextareaProps extends SeedTextField . TextareaProps {}
/**
* @see https://seed-design.io/lynx/components/text-field-textarea
*/
export const TextFieldTextarea = SeedTextField.Textarea;
/**
* This file is a snippet from SEED Design, helping you get started quickly with @seed-design/* packages.
* You can extend this snippet however you want.
*/
children?React.ReactNode
label?React.ReactNode
labelWeight?"medium" | "bold" | undefined
indicator?React.ReactNode
prefixIcon?React.ReactElement < LynxIconElementProps, string | React.JSXElementConstructor < any >> | undefined
prefix?React.ReactNode
suffixIcon?React.ReactElement < LynxIconElementProps, string | React.JSXElementConstructor < any >> | undefined
suffix?React.ReactNode
description?React.ReactNode
errorMessage?React.ReactNode
hideCharacterCount?boolean | undefined
maxGraphemeCount?number | undefined
showRequiredIndicator?boolean | undefined
fieldRef?React.Ref < NodesRef > | undefined
onValueChange?(( values : { value : string ; graphemes : string []; slicedValue : string ; slicedGraphemes : string []; }) => void ) | undefined
variant?"outline" | "underline" | undefined
size?"medium" | "large" | undefined
invalid?boolean | undefined
readOnly?boolean | undefined
disabled?boolean | undefined
value?string | undefined
defaultValue?string | undefined
required?boolean | undefined
name?string | undefined
style?CSSProperties | undefined
className?string | undefined
autoresize?boolean | undefined
placeholder?string | undefined
confirm-type?"send" | "search" | "go" | "done" | "next" | undefined
maxlength?number | undefined
maxlines?number | undefined
bounces?boolean | undefined
line-spacing?number | `${ number }px` | `${ number }rpx` | undefined
readonly?boolean | undefined
disabled?boolean | undefined
input-filter?string | undefined
enable-scroll-bar?boolean | undefined
type?"number" | "text" | "digit" | "tel" | "email" | undefined
ios-auto-correct?boolean | undefined
ios-spell-check?boolean | undefined
android-fullscreen-mode?boolean | undefined
bindfocus?(( e : BaseEvent < "bindfocus" , TextAreaFocusEvent >) => void ) | undefined
bindblur?(( e : BaseEvent < "bindblur" , TextAreaBlurEvent >) => void ) | undefined
bindconfirm?(( e : BaseEvent < "bindconfirm" , TextAreaConfirmEvent >) => void ) | undefined
bindinput?(( e : BaseEvent < "bindinput" , TextAreaInputEvent >) => void ) | undefined
bindselection?(( e : BaseEvent < "bindselection" , TextAreaSelectionChangeEvent >) => void ) | undefined
id?string | undefined
name?string | undefined
hidden?boolean | undefined
flatten?boolean | undefined
focusable?boolean | undefined
bindlayoutchange?EventHandler < LayoutChangeDetailEvent < Target >> | undefined
main-thread:bindlayoutchange?EventHandler < LayoutChangeDetailEvent < Element >> | undefined
style?CSSProperties | undefined
className?string | undefined
import "./styles" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" gap = "x5" >
< TextField label = "라벨" description = "설명을 써주세요" >
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField
label = "라벨"
description = "설명을 써주세요"
invalid
errorMessage = "오류가 발생한 이유를 써주세요"
>
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
import "./styles" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" gap = "x5" >
< TextField label = "라벨" description = "설명을 써주세요" disabled >
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField
label = "라벨"
description = "설명을 써주세요"
disabled
invalid
errorMessage = "오류가 발생한 이유를 써주세요"
>
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
import "./styles" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" gap = "x5" >
< TextField label = "라벨" description = "설명을 써주세요" readOnly >
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField
label = "라벨"
description = "설명을 써주세요"
readOnly
invalid
errorMessage = "오류가 발생한 이유를 써주세요"
>
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
size로 TextField의 크기를 정합니다. (default: large)
Lynx에서는 large와 medium을 지원합니다. CSS viewport breakpoint가 없어 responsive는 지원하지 않습니다.
import "./styles" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" gap = "spacingY.componentDefault" >
< TextField label = "라벨" description = "size=large (default)" size = "large" >
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField label = "라벨" description = "size=medium" size = "medium" >
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField variant = "underline" description = "size=large (default)" size = "large" >
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField variant = "underline" description = "size=medium" size = "medium" >
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
<TextFieldTextarea>에 height 관련 스타일을 직접 지정하여 높이를 고정하거나 최소·최대 높이를 설정할 수 있습니다.
고정 높이를 사용할 때는 autoresize={false}와 명시적인 height를 함께 지정합니다.
import "./styles" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" >
< TextField label = "라벨" description = "설명을 써주세요" >
< TextFieldTextarea
accessibility-label = "라벨"
placeholder = "플레이스홀더"
autoresize = { false }
style = {{ height: "250px" }}
/>
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
import "./styles" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" >
< TextField label = "라벨" description = "설명을 써주세요" >
< TextFieldTextarea
accessibility-label = "라벨"
placeholder = "플레이스홀더"
style = {{ minHeight: "200px" , maxHeight: "300px" }}
/>
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
indicator 또는 showRequiredIndicator prop을 사용할 수 있습니다.
import "./styles" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" gap = "spacingY.componentDefault" >
< TextField
label = "선택 필드"
labelWeight = "bold"
description = "설명을 써주세요"
indicator = "선택"
>
< TextFieldTextarea accessibility-label = "선택 필드" placeholder = "플레이스홀더" />
</ TextField >
< TextField label = "필수 필드" description = "설명을 써주세요" required >
< TextFieldTextarea accessibility-label = "필수 필드" placeholder = "플레이스홀더" />
</ TextField >
< TextField label = "필수 필드" description = "설명을 써주세요" required showRequiredIndicator >
< TextFieldTextarea accessibility-label = "필수 필드" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
import "./styles" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" gap = "x3" >
< TextField label = "라벨" description = "설명을 써주세요" maxGraphemeCount = { 8 }>
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
value를 사용자 인식 문자(grapheme cluster) 단위로 나눈 결과를 onValueChange 콜백의 graphemes와 slicedGraphemes로 제공합니다.
문자 분리는 unicode-segmenter 를 통해 이루어집니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
const [ value , setValue ] = useState ( "" );
const [ graphemes , setGraphemes ] = useState < string []>([]);
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" gap = "x4" >
< TextField
label = "라벨"
description = "국기 이모지 🇰🇷 를 추가해보세요."
maxGraphemeCount = { 100 }
value = {value}
onValueChange = {({ slicedValue , slicedGraphemes }) => {
setValue (slicedValue);
setGraphemes (slicedGraphemes);
}}
>
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< VStack gap = "x2" >
< text className = "text-field-textarea-preview__status" >
graphemes.length: { JSON . stringify (graphemes. length )}
</ text >
< text className = "text-field-textarea-preview__status" >
value.length: { JSON . stringify (value. length )}
</ text >
< text className = "text-field-textarea-preview__status" >
graphemes: { JSON . stringify (graphemes)}
</ text >
< text className = "text-field-textarea-preview__status" >value: {value}</ text >
</ VStack >
</ VStack >
</ VStack >
</ view >
);
}
Lynx는 HTML Form을 지원하지 않습니다. value와 onValueChange를 사용해 입력값을 React state로 관리할 수 있습니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
const [ value , setValue ] = useState ( "안녕하세요" );
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" gap = "x3" >
< TextField
label = "자기소개"
description = "입력값을 React state로 관리합니다."
value = {value}
onValueChange = {({ value : nextValue }) => setValue (nextValue)}
>
< TextFieldTextarea accessibility-label = "자기소개" placeholder = "저는…" />
</ TextField >
< text className = "text-field-textarea-preview__status" >입력값: {value}</ text >
</ VStack >
</ VStack >
</ view >
);
}
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
const [ value , setValue ] = useState ( "" );
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" >
< TextField
label = "레이블"
description = "공백을 입력할 수 없어요"
value = {value}
onValueChange = {({ value : nextValue }) => setValue (nextValue. replace ( / / g , "" ))}
>
< TextFieldTextarea accessibility-label = "레이블" placeholder = "공백을 입력해보세요" />
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
const [ value , setValue ] = useState ( "" );
return (
< view className = { `${ seedClassName } docs-lynx-text-field-textarea-root` }>
< VStack width = "full" height = "full" align = "center" justify = "center" >
< VStack width = "full" maxWidth = "480px" >
< TextField
label = "라벨"
description = "6글자까지 입력 가능합니다"
maxGraphemeCount = { 6 }
value = {value}
onValueChange = {({ slicedValue }) => setValue (slicedValue)}
>
< TextFieldTextarea accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ view >
);
}
TextFieldTextarea는 기본적으로 Lynx native textarea의 측정 기능을 사용해 내용에 맞춰 높이가 늘어납니다. iOS에서는 크기 측정용 래퍼가 최소 높이와 세로 여백을 맡고, Android에서는 native textarea가 직접 맡습니다. 실제 영역의 높이가 달라지면 KeyboardAvoidingScrollView의 회피 위치를 다시 계산합니다.
Android에서는 SEED typography의 줄 높이를 맞추기 위해 line-spacing="3.2px"를 기본 적용합니다. line-spacing을 명시하면 모든 플랫폼에서 해당 값이 우선하며, Android의 기본 보정은 line-spacing={0}으로 해제할 수 있습니다. fontSize나 lineHeight를 직접 변경한다면 이에 맞는 line-spacing도 함께 지정해야 합니다.
KeyboardAvoidingScrollView 안에 배치하면 TextFieldTextarea가 focus될 때 자동으로 등록됩니다. autoresize로 레이아웃이 바뀌면 활성 입력 위치를 다시 계산합니다.
import { KeyboardAvoidingScrollView } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
export function KeyboardAwareFields () {
return (
< KeyboardAvoidingScrollView >
< TextField label = "내용" >
< TextFieldTextarea accessibility-label = "내용" />
</ TextField >
</ KeyboardAvoidingScrollView >
);
}
편집 가능한 상태에서는 HTML <textarea> 대신 Lynx native <textarea> element를 렌더링합니다.
readOnly 상태에서는 native focus·selection·잘라내기 메뉴를 제거하기 위해 <text> element로 렌더링합니다. 이 상태의 ref는 <text>를 가리키며 textarea 전용 UI method와 이벤트는 사용할 수 없습니다.
onChange 대신 snippet TextField의 onValueChange를 사용합니다. 원문과 grapheme 단위로 자른 값을 함께 제공합니다.
native bindinput은 TextFieldTextarea에 추가로 전달할 수 있습니다.
Field.Label과 입력의 DOM id 연결이 없으므로 accessibility-label을 입력에 직접 제공합니다.
autoresize는 DOM scrollHeight 대신 native intrinsic height를 사용합니다. iOS에서는 크기 측정용 래퍼가 세로 여백과 최소 높이를 소유해 첫 입력 시 native content size에 여백이 중복되지 않게 합니다. Android에서는 native textarea가 세로 여백과 최소 높이를 직접 소유합니다.
Android에서는 CSS line-height가 native textarea에 적용되지 않아 line-spacing="3.2px"를 기본 적용합니다. 명시적인 line-spacing 값이 이 기본값보다 우선합니다.
controlled textarea도 native 입력 이벤트를 그대로 유지하고, 외부에서 값이 달라진 경우에만 setValue로 동기화합니다. 입력마다 readonly를 토글하지 않아 줄 추가 시 native scroll offset과 높이 측정이 초기화되지 않습니다.
포커스 시 키보드가 나타나도록 show-soft-input-on-focus의 기본값은 true입니다. undefined가 native attribute로 전달되지 않도록 컴포넌트가 이 기본값을 명시적으로 적용합니다. 커스텀 키보드를 사용하는 경우에는 false로 재정의할 수 있습니다.
Android의 fullscreen extract input은 기본적으로 비활성화합니다. 필요한 경우 android-fullscreen-mode={true}를 명시합니다.
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을 명시합니다.
HTML form submit, browser validation, React Hook Form, aria-describedby id 연결은 지원하지 않습니다.
큰 textarea에서 현재 caret 위치만 기준으로 키보드를 회피하는 기능은 지원하지 않습니다. 현재는 Field·TextField·native 입력 영역 중 안전 영역에 맞는 가장 큰 영역을 선택합니다.