# Swipeable Menu Sheet URL: /react/components/swipeable-menu-sheet Source: https://github.com/daangn/seed-design/blob/dev/docs/content/react/components/swipeable-menu-sheet.mdx 사용자의 작업과 관련된 선택지를 제공하는 시트 형태의 컴포넌트입니다. 사용 가능 버전: @seed-design/react@2.0.0, @seed-design/css@2.0.0 ## Preview ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; const SwipeableMenuSheetPreview = () => { return ( Open } /> } /> } /> } /> } tone="critical" /> ); }; export default SwipeableMenuSheetPreview; ``` ## Installation - npm: npx @seed-design/cli@latest add ui:swipeable-menu-sheet - pnpm: pnpm dlx @seed-design/cli@latest add ui:swipeable-menu-sheet - yarn: yarn dlx @seed-design/cli@latest add ui:swipeable-menu-sheet - bun: bun x @seed-design/cli@latest add ui:swipeable-menu-sheet ## Props ### `SwipeableMenuSheetRoot` ### `SwipeableMenuSheetTrigger` ### `SwipeableMenuSheetContent` ### `SwipeableMenuSheetGroup` ### `SwipeableMenuSheetItem` ## Examples ### Trigger ``는 `aria-haspopup="dialog"` 속성을 설정하고, SwipeableMenuSheet의 `open` 상태에 따라 `aria-expanded` 속성을 자동으로 설정합니다. 이 속성은 스크린 리더와 같은 보조 기술에 유용합니다. `MenuSheet`과 달리, swipe-down 제스처로도 시트를 닫을 수 있어요. 시트 상단의 핸들이 드래그 affordance를 제공합니다. `SwipeableMenuSheetContent`의 `showCloseButton` prop으로 보이는 닫기 버튼을 표시할 수 있으며, 기본값(`false`)에서는 스크린 리더 사용자를 위해 시각적으로 숨겨진 닫기 버튼이 렌더링됩니다. ## Preview ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; const SwipeableMenuSheetPreview = () => { return ( Open } /> } /> } /> } /> } tone="critical" /> ); }; export default SwipeableMenuSheetPreview; ``` ### Controlled Trigger 외의 방식으로 SwipeableMenuSheet를 열고 닫을 수 있습니다. 이 경우 `open` prop을 사용하여 SwipeableMenuSheet의 상태를 제어합니다. ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { useState } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, } from "seed-design/ui/swipeable-menu-sheet"; const SwipeableMenuSheetControlled = () => { const [open, setOpen] = useState(false); const scheduleOpen = () => { setTimeout(() => { setOpen(true); }, 1000); }; return ( <> 1초 후 열기 } /> } /> } /> ); }; export default SwipeableMenuSheetControlled; ``` ### With Title `SwipeableMenuSheetContent`의 `title` prop을 사용하여 시트 헤더에 제목을 표시합니다. ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; const SwipeableMenuSheetWithTitle = () => { return ( Open } /> } description="Ut nulla et id dolor labore ullamco irure est id occaecat." /> } description="Ut nulla et id dolor labore ullamco irure est id occaecat." /> } /> } tone="critical" /> ); }; export default SwipeableMenuSheetWithTitle; ``` ### With Title and Description `SwipeableMenuSheetContent`의 `description` prop을 사용하여 제목 아래에 부가 설명을 추가합니다. ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; export default function SwipeableMenuSheetWithTitleAndDescription() { return ( Open } /> } description="Ut nulla et id dolor labore ullamco irure est id occaecat." /> } description="Ut nulla et id dolor labore ullamco irure est id occaecat." /> } /> } tone="critical" /> ); } ``` ### Close Button `SwipeableMenuSheetContent`의 `showCloseButton` prop으로 시트 하단에 보이는 닫기 버튼을 표시합니다. 기본값은 `false`이며, 이때는 스크린 리더 사용자를 위한 시각적으로 숨겨진 닫기 버튼이 렌더링됩니다. ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; const SwipeableMenuSheetWithCloseButton = () => { return ( Open } /> } /> } /> ); }; export default SwipeableMenuSheetWithCloseButton; ``` ### Label Align `SwipeableMenuSheetContent`의 `labelAlign` prop으로 메뉴 항목의 레이블 정렬을 설정합니다. #### `labelAlign="left"` (with `PrefixIcon`) 레이블을 왼쪽 정렬합니다. ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; const SwipeableMenuSheetWithPrefixIcon = () => { return ( Open } /> } /> } /> } /> } tone="critical" /> ); }; export default SwipeableMenuSheetWithPrefixIcon; ``` #### `labelAlign="center"` (without `PrefixIcon`) 레이블을 중앙 정렬합니다. (일반적으로, `prefixIcon` 없는 경우) ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; const SwipeableMenuSheetWithoutPrefixIcon = () => { return ( Open ); }; export default SwipeableMenuSheetWithoutPrefixIcon; ``` #### Overriding `labelAlign` 필요한 경우 `SwipeableMenuSheetContent`에 지정한 `labelAlign`을 `SwipeableMenuSheetGroup` 또는 `SwipeableMenuSheetItem`에 지정한 `labelAlign`으로 덮어쓸 수 있습니다. ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; const SwipeableMenuSheetOverridingLabelAlign = () => { return ( Open ); }; export default SwipeableMenuSheetOverridingLabelAlign; ``` ### `onOpenChange` Details `onOpenChange` 두 번째 인자로 `details`가 제공됩니다. #### `reason` **열릴 때** (`open: true`) - `"trigger"`: `SwipeableMenuSheetTrigger` (`SwipeableMenuSheet.Trigger`)로 열림 **닫힐 때** (`open: false`) - `"closeButton"`: 닫기 버튼(`SwipeableMenuSheet.CloseButton`)이 활성화되어 닫힘 (`showCloseButton`이 `false`인 경우 시각적으로 숨겨진 버튼이며, 주로 스크린 리더 사용자) - `"escapeKeyDown"`: ESC 키 사용 - `"interactOutside"`: 외부 영역 클릭 - `"drag"`: swipe 제스처로 닫힘 ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { HStack, Text, VStack } from "@seed-design/react"; import { useState } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; export default function SwipeableMenuSheetOnOpenChangeReason() { const [open, setOpen] = useState(false); const [openReason, setOpenReason] = useState(null); const [closeReason, setCloseReason] = useState(null); return ( { setOpen(open); (open ? setOpenReason : setCloseReason)(details?.reason ?? null); }} > 열기 } /> } /> } /> 마지막 열림 이유: {openReason ?? "-"} 마지막 닫힘 이유: {closeReason ?? "-"} ); } ``` ### Skip Animation `skipAnimation` prop을 사용하여 SwipeableMenuSheet의 enter/exit 애니메이션을 건너뛸 수 있습니다. ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { SwipeableMenuSheetContent, SwipeableMenuSheetGroup, SwipeableMenuSheetItem, SwipeableMenuSheetRoot, SwipeableMenuSheetTrigger, } from "seed-design/ui/swipeable-menu-sheet"; const SwipeableMenuSheetSkipAnimation = () => { return ( Open } /> } /> } /> ); }; export default SwipeableMenuSheetSkipAnimation; ```