# Dropdown

## Introduction

Dropdown 컴포넌트는 메뉴나 옵션 목록을 표시하는 컨테이너 역할을 하는 컴포넌트입니다. Joy UI의 Dropdown을 그대로 사용하며, MenuButton과 Menu 컴포넌트와 함께 사용하여 사용자가 클릭할 때 선택 가능한 옵션들을 보여줍니다. 네비게이션 메뉴, 필터 옵션, 사용자 프로필 메뉴 등 다양한 용도로 활용할 수 있습니다.

```tsx
<Dropdown>
  <MenuButton variant="outlined" endDecorator={<ExpandMoreIcon />}>
    메뉴 열기
  </MenuButton>
  <Menu>
    <MenuItem>옵션 1</MenuItem>
    <MenuItem>옵션 2</MenuItem>
    <MenuItem>옵션 3</MenuItem>
  </Menu>
</Dropdown>
```

| Field                        | Description | Default |
| ---------------------------- | ----------- | ------- |
| Controls resolved at runtime | —           | —       |

## Usage

```tsx
import { Dropdown, MenuButton, Menu, MenuItem } from '@ceed/cds';

function MyComponent() {
  return (
    <Dropdown>
      <MenuButton>메뉴 열기</MenuButton>
      <Menu>
        <MenuItem>옵션 1</MenuItem>
        <MenuItem>옵션 2</MenuItem>
        <MenuItem>옵션 3</MenuItem>
      </Menu>
    </Dropdown>
  );
}
```

## Examples

### Basic Dropdown

가장 기본적인 Dropdown 사용법입니다.

```tsx
<Stack direction="row" spacing={2}>
  <Dropdown>
    <MenuButton>기본 메뉴</MenuButton>
    <Menu>
      <MenuItem>첫 번째 옵션</MenuItem>
      <MenuItem>두 번째 옵션</MenuItem>
      <MenuItem>세 번째 옵션</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton variant="outlined" endDecorator={<ExpandMoreIcon />}>
      아이콘 포함
    </MenuButton>
    <Menu>
      <MenuItem>옵션 A</MenuItem>
      <MenuItem>옵션 B</MenuItem>
      <MenuItem>옵션 C</MenuItem>
    </Menu>
  </Dropdown>
</Stack>
```

### Button Variants

MenuButton의 다양한 스타일 변형을 사용할 수 있습니다.

```tsx
<Stack direction="row" spacing={2} flexWrap="wrap">
  <Dropdown>
    <MenuButton variant="plain">Plain</MenuButton>
    <Menu>
      <MenuItem>옵션 1</MenuItem>
      <MenuItem>옵션 2</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton variant="outlined">Outlined</MenuButton>
    <Menu>
      <MenuItem>옵션 1</MenuItem>
      <MenuItem>옵션 2</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton variant="soft">Soft</MenuButton>
    <Menu>
      <MenuItem>옵션 1</MenuItem>
      <MenuItem>옵션 2</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton variant="solid">Solid</MenuButton>
    <Menu>
      <MenuItem>옵션 1</MenuItem>
      <MenuItem>옵션 2</MenuItem>
    </Menu>
  </Dropdown>
</Stack>
```

### Button Colors

MenuButton에 다양한 색상을 적용할 수 있습니다.

```tsx
<Stack direction="row" spacing={2} flexWrap="wrap">
  <Dropdown>
    <MenuButton color="primary" variant="soft">
      Primary
    </MenuButton>
    <Menu>
      <MenuItem>옵션 1</MenuItem>
      <MenuItem>옵션 2</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton color="neutral" variant="soft">
      Neutral
    </MenuButton>
    <Menu>
      <MenuItem>옵션 1</MenuItem>
      <MenuItem>옵션 2</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton color="danger" variant="soft">
      Danger
    </MenuButton>
    <Menu>
      <MenuItem>옵션 1</MenuItem>
      <MenuItem>옵션 2</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton color="success" variant="soft">
      Success
    </MenuButton>
    <Menu>
      <MenuItem>옵션 1</MenuItem>
      <MenuItem>옵션 2</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton color="warning" variant="soft">
      Warning
    </MenuButton>
    <Menu>
      <MenuItem>옵션 1</MenuItem>
      <MenuItem>옵션 2</MenuItem>
    </Menu>
  </Dropdown>
</Stack>
```

### Menu Placements

메뉴가 나타나는 위치를 설정할 수 있습니다.

