Next UI Components Guide
Project Information

BottomSheet

BottomSheet와 useBottomSheet usage를 기준으로 하단 시트 구조와 컴포넌트 등록형 popup 흐름을 정리한 가이드 페이지입니다.

BottomSheet

BottomSheet

BottomSheet는 PopupBase를 기반으로 한 하단 시트형 팝업입니다. 필터, 짧은 선택지, 빠른 액션처럼 현재 화면을 유지한 채 즉시 반응해야 하는 흐름을 정리합니다.

Prop

title | children | footer | hasCloseButton | shouldCloseOnBackdrop | shouldCloseOnEscape | className

ReactNode | ReactNode | ReactNode | boolean | boolean | boolean | string

- BottomSheet는 `PopupBase`의 shell을 유지한 채 variant만 하단 시트로 고정한 팝업입니다.
- hook에서는 `component`만 등록하고, 필터 목록이나 선택지처럼 실제 콘텐츠 데이터는 각 BottomSheet 컴포넌트 내부에서 직접 구성합니다.
- backdrop 닫힘과 close button 노출 여부도 개별 시트 컴포넌트 안의 `BottomSheet`에 바로 선언합니다.

Prop

PopupBase shell / design props

title | icon | description | children | footer | className | panelClassName | bodyClassName | footerClassName | contentAlign | hasCloseButton | closeButtonLabel | shouldCloseOnBackdrop | shouldCloseOnEscape | dialogLabel | onClickClose

- BottomSheet은 `PopupBase` shell을 감싼 wrapper이므로, custom popup 컴포넌트 안에서 `title`, `footer`, `contentAlign`, `panelClassName` 같은 shell props를 직접 설정할 수 있습니다. `size`는 LayerPopup 전용입니다.
- 반대로 `id`, `open`, `onRequestClose`, `onExited`는 디자인 props가 아니라 `PopupHost`가 runtime에 주입하는 인스턴스 제어용 props입니다.
- 그래서 보통 custom popup 컴포넌트에서는 `...runtimeProps`를 펼친 뒤, 필요한 shell props만 추가 선언하는 패턴을 사용합니다.

function ExamplePopup(runtimeProps: BottomSheetComponentProps) {
  return (
    <BottomSheet
      {...runtimeProps}
      title="팝업 제목"
      description="PopupBase shell props를 직접 제어하는 예시"

      contentAlign="left"
      panelClassName="customPanel"
      bodyClassName="customBody"
      footerClassName="customFooter"
      hasCloseButton
      closeButtonLabel="닫기"
      shouldCloseOnBackdrop={false}
      shouldCloseOnEscape={true}
      dialogLabel="상세 설정 팝업"
      onClickClose={() => {
        console.log("close button clicked");
      }}
      footer={<button onClick={runtimeProps.onRequestClose}>닫기</button>}
    >
      <div>custom contents</div>
    </BottomSheet>
  );
}
Shell prop groups
  • Header / content: `title`, `icon`, `description`, `children`, `footer`
  • Layout / style: `contentAlign`, `className`, `panelClassName`, `bodyClassName`, `footerClassName`
  • Close / accessibility: `hasCloseButton`, `closeButtonLabel`, `shouldCloseOnBackdrop`, `shouldCloseOnEscape`, `dialogLabel`, `onClickClose`
  • Runtime from host: `id`, `open`, `onRequestClose`, `onExited`
Prop

component | id

React.ComponentType<BottomSheetComponentProps> | string | undefined

- BottomSheet도 LayerPopup과 동일하게 `component` 자체를 등록하는 구조입니다.
- hook 호출부에서는 어떤 시트를 띄울지만 결정하고, 시트 안의 제목, 설명, 리스트, 버튼은 해당 popup 컴포넌트가 직접 가집니다.

bottomSheet.open({
  id: "delivery-slot-bottom-sheet",
  component: DeliverySlotBottomSheet,
});
Prop

useBottomSheet()

{ open: (options) => string; close: (id?: string) => void; closeAll: () => void; bottomSheets: Array<{ id: string; type: "bottomSheet"; status: "open" | "closing" }>; }

