# Side Panel URL: /react/components/side-panel Source: https://github.com/daangn/seed-design/blob/dev/docs/content/react/components/side-panel.mdx 화면 좌측 또는 우측 가장자리에서 슬라이드하여 나타나는 패널 컴포넌트입니다. 데스크탑 환경에서 추가 콘텐츠나 네비게이션을 제공할 때 사용됩니다. 사용 가능 버전: @seed-design/react@2.0.0, @seed-design/css@2.0.0 ## Preview ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelFooter, SidePanelRoot, SidePanelTrigger, } from "seed-design/ui/side-panel"; const SidePanelPreview = () => { return ( Open Side Panel 패널 본문에는 사용자가 확인해야 할 내용이나 추가 입력 폼을 배치할 수 있습니다. 확인 ); }; export default SidePanelPreview; ``` ## Installation ### Default 좌/우 가장자리에서 슬라이드되는 기본 Side Panel 컴포넌트를 포함합니다. - npm: npx @seed-design/cli@latest add ui:side-panel - pnpm: pnpm dlx @seed-design/cli@latest add ui:side-panel - yarn: yarn dlx @seed-design/cli@latest add ui:side-panel - bun: bun x @seed-design/cli@latest add ui:side-panel ### Responsive 뷰포트에 따라 Bottom Sheet로 자동 전환되는 반응형 변형입니다. dependency로 `ui:bottom-sheet`와 `ui:side-panel`이 함께 설치됩니다. - npm: npx @seed-design/cli@latest add ui:responsive-side-panel - pnpm: pnpm dlx @seed-design/cli@latest add ui:responsive-side-panel - yarn: yarn dlx @seed-design/cli@latest add ui:responsive-side-panel - bun: bun x @seed-design/cli@latest add ui:responsive-side-panel ## Props ### `SidePanelRoot` ### `SidePanelTrigger` ### `SidePanelContent` ### `SidePanelBody` ### `SidePanelFooter` ### `ResponsiveSidePanelRoot` ## Examples ### Trigger ``는 `asChild` 패턴을 사용해 자식 요소가 Side Panel을 열 수 있도록 합니다. ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelRoot, SidePanelTrigger, } from "seed-design/ui/side-panel"; const SidePanelTriggerExample = () => { return ( Open Trigger를 클릭하면 현재 화면 위에 Side Panel이 열립니다. ); }; export default SidePanelTriggerExample; ``` ### Controlled Trigger 외의 방식으로 Side Panel을 열고 닫을 수 있습니다. 이 경우 `open` prop을 사용하여 Side Panel의 상태를 제어합니다. ```tsx import { useState } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelFooter, SidePanelRoot, } from "seed-design/ui/side-panel"; const SidePanelControlled = () => { const [open, setOpen] = useState(false); const scheduleOpen = () => { setTimeout(() => { setOpen(true); }, 1000); }; return ( <> 1초 후 열기 외부 상태로 패널을 열고 닫을 때도 본문과 푸터 구조는 동일하게 유지됩니다. 확인 ); }; export default SidePanelControlled; ``` ### Direction ``에 `direction` prop을 설정하여 Side Panel이 열리는 방향을 변경할 수 있습니다. `"left"` 또는 `"right"`를 지원하며, 기본값은 `"right"`입니다. ```tsx import { Flex } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelRoot, SidePanelTrigger, } from "seed-design/ui/side-panel"; const SidePanelDirection = () => { return ( Right 오른쪽 가장자리에서 슬라이드되어 보조 콘텐츠를 표시합니다. Left 왼쪽 가장자리에서 슬라이드되어 탐색이나 설정 영역을 표시합니다. ); }; export default SidePanelDirection; ``` ### Size ``에 `size` prop을 설정하여 Side Panel의 너비를 변경할 수 있습니다. `"small"` (480px), `"medium"` (720px, 기본값), `"large"` (960px)를 지원합니다. ```tsx import { Flex } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelRoot, SidePanelTrigger, } from "seed-design/ui/side-panel"; const SidePanelSize = () => { return ( Small (480px) 좁은 패널에 적합한 간결한 콘텐츠를 배치합니다. Medium (720px) 기본 너비로 상세 정보와 주요 액션을 함께 제공합니다. Large (960px) 넓은 패널에서 더 많은 폼 필드나 상세 콘텐츠를 다룹니다. ); }; export default SidePanelSize; ``` ### Footer Layout `SidePanelFooter`는 flex 레이아웃만 제공하며, 버튼 배치는 `VStack`, `HStack` 등으로 직접 구성합니다. 좁은 패널에서는 `VStack`으로 세로로 쌓고, 넓은 패널에서는 `HStack`으로 가로로 정렬할 수 있습니다. ```tsx import { Box, Flex, HStack, VStack } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelFooter, SidePanelRoot, SidePanelTrigger, } from "seed-design/ui/side-panel"; const SidePanelFooterLayout = () => { return ( Small 확인이 필요한 정보를 간결하게 보여줍니다. 버튼은 패널 너비를 채우며 위에서 아래로 쌓입니다. 확인 취소 Medium 상세 정보와 확인 액션을 함께 제공할 수 있습니다. 버튼은 우측 영역에 가로로 정렬됩니다. 취소 확인 ); }; export default SidePanelFooterLayout; ``` ### Custom Size ``에 `width`, `maxWidth` prop을 전달하여 너비를 직접 제어할 수 있습니다. 프리셋 size 대신 뷰포트 기반의 유동적인 너비가 필요할 때 사용합니다. ```tsx import { Flex } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelRoot, SidePanelTrigger, } from "seed-design/ui/side-panel"; const SidePanelCustomSize = () => { return ( width 80vw, max 640px 뷰포트 너비에 따라 커지되 최대 640px까지만 확장됩니다. width 400px 고정 너비가 필요한 작업 패널에 사용할 수 있습니다. ); }; export default SidePanelCustomSize; ``` ### Show Close Button ``에 `showCloseButton` prop을 전달하여 닫기 버튼을 표시할 수 있습니다. 기본 값은 `true`입니다. ```tsx import { Flex } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelRoot, SidePanelTrigger, } from "seed-design/ui/side-panel"; const SidePanelShowCloseButton = () => { return ( 닫기 버튼 있음 기본적으로 닫기 버튼이 표시되어 패널을 바로 닫을 수 있습니다. 닫기 버튼 없음 닫기 버튼을 숨길 때는 본문이나 푸터에 닫을 수 있는 액션을 제공하세요. ); }; export default SidePanelShowCloseButton; ``` ### Dismissible `dismissible` prop을 `false`로 설정하면 Escape 키, 외부 클릭으로 닫을 수 없습니다. 의도적으로 Side Panel을 닫을 수 없게 하고 싶을 때 사용합니다. ```tsx import { useState } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelFooter, SidePanelRoot, SidePanelTrigger, } from "seed-design/ui/side-panel"; const SidePanelDismissible = () => { const [open, setOpen] = useState(false); return ( 닫기 불가 Side Panel Escape 키, 외부 클릭으로 닫을 수 없습니다. 프로그래밍 방식으로만 닫을 수 있습니다. setOpen(false)}> 닫기 ); }; export default SidePanelDismissible; ``` ### Non-modal `modal` prop을 `false`로 설정하면 배경과 상호작용이 가능합니다. Backdrop이 표시되지 않으며, 포커스 트랩이 비활성화됩니다. Trigger를 다시 눌러 닫아야 하는 경우에는 `open` prop으로 상태를 직접 제어합니다. ```tsx import type { MouseEvent } from "react"; import { useState } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { SidePanelBody, SidePanelContent, SidePanelRoot, SidePanelTrigger, } from "seed-design/ui/side-panel"; const SidePanelNonModal = () => { const [open, setOpen] = useState(false); return ( { event.preventDefault(); setOpen((open) => !open); }} > Non-modal Side Panel 배경과 상호작용이 가능합니다. Backdrop이 표시되지 않습니다. ); }; export default SidePanelNonModal; ``` ### Responsive `ResponsiveSidePanel`을 사용하면 md 이상에서는 Side Panel, sm 이하에서는 Bottom Sheet로 자동 전환됩니다. 뷰포트를 줄여서 전환 동작을 확인해보세요. `onOpenChange`는 열림 상태만 전달하며, Side Panel 또는 Bottom Sheet에만 적용되는 Root 옵션은 `sidePanelRootProps`, `bottomSheetRootProps`로 전달합니다. ```tsx import { Box, VStack } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { ResponsiveSidePanelBody, ResponsiveSidePanelContent, ResponsiveSidePanelFooter, ResponsiveSidePanelRoot, ResponsiveSidePanelTrigger, } from "seed-design/ui/responsive-side-panel"; const SidePanelResponsive = () => { return ( Open 본문 영역은 Header/Body/Footer 구조로 동일합니다. md 이상에서는 화면 우측에서 슬라이드되는 Side Panel로, sm 이하에서는 화면 하단에서 슬라이드되는 Bottom Sheet로 표시됩니다. 확인 ); }; export default SidePanelResponsive; ``` ## Keyboard Interactions | Key | Behavior | | ------------- | ------------------------------------------------- | | `Escape` | `dismissible=true`일 때 Side Panel을 닫습니다. | | `Tab` | `modal=true`일 때 Side Panel 내부 요소들 사이로 포커스를 순환합니다. | | `Shift + Tab` | `modal=true`일 때 역방향으로 포커스를 순환합니다. |