# Sheet > 2026-10-10 추가 수정 요청 기준: 화면 가장자리 모서리는 직각, 안쪽 두 모서리만 기존 --hm-radius-control-md를 임시 재사용. 신규 확정 radius 수치가 아니며 GNB/LNB 모바일 Sheet도 같은 계약. 과거 검증 기록은 당시 결과이며 현재 검증은 [추가 수정 보고서](../guidelines/publisher-additional-review-2026-10-10.md)를 따릅니다. 현재 HM 구현의 기준 문서. 공통 원칙은 `docs/guidelines/프로젝트-지침.md`(§6, §7), Token 구조 원칙은 `테마-토큰-가이드.md`를 따른다. 이 문서는 Sheet 고유의 API·Token·상태·결정만 기록한다. Dialog 문서(`dialog.md`)와 값을 공유하지 않는다. ## 1. 상태 | 항목 | 내용 | |---|---| | 구현 상태 | 구현 완료 (현재 HM 규격) | | 기준일 | 2026-10-02 | | 기반 | shadcn/ui Sheet (Radix `Dialog`) | | 대표 Story | `Components/Overlay/Sheet` → `All` (이름 "Sheet") | | 보류 | 아래 §11 | ## 2. 적용 근거 - **참고 근거**: 외부 ui_viz Reference (ZIP 미포함)의 기존 테스트 규격에는 Sheet가 없다(Dialog 문서가 "side sheet"를 범위 밖으로 둠). 참고할 수치가 없었다. - **현재 HM 규격**: 아래 §3~§4. Dialog에서 검증한 접근성 원칙(Radix modal, `asChild` 처리)은 재사용하고, 면·윤곽·그림자 등 수치는 현재 HM Semantic으로 새로 정했다. `--hm-dialog-*`를 참조하지 않는다. - **구현 방식**: shadcn / Radix Dialog 기반 Sheet 구조와 `side` API 유지, theme CSS로 HM 스타일 연결. - **보류**: §11. ## 3. 기본 규격 (현재 HM 규격) | 항목 | 값 | |---|---| | Surface / 전경 | `--hm-sem-bg-surface` / `--hm-sem-fg-primary` | | Border | 1px `--hm-sem-stroke-input-default`, 페이지를 향한 한 변에만 | | Shadow | `0 0 12px rgb(0 0 0 / .2)` | | Radius | 없음(viewport edge에 붙음) | | left / right | 폭 `min(400px, 100vw − 48px)`, 높이 100% | | top / bottom | 폭 100%, 높이 내용 기준, 최대 `100dvh − 48px` | | Padding | 24px (Header·Footer·Body 좌우) | | Header | padding `24 (24+36) 16 24` (오른쪽은 Close 버튼 자리), Title↔Description gap 8px | | Title | 20 / 28 / 700 | | Description | 14 / 20 / 400, `--hm-sem-fg-secondary` | | Body | 14 / 20 / 400, 좌우 padding 24px, 유일한 scroll 영역 | | Footer | padding `16 24 24`, gap 8px, 오른쪽 정렬(좁은 화면은 세로, shadcn `flex-col-reverse sm:flex-row`) | | Close(X) | shadcn 기본(ghost `icon-sm`, 오른쪽 위 12px, sr-only "Close") | | Overlay / animation | shadcn 기본(`bg-black/10` + blur, side별 slide) | ## 4. 상태 규격 | 상태 | 값 | |---|---| | Closed / Open | Radix `data-state`, 열림 시 modal, 배경 aria-hidden, scroll lock | | Focus | 열릴 때 Radix 기본(첫 tabbable), 닫힐 때 trigger로 복귀 | | Long Content | Header·Footer 고정, Body만 세로 scroll | | Form | 소비 조합(Body 안 Label + Input) | ## 5. API Radix Dialog props 그대로. export: `Sheet`, `SheetTrigger`, `SheetClose`, `SheetPortal`, `SheetOverlay`, `SheetContent`, `SheetHeader`, `SheetBody`, `SheetFooter`, `SheetTitle`, `SheetDescription`. - `SheetContent`: `side` `"top" | "right" | "bottom" | "left"` (기본 `right`, shadcn API 유지), `showCloseButton`(기본 true). 출력 `data-side`. - `SheetBody`(신규): scroll owner. 없어도 동작하지만 이 경우 Body padding과 내부 scroll이 없다. - `SheetClose`: `asChild`일 때 자식의 `data-slot`을 유지(DialogClose와 같은 규칙, Button HM 스타일 보존). - 새 prop(`size`, `variant`)은 만들지 않았다. ## 6. Token Component Mapping 위치: `packages/ui/src/theme/sheet.css` (`--hm-sheet-*`). `background`, `text`, `border-width`, `border-color`, `shadow`, `width`, `edge-gap`, `padding`, `header-gap`, `footer-gap`, `close-clearance`, `title-*`, `description-*`, `body-font-size`, `body-line-height`. Semantic과 Theme palette(`--hm-sem-stroke-input-default`)만 참조한다. 신규 Primitive 없음. ## 7. shadcn / Radix에서 유지한 항목 Radix 구조·ARIA(`role=dialog`, `aria-labelledby/describedby`)·focus trap·initial focus·focus 복귀·Escape·바깥 클릭 닫힘·scroll lock, Portal·Overlay, position(`inset-*`)·side별 slide animation class, `data-slot`, `cn(..., className)`, Close 버튼. ## 8. HM에서 변경한 항목 - shadcn `bg-popover text-popover-foreground shadow-lg gap-4 border-*`, side별 `w-3/4 sm:max-w-sm`·`h-auto`, Header/Footer `p-4` 제거 → theme CSS. - `SheetBody` 추가(scroll owner), `SheetClose asChild` data-slot 처리. - 폭을 `min(400px, 100vw − 48px)`로 지정(좁은 화면에서 Overlay 띠 48px 유지). ## 9. Storybook - 대표 Story `All`("Sheet"): 트리거 6개(right, left, top, bottom, 폼, 긴 내용)가 각각 실제 Sheet를 연다. - verification: `Right`, `Left`, `Top`, `Bottom`, `Form`, `Long Content`(처음부터 열림). ## 10. 사용자 확정 결정 - 2026-10-02: ui-viz는 참고 자료이며 최종 기준은 현재 HM 구현과 이 문서다(작업 지시). 개별 수치에 대한 별도 결정은 없다. ## 11. 미확정 / 보류 - 수치(400px 폭, 24px padding, 그림자, 48px edge gap)는 현재 HM 규격이며 디자인 확정 시 재검토. - Overlay 색·blur, Motion은 정해진 규칙이 없어 shadcn 기본 유지. - Header/Footer divider 없음(미정의). Close 버튼 규격은 shadcn 기본. - top/bottom side 사용처는 Drawer와 겹친다. 둘의 역할 경계(Drawer = 드래그로 닫는 하단 panel)는 사용 가이드로 정리 예정. - 소비 화면이 쓰는 공통 header/footer 높이 대응은 없음. ## 12. 관련 파일 ``` packages/ui/src/components/ui/sheet.tsx packages/ui/src/theme/sheet.css packages/ui/src/theme.css (import) packages/ui/src/index.ts (export) src/components/sheet.stories.tsx ``` ## 13. 검증 상태 - `npm run typecheck`, `npm run build`: 통과(2026-10-02). - 실제 interaction(Browser pane): 클릭 열기(focus가 "취소"로 이동, `role=dialog`), Escape 닫힘과 trigger focus 복귀, 바깥(Overlay) 클릭 닫힘과 focus 복귀, X 닫기, 네 방향 위치(right 우측 400px, left 좌측 0, top/bottom 전체 폭), 긴 내용에서 Body만 scroll하고 Footer가 화면 안. - 390×844: right Sheet 폭 342px(left 82px), 가로 overflow 없음. - computed style: white, border-left `rgb(222,219,210)`, shadow `0 0 12px .2`. - 미확인: focus trap의 Tab 순환(코드 경로는 Radix 기본), side별 닫힘 animation 시각, top/bottom의 모바일 높이 한계.