# 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`일 때 역방향으로 포커스를 순환합니다. |