소프트 키보드가 활성 입력을 가리지 않도록 세로 스크롤 위치와 하단 여백을 조정하는 컴포넌트입니다.
@seed-design/lynx-react@0.4.0
npm install @seed-design/lynx-react pnpm add @seed-design/lynx-react yarn add @seed-design/lynx-react bun add @seed-design/lynx-react
아래 예제에서 사용하는 Text Field 레지스트리 스니펫도 추가합니다.
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
id?string | undefined
hidden?boolean | undefined
focusable?boolean | undefined
bounces?boolean | undefined
enable-scroll?boolean | undefined
scroll-bar-enable?boolean | undefined
upper-threshold?number | undefined
lower-threshold?number | undefined
initial-scroll-offset?number | undefined
initial-scroll-to-index?number | undefined
bindlayoutchange?EventHandler < LayoutChangeDetailEvent < Target >> | undefined
bindscrolltoupper?(( e : ScrollToUpperEvent ) => void ) | undefined
bindscrolltolower?(( e : ScrollToLowerEvent ) => void ) | undefined
bindscroll?(( e : ScrollEvent ) => void ) | undefined
bindscrollend?(( e : ScrollEndEvent ) => void ) | undefined
bindcontentsizechanged?(( e : ContentSizeChangedEvent ) => void ) | undefined
style?CSSProperties | undefined
children?ReactNode
className?string | undefined
bindtap?EventHandler < BaseTouchEvent < Target >> | undefined
bindtouchstart?EventHandler < BaseTouchEvent < Target >> | undefined
bindtouchend?EventHandler < BaseTouchEvent < Target >> | undefined
bindtouchcancel?EventHandler < BaseTouchEvent < Target >> | undefined
main-thread:bindtap?EventHandler < BaseTouchEvent < Element >> | undefined
세로로 스크롤되는 입력 화면의 가장 바깥 영역에 배치합니다. keyboardGap은 키보드와 활성 입력 영역 사이의 간격입니다. scrollBehavior는 회피 위치로 이동하는 방식을 정합니다.
Text Field Input과 Text Field Textarea의 레지스트리 스니펫이 제공하는 TextField 안에 입력 요소를 배치합니다. 이 TextField가 내부에 만드는 Field 경계를 기준으로 입력 영역과 하단을 추적합니다. 입력 요소가 focus·blur·layout 변경을 자동으로 전달하므로 별도 등록 prop은 필요하지 않습니다.
Android에서 이 컴포넌트가 키보드 회피를 전담한다면 입력 요소에 android-set-soft-input-mode="nothing"을 지정합니다. host window의 별도 pan이나 resize와 회피 동작이 겹치지 않게 합니다.
화면 아래쪽의 TextField.Input에 focus하면 입력 영역과 키보드 사이에 24px 간격이 생기도록 자동 스크롤합니다.
import "./styles" ;
import { root } from "@lynx-js/react" ;
import { KeyboardAvoidingScrollView, useSeedClassName } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< KeyboardAvoidingScrollView
className = "keyboard-avoiding-scroll-view-preview"
keyboardGap = { 24 }
scrollBehavior = "smooth"
>
< view className = "keyboard-avoiding-scroll-view-preview__content" >
< text className = "keyboard-avoiding-scroll-view-preview__title" >한 줄 입력</ text >
< text className = "keyboard-avoiding-scroll-view-preview__description" >
아래 입력 영역을 탭하면 키보드 위로 자동 스크롤됩니다.
</ text >
< view className = "keyboard-avoiding-scroll-view-preview__spacer" >
< text className = "keyboard-avoiding-scroll-view-preview__spacer-label" >
입력 영역이 화면 아래에 오도록 확보한 공간
</ text >
</ view >
< view className = "keyboard-avoiding-scroll-view-preview__field" >
< TextField label = "주소" >
< TextFieldInput
accessibility-label = "주소"
android-set-soft-input-mode = "nothing"
maxlength = { 80 }
placeholder = "동네 이름을 입력해 주세요"
/>
</ TextField >
</ view >
< view className = "keyboard-avoiding-scroll-view-preview__footer-space" />
</ view >
</ KeyboardAvoidingScrollView >
</ page >
);
}
root. render (< Root />);
이 예제는 네이티브 키보드 동작을 사용합니다. QR 코드 탭에서 Lynx Explorer로 실행한 뒤 화면 아래의 주소 입력 영역을 탭해 확인해 주세요.
TextField.Textarea에 여러 줄을 입력해 높이가 달라지면 활성 입력 영역의 위치를 다시 계산합니다.
import "./styles" ;
import { root } from "@lynx-js/react" ;
import { KeyboardAvoidingScrollView, useSeedClassName } from "@seed-design/lynx-react" ;
import { TextField, TextFieldTextarea } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< KeyboardAvoidingScrollView
className = "keyboard-avoiding-scroll-view-preview"
keyboardGap = { 24 }
scrollBehavior = "smooth"
>
< view className = "keyboard-avoiding-scroll-view-preview__content" >
< text className = "keyboard-avoiding-scroll-view-preview__title" >여러 줄 입력</ text >
< text className = "keyboard-avoiding-scroll-view-preview__description" >
줄을 추가해 입력 영역이 커져도 키보드 위의 안전한 위치를 다시 계산합니다.
</ text >
< view className = "keyboard-avoiding-scroll-view-preview__spacer" >
< text className = "keyboard-avoiding-scroll-view-preview__spacer-label" >
입력 영역이 화면 아래에 오도록 확보한 공간
</ text >
</ view >
< view className = "keyboard-avoiding-scroll-view-preview__field" >
< TextField label = "자기소개" >
< TextFieldTextarea
accessibility-label = "자기소개"
android-set-soft-input-mode = "nothing"
maxlength = { 300 }
placeholder = "여러 줄을 입력해 보세요"
/>
</ TextField >
</ view >
< view className = "keyboard-avoiding-scroll-view-preview__footer-space" />
</ view >
</ KeyboardAvoidingScrollView >
</ page >
);
}
root. render (< Root />);
이 예제는 네이티브 입력 요소의 자동 높이 조절과 키보드 회피 동작을 사용합니다. QR 코드 탭에서 Lynx Explorer로 실행한 뒤 여러 줄을 입력해 확인해 주세요.
브라우저의 visualViewport나 CSS viewport unit 대신 Lynx keyboard global event와 native node 측정을 사용합니다.
키보드가 열릴 때 필요한 하단 spacer만 추가하고, 사용자 스크롤 중에는 자동 이동을 잠시 중단합니다.
브라우저의 form 제출과 자동 focus 이동은 제공하지 않습니다.
가로·중첩 scroll view는 지원하지 않습니다.
키보드 toolbar 높이와 큰 textarea의 caret 단위 회피는 아직 반영하지 않습니다.