Bottom Sheet 화면 하단에서 올라오는 시트 컴포넌트로, 드래그·snap·dismiss 상호작용을 제공합니다.
npx @seed-design/cli add ui:bottom-sheet pnpm dlx @seed-design/cli add ui:bottom-sheet yarn dlx @seed-design/cli add ui:bottom-sheet bun x @seed-design/cli add ui:bottom-sheet
의존성 설치
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:bottom-sheet
* @requires @seed-design/lynx-react@>=0.1.0 <1.0.0
* @requires @seed-design/lynx-css@>=0.1.0 <1.0.0
**/
import {
BottomSheet as SeedBottomSheet,
type BottomSheetBodyProps as SeedBottomSheetBodyProps,
type BottomSheetContentProps as SeedBottomSheetContentProps,
type BottomSheetFooterProps as SeedBottomSheetFooterProps,
type BottomSheetRootProps as SeedBottomSheetRootProps,
type BottomSheetRootRef as SeedBottomSheetRootRef,
type BottomSheetTriggerProps as SeedBottomSheetTriggerProps,
} from "@seed-design/lynx-react" ;
import {
forwardRef,
type ForwardRefExoticComponent,
type PropsWithoutRef,
type ReactNode,
type RefAttributes,
} from "@lynx-js/react" ;
export interface BottomSheetRootProps extends SeedBottomSheetRootProps {}
export type BottomSheetRootRef = SeedBottomSheetRootRef ;
/**
* @see https://seed-design.io/lynx/components/bottom-sheet
*/
export const BottomSheetRoot : ForwardRefExoticComponent <
PropsWithoutRef < BottomSheetRootProps > & RefAttributes < SeedBottomSheetRootRef >
> = forwardRef < SeedBottomSheetRootRef , BottomSheetRootProps >(( props , ref ) => {
return < SeedBottomSheet.Root ref = {ref} { ... props} />;
});
BottomSheetRoot.displayName = "BottomSheetRoot" ;
export interface BottomSheetTriggerProps extends SeedBottomSheetTriggerProps {}
export const BottomSheetTrigger = SeedBottomSheet.Trigger;
export interface BottomSheetContentProps extends Omit < SeedBottomSheetContentProps , "title" > {
title ?: ReactNode ;
description ?: ReactNode ;
/**
* @default false
*/
showHandle ?: boolean ;
}
/**
* Positioner / Backdrop / Handle / Header / Title / Description을 내부에서 조립해
* 사용자가 단일 컴포넌트로 콘텐츠를 구성할 수 있도록 한다.
*
* 웹 BottomSheetContent와 달리 아래는 Lynx에서 미지원:
* - `showCloseButton` (Tier B: SVG 지원 후 추가 예정)
* - `accessibility-label` 기반 VisuallyHidden 제목 fallback (VisuallyHidden 미구현)
*/
export const BottomSheetContent = ( props : BottomSheetContentProps ) => {
const { children , title , description , showHandle = false , ... otherProps } = props;
const shouldRenderHeader = title || description;
return (
< SeedBottomSheet.Positioner >
< SeedBottomSheet.Backdrop />
< SeedBottomSheet.Content { ... otherProps}>
{showHandle && < SeedBottomSheet.Handle />}
{shouldRenderHeader && (
< SeedBottomSheet.Header >
{title && < SeedBottomSheet.Title >{title}</ SeedBottomSheet.Title >}
{description && (
< SeedBottomSheet.Description >{description}</ SeedBottomSheet.Description >
)}
</ SeedBottomSheet.Header >
)}
{children}
</ SeedBottomSheet.Content >
</ SeedBottomSheet.Positioner >
);
};
export interface BottomSheetBodyProps extends SeedBottomSheetBodyProps {}
export const BottomSheetBody : ( props : BottomSheetBodyProps ) => ReactNode = SeedBottomSheet.Body;
export interface BottomSheetFooterProps extends SeedBottomSheetFooterProps {}
export const BottomSheetFooter : ( props : BottomSheetFooterProps ) => ReactNode =
SeedBottomSheet.Footer;
/**
* 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.
*/
@seed-design/lynx-react의 BottomSheet는 @lynx-js/lynx-ui-sheet 를 래핑합니다. 드래그·스프링·snap·presence 로직은 lynx-ui-sheet가 담당하고, SEED는 공개 API와 recipe 슬롯 스타일만 제공합니다. @seed-design/lynx-react를 설치하면 @lynx-js/lynx-ui-sheet도 함께 설치됩니다.
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에 넣으면 세로 스크롤 영역으로 렌더링됩니다. 스크롤 가능한 긴 본문에서는 BottomSheetRoot에 handleOnly를 함께 사용해 시트 드래그를 handle로 제한하고, 본문 위의 세로 제스처는 body 스크롤에 사용하세요.
< BottomSheetRoot handleOnly snapPoints = {[ "80%" ]}>
< BottomSheetTrigger >
< text >긴 본문 열기</ text >
</ BottomSheetTrigger >
< BottomSheetContent title = "제목" showHandle >
< BottomSheetBody >{ /* 긴 본문 */ }</ BottomSheetBody >
</ BottomSheetContent >
</ BottomSheetRoot >
BottomSheetRoot에 ref를 전달하면 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 >
);
}
style?CSSProperties | undefined
children?ReactNode
className?string | undefined
bindtap?EventHandler < BaseTouchEvent < Target >> | undefined
title?ReactNode
description?ReactNode
showHandle?boolean | undefined
style?CSSProperties | undefined
children?ReactNode
className?string | undefined
Lynx BottomSheet는 React BottomSheet와 다음과 같은 차이가 있습니다.
이벤트 핸들링 : onClick 대신 bindtap을 사용합니다.
렌더링 요소 : HTML <div> 대신 네이티브 <view>/<text> 요소를 렌더링합니다.
내부 엔진 : Radix Drawer 대신 @lynx-js/lynx-ui-sheet를 래핑합니다.
항목 웹 Lynx 상태 prop open/defaultOpen/onOpenChange동일 (내부에서 lynx-ui-sheet의 show/defaultShow/onShowChange로 매핑) 마운트 제어 lazyMount, unmountOnExit미지원 — forceMount로 대체BottomSheetPositioner존재 동일 (lynx-ui-sheet의 SheetView 래핑) — 첫 open 전까지 Backdrop/Content 마운트 지연 BottomSheetCloseButton존재 미포함 — Tier B (SVG 지원 후 추가 예정)snapPoints없음 지원 ((number | string)[], 기본값 ["fit"]) BottomSheetTrigger의 asChild지원 미지원 (기본 <view>로만 렌더링)imperative ref API — BottomSheetRootRef.{open, close, snapTo, expand, collapse}
현재 Lynx 플랫폼 제약으로 다음 기능이 지원되지 않습니다.
기능 웹 대응 설명 BottomSheetCloseButtonBottomSheet.CloseButtonX 아이콘 SVG 필요
기능 웹 대응 대체 방법 lazyMountBottomSheet.Root propforceMount={false} (기본값) — 기본적으로 열릴 때만 마운트unmountOnExitBottomSheet.Root propforceMount로 제어 — lynx-ui-sheet의 presence 상태 머신이 자연스럽게 언마운트 처리