```tsx
<Stack direction="row" spacing={2} sx={{
  mt: 4
}}>
<Dropdown>
  <MenuButton variant="outlined">Bottom Start</MenuButton>
  <Menu placement="bottom-start">
    <MenuItem>옵션 1</MenuItem>
    <MenuItem>옵션 2</MenuItem>
    <MenuItem>옵션 3</MenuItem>
  </Menu>
</Dropdown>

<Dropdown>
  <MenuButton variant="outlined">Bottom</MenuButton>
  <Menu placement="bottom">
    <MenuItem>옵션 1</MenuItem>
    <MenuItem>옵션 2</MenuItem>
    <MenuItem>옵션 3</MenuItem>
  </Menu>
</Dropdown>

<Dropdown>
  <MenuButton variant="outlined">Bottom End</MenuButton>
  <Menu placement="bottom-end">
    <MenuItem>옵션 1</MenuItem>
    <MenuItem>옵션 2</MenuItem>
    <MenuItem>옵션 3</MenuItem>
  </Menu>
</Dropdown>

<Dropdown>
  <MenuButton variant="outlined">Top Start</MenuButton>
  <Menu placement="top-start">
    <MenuItem>옵션 1</MenuItem>
    <MenuItem>옵션 2</MenuItem>
    <MenuItem>옵션 3</MenuItem>
  </Menu>
</Dropdown>
</Stack>
```

### With Icons

아이콘이 포함된 메뉴를 만들 수 있습니다.

```tsx
<Dropdown>
  <MenuButton variant="outlined" startDecorator={<PersonIcon />} endDecorator={<ExpandMoreIcon />}>
    사용자 메뉴
  </MenuButton>
  <Menu>
    <MenuItem>
      <PersonIcon sx={{
        mr: 1
      }} />
      프로필 보기
    </MenuItem>
    <MenuItem>
      <SettingsIcon sx={{
        mr: 1
      }} />
      설정
    </MenuItem>
    <ListDivider />
    <MenuItem>
      <LogoutIcon sx={{
        mr: 1
      }} />
      로그아웃
    </MenuItem>
  </Menu>
</Dropdown>
```

### Actions Menu

편집, 삭제 등의 액션 메뉴로 활용할 수 있습니다.

```tsx
<Dropdown>
  <MenuButton variant="plain" color="neutral" endDecorator={<ExpandMoreIcon />} sx={{
    fontSize: 'sm'
  }}>
  작업
</MenuButton>
<Menu>
  <MenuItem>
    <EditIcon sx={{
      mr: 1,
      fontSize: 'sm'
    }} />
    편집
  </MenuItem>
  <MenuItem>
    <DeleteIcon sx={{
      mr: 1,
      fontSize: 'sm',
      color: 'danger.500'
    }} />
    <Typography color="danger">삭제</Typography>
  </MenuItem>
</Menu>
</Dropdown>
```

### Filter Menu

필터링 기능을 위한 드롭다운 메뉴입니다.

```tsx
<Dropdown>
  <MenuButton variant="outlined" startDecorator={<FilterListIcon />} endDecorator={<ExpandMoreIcon />}>
    필터: {selectedFilter}
  </MenuButton>
  <Menu>
    <MenuItem onClick={() => setSelectedFilter('전체')}>전체</MenuItem>
    <MenuItem onClick={() => setSelectedFilter('활성')}>활성</MenuItem>
    <MenuItem onClick={() => setSelectedFilter('비활성')}>비활성</MenuItem>
    <MenuItem onClick={() => setSelectedFilter('대기중')}>대기중</MenuItem>
  </Menu>
</Dropdown>
```

### Profile Dropdown

사용자 프로필 메뉴로 활용할 수 있습니다.

```tsx
<Dropdown>
  <MenuButton variant="plain" color="neutral" startDecorator={<Avatar size="sm" variant="soft" color="primary">
    김
  </Avatar>} endDecorator={<ExpandMoreIcon />} sx={{
  gap: 1,
  padding: 1
}}>
김철수
</MenuButton>
<Menu sx={{
  minWidth: 200
}}>
<Stack px={2} py={1.5} spacing={0.5}>
  <Typography level="title-sm" fontWeight="bold">
    김철수
  </Typography>
  <Typography level="body-xs" color="neutral">
    kim@example.com
  </Typography>
</Stack>

<ListDivider />

<MenuItem>
  <PersonIcon sx={{
    mr: 1
  }} />내 프로필
</MenuItem>
<MenuItem>
  <SettingsIcon sx={{
    mr: 1
  }} />
  계정 설정
</MenuItem>

<ListDivider />

<MenuItem>
  <LogoutIcon sx={{
    mr: 1
  }} />
  로그아웃
</MenuItem>
</Menu>
</Dropdown>
```

