본문 바로가기

Components · 내비게이션

Step Indicator (단계 표시기)

다단계 절차에서 전체 단계와 현재 위치·완료 여부를 보여 주는 내비게이션 컴포넌트. 견적 요청·온보딩 같은 선형 입력에 쓴다.

정의

여러 단계로 이뤄진 절차에서 전체 단계와 현재 위치·완료 상태를 함께 보여 주는 내비게이션 컴포넌트다.

Anatomy

3 4 정보 입력 제품 선택 일정 협의 최종 확인 ① 단계 원 ② 연결선 ④ 현재 단계 ③ 단계 라벨
부위토큰
① 단계 원크기 --step-size(32) · 완료 --step-bg-done · 진행중 --step-bg-active+글자 --step-fg-active · 대기 --step-bg-pending+글자 --step-fg-pending
② 연결선--step-connector, 완료 구간은 --step-bg-active로 채움
③ 단계 라벨--step-label-fg · --text-caption
④ 현재 단계진행중 원 + aria-current="step"

변형

변형용도
수평(기본)3~5단계의 짧은 절차(견적 요청 4단계 등) — 가로 배열
수직단계 설명이 길거나 모바일 폭이 좁을 때 — 세로 배열
체크형완료 단계는 체크(✓), 대기·진행중은 번호로 상태를 구분

상태

상태라벨
대기(pending)bg --step-bg-pending / fg --step-fg-pending--step-label-fg(흐리게)
진행중(active)bg --step-bg-active / fg --step-fg-active--step-label-fg(굵게) + aria-current="step"
완료(done)bg --step-bg-done / 체크 --step-fg-active--step-label-fg
Focus(이동 가능 단계만)box-shadow: var(--focus-ring)

Do / Don't

Do
  • 3~7단계 안에서 쓴다(KRDS 권장) — 견적 요청·온보딩 같은 짧고 선형인 절차에.
  • 완료·진행중·대기를 색과 형태(체크/번호) 둘 다로 구분한다 — 색만으로 나누지 않는다.
  • 현재 단계 라벨을 굵기·색으로 강조해 지금 위치를 분명히 한다.
Don't
  • 8단계 이상을 한 줄에 늘어놓지 말 것 — 단계를 묶거나 진행률 바로 대체한다.
  • 비선형(자유 이동) 절차에 쓰지 말 것 — 순서가 없으면 단계 표시기가 아니라 탭·목차를 쓴다.
  • 아직 도달하지 않은 대기 단계를 클릭 가능하게 열어 두지 말 것.

콘텐츠 규칙

  • 라벨은 명사구 1~2어절("정보 입력"·"일정 협의") — 문장 금지, 각 단계 길이를 맞춘다.
  • 단계 번호는 자동(1·2·3…), 라벨에 "1단계"처럼 번호를 중복 표기하지 않는다.
  • 모든 단계 라벨의 품사·어투를 통일한다(전부 명사형 또는 전부 동사형).
  • 전역 규칙: ../guidelines/ux-writing.md.

키보드 인터랙션

동작
Tab이동 가능한(완료) 단계로 포커스 이동
Enter포커스된 완료 단계로 이동

정적(표시 전용) 단계 표시기는 포커스를 받지 않는다 — 이때 키보드 인터랙션은 해당 없음.

접근성

  • <ol>(순서 있는 목록)로 마크업 — 단계의 순서를 의미로 전달한다.
  • 현재 단계에 aria-current="step" — 스크린리더가 위치를 알린다.
  • 완료/대기 상태를 시각(체크·색)만으로 두지 말고 시각적으로 숨긴 텍스트("완료" 등)로도 전달한다.
  • 대비: 대기 단계 라벨도 --step-label-fg로 최소 대비를 유지(과하게 흐리지 않게).
  • 기준: ../guidelines/accessibility.md.

코드

  1. 정보 입력 (완료)
  2. 제품 선택 (완료)
  3. 3 일정 협의
  4. 4 최종 확인
html
<ol class="pi-steps" aria-label="견적 요청 단계">
  <li class="pi-steps__item pi-steps__item--done">
    <span class="pi-steps__marker" aria-hidden="true">&#10003;</span>
    <span class="pi-steps__label">정보 입력<span class="pi-steps__sr"> (완료)</span></span>
  </li>
  <li class="pi-steps__item pi-steps__item--done">
    <span class="pi-steps__marker" aria-hidden="true">&#10003;</span>
    <span class="pi-steps__label">제품 선택<span class="pi-steps__sr"> (완료)</span></span>
  </li>
  <li class="pi-steps__item pi-steps__item--active" aria-current="step">
    <span class="pi-steps__marker">3</span>
    <span class="pi-steps__label">일정 협의</span>
  </li>
  <li class="pi-steps__item">
    <span class="pi-steps__marker">4</span>
    <span class="pi-steps__label">최종 확인</span>
  </li>
</ol>
css
.pi-steps { display: flex; list-style: none; margin: 0; padding: 0; }
.pi-steps__item {
  display: flex; flex-direction: column; align-items: center;
  flex: 1 1 0; position: relative; text-align: center; gap: var(--space-3);
}
.pi-steps__item::before {
  content: ""; position: absolute; top: calc(var(--step-size) / 2); height: var(--border-medium);
  left: calc(-50% + var(--step-size) / 2); width: calc(100% - var(--step-size)); background: var(--step-connector);
}
.pi-steps__item:first-child::before { display: none; }
.pi-steps__item--done::before,
.pi-steps__item--active::before { background: var(--step-bg-active); }
.pi-steps__marker {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--step-size); height: var(--step-size); border-radius: var(--radius-full);
  background: var(--step-bg-pending); color: var(--step-fg-pending); font: var(--text-label);
}
.pi-steps__item--active .pi-steps__marker { background: var(--step-bg-active); color: var(--step-fg-active); font-weight: var(--font-weight-bold); }
.pi-steps__item--done .pi-steps__marker { background: var(--step-bg-done); color: var(--step-fg-active); }
.pi-steps__label { font: var(--text-caption); color: var(--step-label-fg); word-break: keep-all; }
.pi-steps__item--active .pi-steps__label { font-weight: var(--font-weight-bold); }
.pi-steps__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

Changelog

날짜변경
2026-07-15문서 계약(10섹션) 적용 — KRDS 벤치마킹 규격(2026-07-15) 승계, Anatomy 도해·변형·상태·콘텐츠 규칙·키보드·실코드 신설