Accordion
compound 패턴의 Accordion을 box/line variant, activeIndices 제어, shouldKeepMounted, buttonIndex 기준으로 정리한 가이드 페이지입니다.
Accordion / usage
Accordion은 필요한 정보만 접고 펼치는 compound UI입니다. 이 페이지에서는 box/line variant, activeIndices 제어, shouldKeepMounted, buttonIndex 패턴을 기준으로 정리합니다.
children | type | variant | defaultActiveIndices
ReactNode"single" | "multiple""box" | "line"기본 구조는 Accordion 안에 Item, Button, Head, Panel을 조합하는 형태입니다. 아래 예시는 단일 패널만 열리는 box variant의 기본 패턴입니다.
activeIndices | onChange | shouldKeepMounted
number[](nextActiveIndices: number[]) => voidbooleanactiveIndices를 연결하면 외부 상태로 열린 패널을 제어할 수 있습니다. shouldKeepMounted를 true로 두면 패널을 닫아도 내부 form 상태가 유지돼서 실제 입력 요소 테스트에 더 적합합니다.
buttonIndex
numberAccordion.Head에 buttonIndex를 주면 헤더 전체를 버튼으로 감싸지 않고, 오른쪽 화살표만 토글 버튼으로 쓸 수 있습니다. 헤더 텍스트는 토글 버튼과 panel의 접근성 이름으로 함께 연결되며, 약관 동의처럼 헤더 안에 체크박스나 다른 인터랙션을 넣을 때 이 패턴이 더 안전합니다.
- 서비스 제공을 위한 기본 계정 정보와 접속 로그를 수집합니다.
- 관련 법령 보관 기간이 끝나면 지체 없이 파기한다는 조건입니다.
- 헤더의 체크박스는 독립적으로 동작하고, 오른쪽 화살표만 패널을 엽니다.
Accordion props 한눈에 보기
Accordion root가 제어하는 열림 방식과 스타일 variant 규칙을 정리했습니다.
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
children | React.ReactNode | - | Required | 보통 Accordion.Item, Accordion.Button, Accordion.Head, Accordion.Panel 조합을 넣습니다. |
type | "single" | "multiple" | "multiple" | Optional | single이면 한 번에 하나만 열리고, multiple이면 여러 패널을 동시에 열 수 있습니다. |
variant | "box" | "line" | "box" | Optional | 아코디언 외곽 스타일과 구분선 패턴을 바꿉니다. |
activeIndices | number[] | undefined | Optional | 외부 상태로 열린 패널 index 배열을 제어합니다. 주면 controlled 모드로 동작합니다. |
defaultActiveIndices | number[] | [] | Optional | uncontrolled 모드에서 초기 열린 패널 index 배열입니다. |
onChange | (nextActiveIndices: number[]) => void | undefined | Optional | 패널 토글 뒤 최종 열린 index 배열을 돌려줍니다. |
shouldKeepMounted | boolean | false | Optional | 닫힌 패널을 DOM에서 제거하지 않고 숨김 상태로 유지합니다. 내부 form 상태 유지가 필요할 때 유용합니다. |
className | string | undefined | Optional | Accordion 루트 wrapper에 커스텀 클래스를 추가합니다. |
activeIndices와 defaultActiveIndices는 내부에서 정수만 남기고 중복을 제거한 뒤 사용합니다. type="single"이면 최종적으로 첫 번째 index 하나만 유지됩니다.Accordion.Item props 한눈에 보기
Accordion.Item은 index 단위로 헤더와 패널을 묶는 motion wrapper입니다.
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
children | React.ReactNode | - | Required | 보통 해당 index에 대응하는 Accordion.Button과 Accordion.Panel을 함께 넣습니다. |
index | number | - | Required | 현재 item을 식별하는 index입니다. Button과 Panel의 index와 맞아야 같은 패널로 동작합니다. |
className | string | undefined | Optional | Accordion item wrapper에 커스텀 클래스를 추가합니다. |
layout | initial | animate | exit | style ... | framer-motion HTMLMotionProps<"div"> | inherited | Optional | Accordion.Item은 motion.div 기반이라 필요한 motion/div props를 함께 전달할 수 있습니다. |
Accordion.Item은 현재 index가 열린 상태면 is-active 클래스를 추가하고, layout transition을 같이 적용합니다.Accordion.Button props 한눈에 보기
Accordion.Button은 패널 토글과 접근성 연결을 자동으로 처리하는 button wrapper입니다.
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
children | React.ReactNode | - | Required | 토글 버튼 내부 콘텐츠입니다. 보통 Accordion.Head를 children으로 넣습니다. |
index | number | - | Required | 토글할 패널 index입니다. 같은 index의 Accordion.Panel과 연결됩니다. |
onClick | (index: number, event: MouseEvent<HTMLButtonElement>) => void | undefined | Optional | 내부 토글 처리 이후 추가로 실행되는 콜백입니다. 일반 button onClick과 달리 index를 첫 번째 인자로 받습니다. |
aria-controls | aria-expanded | string | boolean | auto linked | Optional | 생략하면 현재 panel id와 열림 상태를 자동으로 연결합니다. 필요하면 직접 override할 수 있습니다. |
disabled | boolean | false | Optional | 버튼 상호작용을 막습니다. native button disabled 동작을 그대로 따릅니다. |
className | string | undefined | Optional | Accordion button element에 커스텀 클래스를 추가합니다. |
name | title | tabIndex | data-* ... | native button props | inherited | Optional | children, onClick, id를 제외한 나머지 native button props는 그대로 전달할 수 있습니다. |
Accordion.Button은 type="button"과 내부 id를 직접 고정합니다. 또한 패널이 닫혀 있고 shouldKeepMounted가 false이면 기본 aria-controls를 제거해 unmounted panel과의 참조를 피합니다.Accordion.Head props 한눈에 보기
Accordion.Head는 제목 영역과 화살표 토글 버튼을 조합하는 헤더 wrapper입니다.
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
children | React.ReactNode | undefined | Optional | 헤더 제목 영역 콘텐츠입니다. 없으면 제목 없이 화살표 영역만 렌더링됩니다. |
buttonIndex | number | undefined | Optional | 주면 오른쪽 화살표만 Accordion.Button으로 렌더링됩니다. 헤더 안에 checkbox 같은 다른 인터랙션을 넣을 때 유용합니다. |
className | string | undefined | Optional | Accordion head wrapper에 커스텀 클래스를 추가합니다. |
id | role | style | data-* ... | native div props | inherited | Optional | Accordion.Head가 직접 제어하지 않는 div props는 wrapper에 그대로 전달됩니다. |
buttonIndex가 있으면 헤더 텍스트에 title id를 만들고, 오른쪽 화살표 버튼의 aria-labelledby로 연결합니다. 그래서 헤더 전체를 버튼으로 감싸지 않아도 접근성 이름이 유지됩니다.Accordion.Panel props 한눈에 보기
Accordion.Panel은 현재 index의 열림 상태에 따라 collapse 애니메이션과 aria 연결을 처리합니다.
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
children | React.ReactNode | - | Required | 열리고 닫히는 패널 본문 콘텐츠입니다. |
index | number | - | Required | 현재 패널을 식별하는 index입니다. 같은 index의 Accordion.Button과 연결됩니다. |
className | string | undefined | Optional | Accordion panel wrapper에 커스텀 클래스를 추가합니다. |
Accordion의 shouldKeepMounted가 제어합니다. true면 패널을 숨긴 채 유지하고, false면 닫힐 때 DOM에서 제거합니다.