### Nested Menus

여러 개의 드롭다운 메뉴를 나란히 배치할 수 있습니다.

```tsx
<Stack direction="row" spacing={3}>
  <Dropdown>
    <MenuButton variant="outlined" endDecorator={<ExpandMoreIcon />}>
      파일
    </MenuButton>
    <Menu>
      <MenuItem>새 파일</MenuItem>
      <MenuItem>열기</MenuItem>
      <MenuItem disabled>최근 파일</MenuItem>
      <ListDivider />
      <MenuItem>저장</MenuItem>
      <MenuItem>다른 이름으로 저장</MenuItem>
      <ListDivider />
      <MenuItem>인쇄</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton variant="outlined" endDecorator={<ExpandMoreIcon />}>
      편집
    </MenuButton>
    <Menu>
      <MenuItem>실행 취소</MenuItem>
      <MenuItem>다시 실행</MenuItem>
      <ListDivider />
      <MenuItem>잘라내기</MenuItem>
      <MenuItem>복사</MenuItem>
      <MenuItem>붙여넣기</MenuItem>
      <ListDivider />
      <MenuItem>모두 선택</MenuItem>
      <MenuItem>찾기</MenuItem>
    </Menu>
  </Dropdown>
</Stack>
```

### Controlled Dropdown

프로그래밍 방식으로 메뉴의 열림/닫힘 상태를 제어할 수 있습니다.

```tsx
<Stack spacing={2}>
  <Typography level="body-sm">메뉴 상태: {open ? '열림' : '닫힘'}</Typography>

  <Dropdown open={open} onOpenChange={(event, isOpen) => setOpen(isOpen)}>
    <MenuButton variant="outlined" endDecorator={<ExpandMoreIcon />}>
      제어된 메뉴
    </MenuButton>
    <Menu>
      <MenuItem onClick={() => setOpen(false)}>옵션 1</MenuItem>
      <MenuItem onClick={() => setOpen(false)}>옵션 2</MenuItem>
      <MenuItem onClick={() => setOpen(false)}>옵션 3</MenuItem>
    </Menu>
  </Dropdown>

  <Button variant="soft" size="sm" onClick={() => setOpen(!open)}>
    {open ? '메뉴 닫기' : '메뉴 열기'}
  </Button>
</Stack>
```

### Disabled State

비활성 상태의 드롭다운과 메뉴 아이템을 표시할 수 있습니다.

```tsx
<Stack direction="row" spacing={2}>
  <Dropdown>
    <MenuButton disabled>비활성 메뉴</MenuButton>
    <Menu>
      <MenuItem>접근 불가</MenuItem>
    </Menu>
  </Dropdown>

  <Dropdown>
    <MenuButton variant="outlined">일부 옵션 비활성</MenuButton>
    <Menu>
      <MenuItem>활성 옵션</MenuItem>
      <MenuItem disabled>비활성 옵션</MenuItem>
      <MenuItem>활성 옵션 2</MenuItem>
    </Menu>
  </Dropdown>
</Stack>
```

### Long Menu

많은 옵션이 있는 메뉴는 스크롤을 적용할 수 있습니다.

```tsx
<Dropdown>
  <MenuButton variant="outlined" endDecorator={<ExpandMoreIcon />}>
    긴 목록 메뉴
  </MenuButton>
  <Menu sx={{
    maxHeight: 300,
    overflow: 'auto'
  }}>
  {Array.from({
    length: 20
  }, (_, index) => <MenuItem key={index}>옵션 {index + 1}</MenuItem>)}
</Menu>
</Dropdown>
```

### Custom Styling

CSS 스타일을 이용해 드롭다운을 커스터마이징할 수 있습니다.

