본문으로 건너뛰기

BottomSheet

화면 하단에서 위로 슬라이드하며 나타나는 모달 인터페이스입니다. 제스처로 드래그하여 닫을 수 있으며, 키보드가 나타나면 자동으로 위치를 조정합니다.

실제 앱에서 확인하세요

웹에서는 시트 열기·닫기와 기본 레이아웃을 확인할 수 있습니다. 네이티브 드래그 감도, 소프트 키보드 회피, SafeArea, Android 하드웨어 뒤로가기와 dismissable 우선순위는 실제 iOS·Android 앱에서 확인하세요.

앱 예제 Playgroundv1.0.3
Interactive exampleBottomSheet 로컬 웹 예제

예제를 선택하면 현재 저장소 소스로 만든 Expo Web 화면을 불러옵니다.

웹 미지원 또는 플랫폼 종속 기능은 실제 iOS·Android 앱에서 확인하세요.

BottomSheetOverlay 렌더러​

BottomSheetOverlay는 OverlayProvider 내부에서 시트 상태, 드래그 제스처, 배경 터치, Android back 처리를 연결하는 렌더러입니다. 앱에서 직접 마운트하면 Provider가 관리하는 닫힘 콜백과 우선순위를 우회하게 되므로 showBottomSheet()로 여세요.

기본 사용법​

import { useOverlay } from '@0610studio/zs-ui';

function MyComponent() {
const { showBottomSheet } = useOverlay();

const handleOpenBottomSheet = () => {
showBottomSheet({
component: <MyBottomSheetContent />,
options: {
height: 300,
padding: 20,
},
});
};

return <Button title="BottomSheet 열기" onPress={handleOpenBottomSheet} />;
}

API 참조​

showBottomSheet 함수​

showBottomSheet(props: ShowBottomSheetProps): void

ShowBottomSheetProps 인터페이스​

PropTypeDefaultDescription
componentReact.ReactNodeRequiredBottom Sheet 내부에 표시할 컴포넌트
headerComponentReact.ReactNodeundefined상단에 표시할 헤더 컴포넌트
optionsBottomSheetOptions{}Bottom Sheet 옵션

BottomSheetOptions 인터페이스​

PropTypeDefaultDescription
dismissablebooleantrue배경 터치·아래로 끌기 제스처로 닫을 수 있는지 여부. false여도 hideOverlay('bottomSheet') 호출로는 닫힙니다
onClose() => voidundefined시트가 어떤 경로(버튼·배경 터치·드래그·뒤로가기)로 닫히든 정확히 1회 호출되는 콜백
isBackgroundTouchClosebooleantrueDeprecated — dismissable을 사용하세요. dismissable 미지정 시에만 참조되며, 이제 배경 터치뿐 아니라 제스처 닫힘까지 함께 제어합니다
marginHorizontalnumber10시트의 좌우 여백
marginBottomnumber10시트의 하단 여백
heightnumber | 'auto'300시트의 높이 ('auto' 지정 시 컨텐츠 크기에 맞춤)
maxHeightnumber화면 높이시트의 최대 높이 제한
paddingnumber14시트 내부 패딩
foldableSingleScreenbooleanfalse폴더블 디바이스에서 단일 화면 모드 사용 여부
type'floating' | 'fixed''floating'시트 타입 (floating: 떠있는 형태, fixed: 화면 하단에 고정)

특징​

  • 제스처 지원: 드래그하여 닫을 수 있습니다
  • 키보드 대응: 키보드가 나타나면 자동으로 위치를 조정합니다
  • 애니메이션: 부드러운 스프링 애니메이션이 적용됩니다
  • 폴더블 디바이스 지원: 폴더블 디바이스에서도 올바르게 동작합니다

예제​

기본 사용​

import { useOverlay, ZSText, ZSPressable } from '@0610studio/zs-ui';
import { View } from 'react-native';

function MyBottomSheetContent() {
const { hideOverlay } = useOverlay();

return (
<View>
<ZSText typo="heading.2">제목</ZSText>
<ZSText typo="body.2">내용</ZSText>
<ZSPressable onPress={() => hideOverlay('bottomSheet')}>
<ZSText typo="body.2">닫기</ZSText>
</ZSPressable>
</View>
);
}

function MyComponent() {
const { showBottomSheet } = useOverlay();

const handleOpenBottomSheet = () => {
showBottomSheet({
component: <MyBottomSheetContent />,
options: {
height: 300,
},
});
};

return <Button title="BottomSheet 열기" onPress={handleOpenBottomSheet} />;
}

헤더 컴포넌트 사용​

import { useOverlay, ZSText } from '@0610studio/zs-ui';
import { View } from 'react-native';

function MyComponent() {
const { showBottomSheet } = useOverlay();

const handleOpenBottomSheet = () => {
showBottomSheet({
headerComponent: (
<View style={{ padding: 20 }}>
<ZSText typo="heading.2">헤더</ZSText>
</View>
),
component: <MyBottomSheetContent />,
options: {
height: 400,
},
});
};

return <Button title="BottomSheet 열기" onPress={handleOpenBottomSheet} />;
}

Fixed 타입 (화면 하단 고정)​

import { useOverlay } from '@0610studio/zs-ui';

function MyComponent() {
const { showBottomSheet } = useOverlay();

const handleOpenBottomSheet = () => {
showBottomSheet({
component: <MyBottomSheetContent />,
options: {
height: 500,
type: 'fixed',
padding: 20,
},
});
};

return <Button title="BottomSheet 열기" onPress={handleOpenBottomSheet} />;
}

커스텀 여백​

import { useOverlay } from '@0610studio/zs-ui';

function MyComponent() {
const { showBottomSheet } = useOverlay();

const handleOpenBottomSheet = () => {
showBottomSheet({
component: <MyBottomSheetContent />,
options: {
height: 400,
marginHorizontal: 20,
marginBottom: 30,
padding: 30,
},
});
};

return <Button title="BottomSheet 열기" onPress={handleOpenBottomSheet} />;
}

배경 터치·제스처로 닫기 비활성화​

dismissable: false를 지정하면 배경 터치와 아래로 끌기 제스처 모두 무시됩니다. 사용자가 반드시 시트 내부 동작(버튼 등)으로만 닫아야 할 때 사용하세요.

import { useOverlay } from '@0610studio/zs-ui';

function MyComponent() {
const { showBottomSheet } = useOverlay();

const handleOpenBottomSheet = () => {
showBottomSheet({
component: <MyBottomSheetContent />,
options: {
height: 300,
dismissable: false,
},
});
};

return <Button title="BottomSheet 열기" onPress={handleOpenBottomSheet} />;
}

BottomSheet 닫기​

import { useOverlay, ZSPressable, ZSText } from '@0610studio/zs-ui';
import { View } from 'react-native';

function MyBottomSheetContent() {
const { hideOverlay } = useOverlay();

return (
<View>
<ZSPressable onPress={() => hideOverlay('bottomSheet')}>
<ZSText typo="body.2">닫기</ZSText>
</ZSPressable>
</View>
);
}