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를 래핑합니다. 드래그·스프링·snap·presence 로직은 lynx-ui-sheet가 담당하고, SEED는 공개 API와 recipe 슬롯 스타일만 제공합니다. @seed-design/lynx-react를 설치하면 @lynx-js/lynx-ui-sheet도 함께 설치됩니다.

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>
  );
}

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

본문 콘텐츠가 길어지는 경우 BottomSheetBody에 넣으면 세로 스크롤 영역으로 렌더링됩니다. 스크롤 가능한 긴 본문에서는 BottomSheetRoothandleOnly를 함께 사용해 시트 드래그를 handle로 제한하고, 본문 위의 세로 제스처는 body 스크롤에 사용하세요.

<BottomSheetRoot handleOnly snapPoints={["80%"]}>
  <BottomSheetTrigger>
    <text>긴 본문 열기</text>
  </BottomSheetTrigger>
  <BottomSheetContent title="제목" showHandle>
    <BottomSheetBody>{/* 긴 본문 */}</BottomSheetBody>
  </BottomSheetContent>
</BottomSheetRoot>

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

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

Footer의 버튼, 배경 탭, 아래 방향 드래그로 Bottom Sheet를 닫을 수 있습니다. 예제 위쪽의 상태 값에서 onOpenChange 결과를 확인할 수 있습니다.

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

Controlled

Trigger 외의 방식으로 Bottom Sheet를 열고 닫으려면 openonOpenChange로 상태를 제어합니다. 배경 탭이나 드래그로 닫을 때도 onOpenChange가 호출되므로 전달받은 값을 open에 반영해야 합니다.

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

Snap Points

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

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

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

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

웹 버전과의 차이

Lynx BottomSheet는 React BottomSheet와 다음과 같은 차이가 있습니다.

  • 이벤트 핸들링: onClick 대신 bindtap을 사용합니다.
  • 렌더링 요소: HTML <div> 대신 네이티브 <view>/<text> 요소를 렌더링합니다.
  • 내부 엔진: Radix Drawer 대신 @lynx-js/lynx-ui-sheet를 래핑합니다.
항목Lynx
상태 propopen/defaultOpen/onOpenChange동일 (내부에서 lynx-ui-sheet의 show/defaultShow/onShowChange로 매핑)
onOpenChangedetails.reason지원미지원 — 변경된 open 값만 전달
마운트 제어lazyMount, unmountOnExit미지원forceMount로 대체
BottomSheetPositioner존재동일 (lynx-ui-sheet의 SheetView 래핑) — 첫 open 전까지 Backdrop/Content 마운트 지연
BottomSheetCloseButton존재미포함 — Tier B (SVG 지원 후 추가 예정)
snapPoints지원지원 ((number | string)[], 기본값 ["fit"])
BottomSheetTriggerasChild지원미지원 (기본 <view>로만 렌더링)
imperative ref APIBottomSheetRootRef.{open, close, snapTo, expand, collapse}

Lynx 미지원 기능

현재 Lynx 플랫폼 제약으로 다음 기능이 지원되지 않습니다.

Lynx SVG 지원 후 추가 예정

기능웹 대응설명
BottomSheetCloseButtonBottomSheet.CloseButtonX 아이콘 SVG 필요

마운트 수명주기

기능웹 대응대체 방법
lazyMountBottomSheet.Root propforceMount={false} (기본값) — 기본적으로 열릴 때만 마운트
unmountOnExitBottomSheet.Root propforceMount로 제어 — lynx-ui-sheet의 presence 상태 머신이 자연스럽게 언마운트 처리

Last updated on

목차