```tsx
<Stack direction="row" spacing={2}>
  <Dropdown>
    <MenuButton variant="soft" color="primary" endDecorator={<ExpandMoreIcon />} sx={{
      borderRadius: 'xl',
      fontWeight: 'bold'
    }}>
    커스텀 버튼
  </MenuButton>
  <Menu sx={{
    borderRadius: 'md',
    boxShadow: 'lg',
    border: '2px solid',
    borderColor: 'primary.200'
  }}>
  <MenuItem sx={{
    borderRadius: 'sm',
    mx: 0.5,
    my: 0.25
  }}>둥근 아이템 1</MenuItem>
  <MenuItem sx={{
    borderRadius: 'sm',
    mx: 0.5,
    my: 0.25
  }}>둥근 아이템 2</MenuItem>
  <MenuItem sx={{
    borderRadius: 'sm',
    mx: 0.5,
    my: 0.25
  }}>둥근 아이템 3</MenuItem>
</Menu>
</Dropdown>

<Dropdown>
  <MenuButton variant="outlined" sx={{
    background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
    border: 0,
    borderRadius: 3,
    color: 'white',
    '&:hover': {
      background: 'linear-gradient(45deg, #FE6B8B 60%, #FF8E53 100%)'
    }
  }}>
  그라데이션 버튼
</MenuButton>
<Menu>
  <MenuItem>스타일링된 메뉴</MenuItem>
  <MenuItem>아이템 2</MenuItem>
</Menu>
</Dropdown>
</Stack>
```

## Component Structure

Dropdown은 다음 컴포넌트들과 함께 사용됩니다:

```tsx
<Dropdown>
  <MenuButton>트리거 버튼</MenuButton>
  <Menu>
    <MenuItem>메뉴 아이템 1</MenuItem>
    <MenuItem>메뉴 아이템 2</MenuItem>
    <ListDivider /> {/* 구분선 */}
    <MenuItem>메뉴 아이템 3</MenuItem>
  </Menu>
</Dropdown>
```

### MenuButton Props

MenuButton 컴포넌트의 주요 props:

- `variant`: `'plain' | 'outlined' | 'soft' | 'solid'`
- `color`: `'primary' | 'neutral' | 'danger' | 'success' | 'warning'`
- `size`: `'sm' | 'md' | 'lg'`
- `startDecorator`: 앞쪽에 표시할 요소
- `endDecorator`: 뒤쪽에 표시할 요소
- `disabled`: 비활성 상태

### Menu Props

Menu 컴포넌트의 주요 props:

- `placement`: `'top-start' | 'top' | 'top-end' | 'bottom-start' | 'bottom' | 'bottom-end'`
- `size`: `'sm' | 'md' | 'lg'`
- `sx`: 스타일 커스터마이징

## Common Use Cases

### Navigation Menu

```tsx
<Dropdown>
  <MenuButton variant="plain">메뉴</MenuButton>
  <Menu>
    <MenuItem component="a" href="/home">
      홈
    </MenuItem>
    <MenuItem component="a" href="/about">
      회사소개
    </MenuItem>
    <MenuItem component="a" href="/products">
      제품
    </MenuItem>
    <ListDivider />
    <MenuItem component="a" href="/contact">
      문의하기
    </MenuItem>
  </Menu>
</Dropdown>
```

### User Profile Menu

```tsx
<Dropdown>
  <MenuButton variant="plain" startDecorator={<Avatar size="sm" />} endDecorator={<ExpandMoreIcon />}>
    사용자명
  </MenuButton>
  <Menu>
    <Stack px={2} py={1}>
      <Typography level="title-sm">사용자명</Typography>
      <Typography level="body-xs" color="neutral">
        user@example.com
      </Typography>
    </Stack>
    <ListDivider />
    <MenuItem>프로필</MenuItem>
    <MenuItem>설정</MenuItem>
    <ListDivider />
    <MenuItem>로그아웃</MenuItem>
  </Menu>
</Dropdown>
```

### Filter Dropdown

```tsx
const [filter, setFilter] = useState('전체');

<Dropdown>
  <MenuButton variant="outlined" startDecorator={<FilterListIcon />} endDecorator={<ExpandMoreIcon />}>
    필터: {filter}
  </MenuButton>
  <Menu>
    <MenuItem onClick={() => setFilter('전체')}>전체</MenuItem>
    <MenuItem onClick={() => setFilter('활성')}>활성</MenuItem>
    <MenuItem onClick={() => setFilter('비활성')}>비활성</MenuItem>
  </Menu>
</Dropdown>;
```

### Action Menu

```tsx
<Dropdown>
  <MenuButton variant="plain" size="sm">
    작업
  </MenuButton>
  <Menu>
    <MenuItem>
      <EditIcon sx={{ mr: 1 }} />
      편집
    </MenuItem>
    <MenuItem>
      <CopyIcon sx={{ mr: 1 }} />
      복사
    </MenuItem>
    <MenuItem color="danger">
      <DeleteIcon sx={{ mr: 1 }} />
      삭제
    </MenuItem>
  </Menu>
</Dropdown>
```

### Language Selector

