SideSheet
BottomSheet의 적응형 확장 짝 — 좁은 화면은 하단 시트, 넓은 화면은 측면 패널로 자동 전환합니다. 두 표면을 합성한 ADR-012 Track C 컴포넌트입니다.
마지막 업데이트 2026-06-12
한눈에#
같은 콘텐츠를 뷰포트 폭에 따라 하단 시트 ↔ 측면 패널로 자동 전환하는 적응형 래퍼입니다 — BottomSheet와 Drawer를 합성합니다.
- 적응형: 시트 ↔ 측면
- compact → BottomSheet
- expanded → 측면 패널
- 동작 계약 일관
같은 콘텐츠를 뷰포트 폭에 따라 두 표면으로 갈아끼우는 얇은 적응형 래퍼입니다 — compact(< 600px)면 BottomSheet, 그 이상이면 측면 패널 (Drawer 어휘)로 렌더합니다. 다이얼로그·포커스 트랩·Escape·배경 클릭 닫기·스크롤 잠금은 두 표면이 그대로 책임지므로 동작 계약이 일관됩니다.
트리거를 눌러 직접 확인하세요(창 폭을 바꿔 표면 전환도):
사용 시점#
같은 콘텐츠를 폭에 따라 시트↔측면으로 자동 전환하면 SideSheet — 한 표면으로 고정하려면 다른 컴포넌트입니다.
권장 — 이렇게 쓰세요
지양 — 이러지 마세요
쓴다 — 모바일·데스크톱을 한 컴포넌트로 — 좁으면 하단 시트, 넓으면 측면 패널로 자동 전환
대신 BottomSheet — 뷰포트와 무관하게 항상 하단 시트로 고정할 때
대신 Drawer — 적응 없이 측면 패널로 고정할 때
플레이그라운드#
컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.
SideSheet를 직접 조작해 보세요
속성·테마·토큰을 바꾸고 React·Flutter 코드를 확인하는 풀스크린 빌더로 엽니다.
플레이그라운드는 넓은 작업 영역이 필요해 웹·태블릿에서 편집할 수 있어요.
변형#
side가 확장(넓은 화면) 표면의 슬라이드 인 방향을 정합니다 — 'right'(기본)·'left'.
compact 뷰포트에서는 항상 하단 시트라 side는 무시됩니다.
크기#
표면이 폭에 따라 갈리므로 별도 size 축은 없습니다 — compact는 하단 시트(상한 85dvh),
expanded는 측면 패널입니다. 강제 전환이 필요하면 responsive로 표면을 고정합니다.
상태#
제어 컴포넌트입니다 — 열림/닫힘은 소비자의 open prop이 결정하고, 닫힘 요청
(Escape·배경·닫기 버튼)은 onClose 콜백으로 전달됩니다. responsive로 적응을
재정의할 수 있습니다 — 'auto'(기본)는 폭에 따라, 'mobile'은 항상 시트, 'desktop'은
항상 측면 패널입니다.
모바일 표면에서는 BottomSheet 규칙이 우선합니다. 표면 공통 class는 className에,
시트 전용 보정은 sheetClassName에, 측면 패널 전용 보정은 drawerClassName에 나눠 넣습니다.
Drawer 전용 border·shadow·폭 보정 class를 className에 섞어 모바일 시트로 전달하지 않습니다.
Props#
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
open | boolean | — | 표시 여부 — 제어 prop |
onClose | () => void | — | Escape·배경·닫기 버튼의 닫힘 요청 콜백 |
title | ReactNode | — | 시트/패널 제목 — 두 표면의 aria-labelledby 대상이라 필수 |
side | 'right' | 'left' | right | expanded(측면 패널) 표면의 슬라이드 인 방향 (기본 right). compact 시트에선 무시 |
footer | ReactNode | — | 하단 액션 영역 (취소/확인 등) |
closeLabel | string | 닫기 | 닫기 버튼 aria-label |
className | string | — | 활성 표면 패널에 전달 — 표면 공통/중립 class만 사용 |
sheetClassName | string | — | compact BottomSheet 표면에만 전달 — 모바일 시트 규칙에 맞는 class만 사용 |
drawerClassName | string | — | expanded Drawer 표면에만 전달 |
responsive | 'auto' | 'mobile' | 'desktop' | auto | 적응형 표시 (기본 'auto') — 'auto': compact→BottomSheet, 그 외→측면 패널. 'mobile': 폭과 무관하게 시트 강제 / 'desktop': 폭과 무관하게 측면 패널 강제. |
ref | Ref<HTMLDivElement> | — | 패널(role=dialog)로 병합 전달되는 ref — 닫힘(미마운트) 동안 null (React 19 ref-as-prop). compact 표면(BottomSheet) 또는 expanded 표면(Drawer) 중 활성 표면의 패널 노드를 가리킨다. |
접근성#
표면 선택만 담당하고 a11y 계약은 합성 대상(BottomSheet/Drawer)이 이행합니다.
| 계약 | 구현 |
|---|---|
| 역할 | role="dialog" + aria-modal="true" (두 표면 공통) |
| 이름 | title이 aria-labelledby로 연결 |
| 포커스 | 열리면 패널로 진입, 트랩(Tab 순환), 닫히면 이전 포커스 복원 |
| 닫기 | Escape · 배경 클릭 · 닫기 버튼 |
| 스크롤 | 열림 동안 배경 body 스크롤 잠금 |
| 적응 SSR | 서버 기본 expanded → mount 후 동기화(hydration mismatch 없음) |
토큰#
자체 토큰 없이 합성 대상의 표면 어휘를 그대로 따릅니다 — BottomSheet·Drawer의 토큰 표를 참고하세요.