- `useBottomSheet()`은 등록형 BottomSheet를 전역 store로 열고 닫는 훅입니다.
- `close(id?)`는 특정 시트 또는 가장 마지막 시트를 닫고, `closeAll()`은 현재 열린 BottomSheet 타입만 한 번에 닫습니다.
- 여러 개를 연 상태에서는 마지막 시트부터 정리되므로 모바일 흐름을 단계적으로 되돌릴 때도 같은 메서드를 그대로 사용할 수 있습니다.

Prop

usePopupStack()

Array<{ id: string; type: "alert" | "confirm" | "layerPopup" | "bottomSheet" | "fullPopup"; status: "open" | "closing" }>

전역 popup stack을 그대로 조회할 수 있어서 BottomSheet가 다른 popup과 섞여 떠 있는 상태도 한 번에 확인할 수 있습니다.

Active popup stack

열린 팝업이 없습니다.


Props Table

BottomSheet props 한눈에 보기

BottomSheet shell에서 직접 제어하는 디자인 props와 PopupHost가 주입하는 runtime props를 함께 정리했습니다.

PropTypeDefaultRequiredDescription
title | description | children | footerReact.ReactNodeundefinedOptional하단 시트 흐름에서 필요한 헤더, 본문, 하단 액션 영역을 조합합니다.
iconReact.ReactNode | nullundefinedOptionaldescription 위에 아이콘 영역을 추가합니다. null이면 아이콘 슬롯을 비웁니다.
contentAlign"left" | "center""left"Optional본문 텍스트와 footer 정렬 기준을 제어합니다.
hasCloseButton | closeButtonLabelboolean | stringtrue | "팝업 닫기"Optional상단 닫기 버튼 노출 여부와 접근성 라벨을 제어합니다.
shouldCloseOnBackdrop | shouldCloseOnEscapebooleantrue | trueOptionalbackdrop 클릭과 Escape 키로 닫힐지 제어합니다. topmost popup에만 Escape가 반응합니다.
dialogLabelstring"바텀시트 팝업"Optionaltitle이 없을 때 dialog aria-label fallback으로 사용합니다.
className | panelClassName | bodyClassName | footerClassNamestringundefinedOptional루트, 패널, body, footer wrapper 각각에 커스텀 클래스를 추가합니다.
onClickClose() => voidundefinedOptional닫기 버튼 클릭 시 onRequestClose 직전에 부가 동작을 실행합니다.
id | open | onRequestClose | onExited | isTopmostruntime props from PopupHostinjectedOptional커스텀 bottom sheet 컴포넌트에서는 보통 `...runtimeProps`로 받고, PopupHost가 lifecycle을 주입합니다.
BottomSheetPopupBase의 bottomSheet variant wrapper입니다. 모바일/빠른 선택 흐름을 전제로 하므로 size는 외부에서 받지 않습니다.

Props Table

useBottomSheet API 한눈에 보기

BottomSheet 등록과 stack 제어에 사용하는 hook API를 표로 정리했습니다.

PropTypeDefaultRequiredDescription
open(options: BottomSheetOptions) => string-Required새 BottomSheet 인스턴스를 stack에 추가하고 생성된 id를 반환합니다.
open.options.componentReact.ComponentType<BottomSheetComponentProps>-RequiredPopupHost가 렌더링할 custom BottomSheet 컴포넌트입니다. runtime props를 받아야 합니다.
open.options.idstringauto generated idOptional특정 인스턴스를 직접 추적하거나 close(id) 대상으로 삼고 싶을 때 사용합니다.
close(id?: string) => void-Requiredid를 주면 해당 BottomSheet를 닫고, 생략하면 현재 타입 stack의 마지막 popup을 닫습니다.
closeAll() => void-Required현재 열린 BottomSheet 타입 인스턴스만 모두 closing 상태로 전환합니다.
bottomSheetsArray<{ id: string; type: "bottomSheet"; status: "open" | "closing" }>-Required전역 popup stack 중 BottomSheet 항목만 필터링한 snapshot 배열입니다.
useBottomSheet()도 store action을 감싼 얇은 wrapper입니다. 실제 shell props와 콘텐츠는 등록한 component 안에서 선언합니다.