```tsx
const [language, setLanguage] = useState('한국어');

<Dropdown>
  <MenuButton variant="soft" size="sm">
    {language}
  </MenuButton>
  <Menu>
    <MenuItem onClick={() => setLanguage('한국어')}>한국어</MenuItem>
    <MenuItem onClick={() => setLanguage('English')}>English</MenuItem>
    <MenuItem onClick={() => setLanguage('日本語')}>日本語</MenuItem>
  </Menu>
</Dropdown>;
```

### Sort Options

```tsx
const [sortBy, setSortBy] = useState('이름순');

<Dropdown>
  <MenuButton variant="outlined" startDecorator={<SortIcon />} endDecorator={<ExpandMoreIcon />}>
    정렬: {sortBy}
  </MenuButton>
  <Menu>
    <MenuItem onClick={() => setSortBy('이름순')}>이름순</MenuItem>
    <MenuItem onClick={() => setSortBy('날짜순')}>날짜순</MenuItem>
    <MenuItem onClick={() => setSortBy('크기순')}>크기순</MenuItem>
  </Menu>
</Dropdown>;
```

## Best Practices

1. **명확한 라벨**: MenuButton의 텍스트는 메뉴의 내용을 명확히 나타내야 합니다.

2. **적절한 아이콘 사용**: 드롭다운임을 나타내는 화살표 아이콘을 사용하세요.

   ```tsx
   <MenuButton endDecorator={<ExpandMoreIcon />}>
   ```

3. **메뉴 아이템 그룹화**: 관련된 메뉴 아이템들은 ListDivider로 구분하세요.

4. **키보드 접근성**: 키보드 탐색이 가능하도록 적절한 props를 설정하세요.

5. **적절한 배치**: 화면 공간을 고려하여 메뉴의 placement를 설정하세요.

6. **로딩 상태**: 필요한 경우 MenuButton에 loading 상태를 표시하세요.

7. **일관된 스타일**: 애플리케이션 전반에서 일관된 드롭다운 스타일을 유지하세요.

8. **모바일 고려**: 모바일에서도 사용하기 쉽도록 충분한 터치 영역을 확보하세요.

## Controlled vs Uncontrolled

### Uncontrolled (기본)

```tsx
<Dropdown>
  <MenuButton>메뉴</MenuButton>
  <Menu>
    <MenuItem>옵션</MenuItem>
  </Menu>
</Dropdown>
```

### Controlled

```tsx
const [open, setOpen] = useState(false);

<Dropdown open={open} onOpenChange={(event, isOpen) => setOpen(isOpen)}>
  <MenuButton>메뉴</MenuButton>
  <Menu>
    <MenuItem onClick={() => setOpen(false)}>옵션</MenuItem>
  </Menu>
</Dropdown>;
```

## Accessibility

Dropdown은 접근성을 위한 기본적인 기능들을 제공합니다:

- **키보드 탐색**: Tab, Enter, Escape, 화살표 키 지원
- **ARIA 속성**: 적절한 ARIA 라벨과 역할 자동 설정
- **포커스 관리**: 메뉴가 열릴 때 첫 번째 아이템으로 포커스 이동
- **스크린 리더**: 메뉴의 상태와 옵션들을 적절히 읽어줌

추가적인 접근성을 위해:

- 메뉴 아이템에 적절한 라벨 제공
- 위험한 작업(삭제 등)에 대한 확인 절차 제공
- 색상에만 의존하지 않는 시각적 피드백

## When to Use Dropdown

### ✅ 사용하기 좋은 경우

- **메뉴 시스템**: 네비게이션이나 컨텍스트 메뉴가 필요할 때
- **필터링**: 여러 옵션 중 하나를 선택하는 필터가 필요할 때
- **액션 목록**: 특정 항목에 대한 여러 작업이 있을 때
- **사용자 메뉴**: 프로필, 설정, 로그아웃 등의 사용자 관련 기능
- **공간 절약**: 화면 공간이 제한적일 때 여러 옵션을 숨기고 싶을 때

### ❌ 사용하지 않는 것이 좋은 경우

- **단일 액션**: 하나의 간단한 작업만 있을 때는 일반 Button 사용
- **긴 폼**: 폼에서는 Select 컴포넌트가 더 적절
- **항상 보여야 하는 옵션**: 중요한 옵션들은 항상 표시하는 것이 좋음
- **너무 많은 옵션**: 20개 이상의 옵션이 있다면 다른 UI 패턴 고려

Dropdown은 사용자에게 깔끔하고 직관적인 메뉴 경험을 제공하는 강력한 컴포넌트입니다. 적절히 사용하면 공간을 효율적으로 활용하면서도 풍부한 기능을 제공할 수 있습니다.
