Lynx

Bottom Sheet

화면 하단에서 올라오는 시트 컴포넌트로, 드래그·snap·dismiss 상호작용을 제공합니다.

Engine ≥ 3.6<overlay>
사용 가능 버전@seed-design/lynx-react@0.1.0, @seed-design/lynx-css@0.1.0
Lynx 예제를 불러오는 중입니다.

Installation

npx @seed-design/cli add ui:bottom-sheet

@seed-design/lynx-reactBottomSheet@lynx-js/lynx-ui-sheet를 래핑합니다. 드래그, spring, snap, presence 동작은 lynx-ui-sheet가 담당합니다. SEED는 공개 API와 recipe 슬롯 스타일을 제공합니다.

Usage

import {
  BottomSheetBody,
  BottomSheetContent,
  BottomSheetFooter,
  BottomSheetRoot,
  BottomSheetTrigger,
} from "@/components/ui/bottom-sheet";

export function App() {
  return (
    <BottomSheetRoot snapPoints={["fit", "80%"]}>
      <BottomSheetTrigger>
        <text>시트 열기</text>
      </BottomSheetTrigger>
      <BottomSheetContent title="제목" description="부가 설명" showHandle>
        <BottomSheetBody>
          <text>본문 콘텐츠</text>
        </BottomSheetBody>
        <BottomSheetFooter>
          <text>하단 액션 영역</text>
        </BottomSheetFooter>
      </BottomSheetContent>
    </BottomSheetRoot>
  );
}

Registry의 BottomSheetContent는 Positioner, Backdrop, Header를 내부에서 조립합니다. BottomSheetTrigger는 Content 밖에 두어야 탭으로 시트를 열 수 있습니다.

저수준 package API에서 BottomSheet.Positionercontainer를 지정하면 <overlay> XElement를 사용합니다. Registry의 기본 경로는 <view>를 사용합니다. container가 필요하다면 앱의 Lynx Engine이 <overlay>를 지원하는지 확인하세요.

Imperative 제어

BottomSheetRootref를 전달하면 open, close, snapTo, expand, collapse 메서드를 호출할 수 있습니다.

import { useRef } from "@lynx-js/react";
import { BottomSheetRoot, type BottomSheetRootRef } from "@/components/ui/bottom-sheet";

export function App() {
  const ref = useRef<BottomSheetRootRef>(null);

  return (
    <BottomSheetRoot ref={ref} snapPoints={["fit", "80%"]}>
      {/* ... */}
    </BottomSheetRoot>
  );
}

Props

BottomSheetRoot

Prop

Type

BottomSheetTrigger

Prop

Type

style?CSSProperties | undefined
children?ReactNode
className?string | undefined
bindtap?EventHandler<BaseTouchEvent<Target>> | undefined

BottomSheetContent

Prop

Type

title?ReactNode
description?ReactNode

BottomSheetBody

Prop

Type

style?CSSProperties | undefined
children?ReactNode
className?string | undefined

BottomSheetFooter

Prop

Type

style?CSSProperties | undefined
children?ReactNode
className?string | undefined

Examples

Trigger

<BottomSheetTrigger>를 탭하면 Bottom Sheet가 열립니다. Lynx는 asChild를 지원하지 않습니다. Trigger는 자식 요소를 감싸는 <view>를 렌더링합니다.

Lynx 예제를 불러오는 중입니다.

Controlled

Trigger 외의 방식으로 Bottom Sheet를 열고 닫으려면 openonOpenChange로 상태를 제어합니다. 다음 예제는 버튼을 탭한 뒤 1초 후 Bottom Sheet를 엽니다.

Lynx 예제를 불러오는 중입니다.

onOpenChange Details

Lynx의 onOpenChange는 변경된 open 값만 전달합니다. React 버전의 details.reason은 지원하지 않습니다. 열고 닫는 원인이 필요하면 앱이 소유한 버튼과 Trigger의 이벤트 핸들러에서 원인을 별도 상태로 기록하세요. 배경 탭과 드래그는 콜백 값만으로 구분할 수 없습니다.

Header Align

<BottomSheetRoot>headerAlign으로 title과 description을 왼쪽 또는 가운데에 정렬할 수 있습니다.

Lynx 예제를 불러오는 중입니다.

Max Height

