본문 바로가기

Components · 컨테이너

Accordion · Disclosure (아코디언·디스클로저)

헤더를 눌러 그 아래 패널을 펼치거나 접는다. FAQ·상세페이지의 긴 콘텐츠를 압축하는 데 적합하다.

정의

헤더를 눌러 그 아래 패널을 펼치거나 접어 긴 콘텐츠를 압축해 보여 주는 컴포넌트다.

Anatomy

디자인구독은 어떻게 신청하나요? 상담 신청 후 담당자가 요금을 안내합니다. ① 아코디언 항목 ② 헤더 버튼 ③ 아이콘 ④ 패널
부위토큰
① 항목보더 --accordion-border · 모서리 --accordion-radius
② 헤더 버튼패딩 --accordion-header-pad · fg --accordion-header-fg · --text-label
③ 아이콘--accordion-icon-fg · 펼침 시 180° 회전
④ 패널fg --accordion-panel-fg · --text-body · 패딩 --accordion-header-pad

변형

변형용도
다중 펼침(기본)여러 항목을 동시에 펼침 — FAQ 목록
단일 펼침한 번에 하나만 펼쳐 비교에 집중 — 형제 항목은 자동 접힘
Disclosure비중 낮은 보조 토글("자세히 보기") — --accordion-* 재사용 + 글자 축소, 주 탐색에는 쓰지 않음

상태

상태헤더
Default(접힘)fg --accordion-header-fg · aria-expanded="false" · 아이콘 기본
Hoverbg --color-bg-subtle
Expanded(펼침)aria-expanded="true" · 아이콘 180° 회전 · 패널 표시
Focusbox-shadow: var(--focus-ring)
Disabledopacity: var(--opacity-disabled) + cursor: not-allowed

Do / Don't

Do
  • "펼쳐 보면 되는" 보조 정보(FAQ·상세 규격)에 쓴다.
  • 헤더 라벨만 읽고도 안에 무엇이 있는지 알 수 있게 구체적으로 쓴다.
  • 아이콘 방향(펼침/접힘)과 aria-expanded 상태를 항상 일치시킨다.
Don't
  • 반드시 봐야 할 핵심 정보를 아코디언 뒤에 숨기지 말 것(KRDS) — 기본 노출한다.
  • 한 항목에 문단 여럿·중첩 아코디언을 넣지 말 것 — 길면 별도 페이지로.
  • Disclosure를 탭·아코디언 같은 주 탐색 자리에 쓰지 말 것 — 보조 토글로만.

콘텐츠 규칙

  • 헤더는 내용을 요약한 명사구·질문 1줄(≤20자) — "항목 1" 같은 무정보 라벨 금지.
  • 패널 본문은 2~5문장 안에서 끝낸다 — 더 길면 문서 섹션으로.
  • FAQ는 질문형 헤더("배송은 얼마나 걸리나요?") + 답변 본문 구조로 통일한다.

키보드 인터랙션

동작
Tab다음 아코디언 헤더로 포커스 이동
Enter / Space포커스된 헤더의 패널 펼침/접힘 토글

접근성

  • 헤더는 네이티브 <button>aria-expanded(true/false) + aria-controls(패널 id). 패널은 role="region"·aria-labelledby(헤더 id) 권장.
  • 헤딩 구조 안에서는 헤더 버튼을 <h3> 등으로 감싸 문서 아웃라인을 유지한다.
  • 상태를 아이콘 회전만으로 두지 말고 aria-expanded로 스크린리더에 전달한다.
  • 헤더 전체가 클릭 대상 ≥ --target-min. 기준: ../guidelines/accessibility.md.

코드

홈페이지에서 상담을 신청하면 담당자가 필요한 디자인 범위를 확인해 월 정액 요금을 안내합니다.

html
<div class="pi-accordion">
  <div class="pi-accordion__item">
    <h3 class="pi-accordion__heading">
      <button class="pi-accordion__header" type="button" aria-expanded="true" aria-controls="acc-sub" id="acc-sub-h">디자인구독은 어떻게 신청하나요?<svg class="pi-accordion__icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M4 6l4 4 4-4" fill="none" stroke="currentColor" stroke-width="1.5"/></svg></button>
    </h3>
    <div class="pi-accordion__panel" role="region" id="acc-sub" aria-labelledby="acc-sub-h">
      <p>홈페이지에서 상담을 신청하면 담당자가 필요한 디자인 범위를 확인해 월 정액 요금을 안내합니다.</p>
    </div>
  </div>
  <div class="pi-accordion__item">
    <h3 class="pi-accordion__heading">
      <button class="pi-accordion__header" type="button" aria-expanded="false" aria-controls="acc-safe" id="acc-safe-h">안전시설관리 구독은 무엇을 관리하나요?<svg class="pi-accordion__icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M4 6l4 4 4-4" fill="none" stroke="currentColor" stroke-width="1.5"/></svg></button>
    </h3>
    <div class="pi-accordion__panel" role="region" id="acc-safe" aria-labelledby="acc-safe-h" hidden>
      <p>노면표시·안전표지를 정기 점검하고 마모되면 교체까지 정액으로 관리합니다.</p>
    </div>
  </div>
</div>
css
.pi-accordion__item { border: var(--border-thin) solid var(--accordion-border); border-radius: var(--accordion-radius); }
.pi-accordion__item + .pi-accordion__item { margin-top: var(--space-3); }
.pi-accordion__heading { margin: 0; }
.pi-accordion__header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  width: 100%;
  padding: var(--accordion-header-pad);
  border: none; background: none; cursor: pointer; text-align: left;
  color: var(--accordion-header-fg);
  font: var(--text-label);
  letter-spacing: var(--text-label-letter-spacing);
  min-height: var(--target-min);
  word-break: keep-all;
  transition: background var(--duration-base) var(--easing-out);
}
.pi-accordion__header:hover { background: var(--color-bg-subtle); }
.pi-accordion__header:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--accordion-radius); }
.pi-accordion__icon { flex: none; color: var(--accordion-icon-fg); transition: transform var(--duration-base) var(--easing-out); }
.pi-accordion__header[aria-expanded="true"] .pi-accordion__icon { transform: rotate(180deg); }
.pi-accordion__panel {
  padding: 0 var(--accordion-header-pad) var(--accordion-header-pad);
  color: var(--accordion-panel-fg);
  font: var(--text-body);
  word-break: keep-all;
}
.pi-accordion__panel[hidden] { display: none; }
.pi-accordion--disclosure .pi-accordion__item { border: none; border-radius: 0; }
.pi-accordion--disclosure .pi-accordion__header { font: var(--text-body-sm); padding: var(--space-3) 0; }
@media (prefers-reduced-motion: reduce) { .pi-accordion__header, .pi-accordion__icon { transition: none; } }
js
document.querySelectorAll(".pi-accordion__header").forEach((header) => {
  header.addEventListener("click", () => {
    const expanded = header.getAttribute("aria-expanded") === "true";
    header.setAttribute("aria-expanded", expanded ? "false" : "true");
    document.getElementById(header.getAttribute("aria-controls")).hidden = expanded;
  });
});

Changelog

날짜변경
2026-07-15문서 계약(10섹션) 적용 — Anatomy 도해·단일/다중 펼침 변형·Disclosure·콘텐츠 규칙·토글 실코드 신설. KRDS 벤치마킹 규격(핵심 정보 숨김 금지) 승계