Sheet
모바일은 아래 시트, 데스크탑은 가운데 모달.
import { Sheet } from '@coldsurfers/surf-ui/primitives'import { MediaRow } from '@coldsurfers/surf-ui/cards'import { Button, Sheet } from '@coldsurfers/surf-ui/primitives'import { useRef, useState } from 'react'const TIERS = [ ['VIP석', '189,000원'], ['R석', '164,000원'], ['S석', '134,000원'], ['A석', '104,000원'], ['B석', '79,000원'], ['시야제한석', '59,000원'],]export default function Example() { const [open, setOpen] = useState(false) const triggerRef = useRef<HTMLButtonElement>(null) return ( <> <Button ref={triggerRef} onClick={() => setOpen(true)}> 시트 열기 </Button> <Sheet open={open} onClose={() => setOpen(false)} label="인터스텔라 필름콘서트 고르기" triggerRef={triggerRef} head={ <MediaRow cover="인" kicker="일 10.11 · 14:00" title="인터스텔라 필름콘서트" meta="경희대 평화의전당" /> } footer={ <Button variant="accent" onClick={() => setOpen(false)}> 놀유니버스에서 예매 ↗ </Button> } > <dl> {TIERS.map(([label, value]) => ( <div key={label} style={{ display: 'flex', justifyContent: 'space-between' }}> <dt>{label}</dt> <dd>{value}</dd> </div> ))} </dl> </Sheet> </> )}판매처 · 날짜 · 고르기처럼 지면에 펴기 긴 것을 담습니다(Figma 1028:381). 화면 폭이 1024 아래면 아래에 붙고(위만 r28 · 손잡이 · safe-area), 위면 가운데 모달(최대 560)이 됩니다.
세 칸입니다 — 머리(손잡이 + head) · 내용(children) · 아래(footer). 머리와 아래는 고정이고 내용만 구릅니다. head 에는 「무엇을 고른 건지」 한 줄(보통 MediaRow), footer 에는 늘 보여야 하는 주 행동을 넣습니다. 모바일은 화면 위 56 을 어둡게 남겨 눌러서 닫을 자리를 둡니다.
모바일에선 머리를 잡고 끌어내려 닫습니다 — 80 넘게 내리거나 빠르게 튕기면 닫히고, 아니면 제자리로 돌아갑니다. 머리 안 링크 위에서도 끌립니다 — 6 넘게 내려와야 끌기로 보고, 그 전에 떼면 탭이라 링크로 갑니다. 열 때 올라오고(데스크탑은 떠오르고) 닫을 때 내려갑니다. open 을 false 로 바꿔도 퇴장이 끝날 때까지 마지막 내용을 그린 채로 두니, 소비처가 내용을 같이 비워도 됩니다. 움직임 줄이기 설정에선 애니메이션 없이 바로 열고 닫습니다.
Escape · 스크롤 잠금 · focus trap · portal · 면 모드는 Modal 과 같습니다.
Props
Prop
Type
그 밖의 Omit<ModalProps, 'placement' | 'panelClassName' | 'overlayClassName'> 속성은 루트 엘리먼트로 그대로 통과한다.