BottomSheetBody는 native <view>를 렌더링합니다. 최대 300px인 스크롤 영역을 만들려면 Body 안에 <scroll-view>를 배치하고 height, maxHeight, flex: "none"을 함께 지정하세요. Lynx의 scroll-viewmaxHeight만 지정하면 콘텐츠 크기를 높이로 계산하지 못해 영역이 0px로 축소될 수 있습니다.

Lynx 예제를 불러오는 중입니다.

Snap Points

snapPoints에는 픽셀 숫자, 화면 높이 기준 백분율, 콘텐츠 크기에 맞추는 "fit"을 사용할 수 있습니다. 배열 순서가 snap index가 되며, initialSnap으로 처음 열릴 높이를 정합니다.

onSnapChange에서는 현재 index와 픽셀로 계산된 높이를 받을 수 있습니다. ref의 snapTo 메서드를 사용하면 원하는 높이로 이동할 수 있습니다.

Lynx 예제를 불러오는 중입니다.

드래그와 snap 애니메이션의 최종 동작은 QR 코드 탭에서 Lynx Explorer로 확인하세요. 문서 미리보기에서는 기기와 제스처 처리 결과가 다를 수 있습니다.

Fade From Index

Lynx는 fadeFromIndex를 지원하지 않습니다. Registry가 제공하는 기본 Backdrop을 사용하세요. snap index별 dim 변화가 꼭 필요하면 저수준 package API로 Backdrop을 직접 조립하고 onSnapChange 상태에 따라 투명도를 제어해야 합니다.

Show Handle

<BottomSheetContent>showHandle을 전달하면 Handle을 표시합니다. 기본값은 false입니다.

Lynx 예제를 불러오는 중입니다.

Show Close Button

Lynx의 BottomSheetContentshowCloseButton과 CloseButton을 지원하지 않습니다. 닫기 버튼이 필요하면 controlled 상태를 사용하고 BottomSheetFooter의 버튼에서 openfalse로 바꾸세요.

Dismissible

Lynx에는 배경 탭, 드래그, ESC 닫기를 한 번에 제어하는 dismissible prop이 없습니다. 드래그는 BottomSheetRootenableDragToClose={false}로 막을 수 있습니다. 배경 탭까지 막아야 한다면 저수준 package API로 조립하고 BottomSheet.BackdropclickToClose={false}를 전달하세요. Lynx에는 웹의 ESC 키 닫기 동작이 없습니다. 닫기 동작을 막았다면 Footer 등에 명시적인 닫기 버튼을 제공하세요.

With Scroll Fog

BottomSheetBody는 스크롤 방식을 정하지 않는 native <view>입니다. 스크롤 힌트가 필요하면 Body 안에 ScrollFog를 직접 배치하세요. 이 구조에서는 size, placement, hideScrollBar와 native scroll-view prop을 사용하는 곳에서 직접 제어할 수 있습니다.

네이티브 fading-edge-length는 스크롤할 콘텐츠가 남아 있는 edge에서만 fog를 표시합니다. 처음에는 아래쪽, 끝까지 스크롤하면 위쪽에 표시됩니다.

Lynx 예제를 불러오는 중입니다.

Bottom Inset

Lynx의 BottomSheetContent는 기기의 safeAreaInsetBottom을 내부 padding으로 적용합니다. React 예제처럼 --seed-safe-area-bottom을 직접 전달할 필요가 없습니다.

Handle Only

<BottomSheetRoot>handleOnly를 전달하면 Bottom Sheet를 움직이는 세로 제스처 영역이 Handle로 제한됩니다. 이 옵션은 <BottomSheetContent showHandle>과 함께 사용하세요. 본문이 길 때는 Body 안의 스크롤 영역과 시트 드래그가 겹치지 않도록 이 조합을 권장합니다.

Lynx 예제를 불러오는 중입니다.

Skip Animation

skipAnimation을 전달하면 Bottom Sheet의 enter, exit, snap 애니메이션을 건너뜁니다.

Lynx 예제를 불러오는 중입니다.

웹 버전과의 차이

항목Lynx
사용자 이벤트onClickbindtap
렌더링 요소HTML 요소네이티브 <view>, <text>, <scroll-view>
상태 propopen, defaultOpen, onOpenChange동일. 내부에서 lynx-ui-sheet의 상태 API로 연결
마운트 제어lazyMount, unmountOnExitRegistry에서 미지원. 저수준 BottomSheet.PositionerforceMount로 제어
Trigger 합성asChild 지원미지원. <view> 렌더링
imperative ref API없음open, close, snapTo, expand, collapse

Last updated on

목차