본문으로 건너뛰기
Dot Design System
v0.3.1

Sheet

현재 맥락을 유지하며 보조 작업이나 탐색 영역을 엽니다.

목적

Sheet는 현재 화면의 맥락을 보존하면서 가장자리에서 보조 작업 공간을 연다. 관련 대상의 세부 정보, mobile navigation, 비교적 긴 설정처럼 Dialog보다 넓은 흐름이 필요하지만 별도 화면 전환까지는 필요하지 않을 때 사용한다.

선택 기준

  • 현재 목록이나 대상과 연결된 상세·편집을 옆에서 처리할 때 사용한다.
  • 작은 화면의 navigation이나 action list를 임시로 펼칠 때 사용한다.
  • 짧은 확인과 한두 field는 Dialog, 간단한 맥락 정보는 Popover를 사용한다.
  • 여러 단계이거나 URL과 복원 가능한 독립 작업이 필요하면 별도 화면으로 분리한다.

구조

Sheet 아래에 SheetTriggerSheetContent를 둔다. Content는 theme 경계 안의 portal, overlay, 기본 close control을 함께 만든다. 내부에 SheetHeader, SheetTitle, SheetDescription, 본문, SheetFooter 순으로 구성한다. 별도 닫기 control에는 SheetClose를 사용한다.

변형과 크기

SheetContentsidetop, bottom, left, right를 지원하며 기본값은 right다. Left와 right는 기본 너비가 viewport의 75%이고 sm 이상에서 최대 24rem이다. Top과 bottom은 내용과 제품 className이 높이를 결정한다.

열릴 때 500ms, 닫힐 때 300ms의 방향 motion이 적용되며 DotTheme의 motion 감소 설정에서는 최소화된다.

상태와 동작

Sheetopen, defaultOpen, onOpenChange로 제어·비제어 상태를 지원한다. 열린 동안 배경은 overlay로 구분되고 focus는 Sheet 안에서 관리된다. 닫으면 Trigger가 있던 작업 맥락으로 돌아간다.

저장하지 않은 변경이 있다면 close 동작에서 손실 여부를 확인한다. 비동기 처리 중에는 주 행동을 비활성화하고 현재 대상과 진행 상태를 유지한다.

콘텐츠

Title은 학습자 세부 정보, 필터 설정처럼 열린 panel의 목적을 설명한다. Description에는 원래 화면과의 관계나 변경 영향을 쓴다. Sheet 안에서 또 다른 전역 navigation을 만들지 않는다.

접근성

SheetTitleSheetDescription을 제공한다. 기본 close control에는 접근 가능한 이름이 포함되어 있다. side와 animation에 관계없이 keyboard 순서가 DOM 순서를 따라야 한다. 저장되지 않은 상태를 색만으로 표시하지 않는다.

좁은 화면과 긴 콘텐츠

Left와 right Sheet는 좁은 화면에서도 75% 너비를 사용하므로 핵심 content가 지나치게 좁아지지 않는지 확인한다. full-screen에 가까운 복잡한 작업은 별도 화면이 낫다. 긴 본문은 header와 footer의 역할을 유지한 채 명시적인 scroll 영역을 구성한다.

공개 API

  • Sheet, SheetTrigger, SheetClose: root와 control
  • SheetContent: SheetContentProps, side="top" | "bottom" | "left" | "right"; 기본 right
  • SheetOverlay, SheetPortal: layer 구성
  • SheetHeader, SheetFooter, SheetTitle, SheetDescription: 내부 구조

예제

사용 코드 · TSX
import {
  Button,
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from '@classum/dot-design-system/ui';

export function FilterSheet() {
  return (
    <Sheet>
      <SheetTrigger asChild>
        <Button variant="outline">필터 열기</Button>
      </SheetTrigger>
      <SheetContent side="right">
        <SheetHeader>
          <SheetTitle>커리큘럼 필터</SheetTitle>
          <SheetDescription>현재 목록에 적용할 상태와 담당자를 선택해요.</SheetDescription>
        </SheetHeader>
        <div className="py-6">필터 control</div>
        <SheetFooter>
          <SheetClose asChild>
            <Button>필터 적용</Button>
          </SheetClose>
        </SheetFooter>
      </SheetContent>
    </Sheet>
  );
}

피해야 할 사용

  • 별도 URL이 필요한 긴 작업을 Sheet에 가두지 않는다.
  • Title과 Description 없이 panel을 열지 않는다.
  • Sheet 안에 Sheet나 Dialog를 연속 중첩하지 않는다.
  • 닫을 때 변경이 사라지는데 아무 경고도 제공하지 않는다.
  • 일반 표면에 캐릭터나 gradient를 장식으로 추가하지 않는다.

관련 항목