Breadcrumb | CoUI
LogoCoUI

Breadcrumb

현재 페이지의 위치를 계층적으로 나타내는 탐색 경로 컴포넌트

Breadcrumb#

현재 페이지의 위치를 계층적으로 표시하여 사용자가 상위 페이지로 쉽게 이동할 수 있도록 하는 탐색 경로 컴포넌트입니다.

Live Preview#

사용 시기 (When to Use)#

이 컴포넌트를 사용하세요:

  • 3단계 이상의 계층 구조를 가진 페이지에서 현재 위치를 안내할 때
  • 사용자가 상위 카테고리로 빠르게 돌아갈 수 있어야 할 때 (예: 이커머스 카테고리, 관리자 설정)
  • 문서, 파일 탐색기처럼 깊은 계층 구조를 탐색할 때

대신 다른 컴포넌트를 사용하세요:

  • Tabs: 동일 레벨의 섹션을 전환할 때
  • Navigation: 앱 주요 섹션 간 이동에는 네비게이션 사용
  • Link: 단순 이전 페이지 이동 링크만 필요할 때

기본 사용법 (Basic Usage)#

Flutter / Web 모두 동일한 Breadcrumb API 를 사용합니다. 데이터-드리븐 — CoreBreadcrumbItem 리스트를 넘기면 마지막 항목이 자동으로 현재 위치(비탐색) 로 렌더링됩니다.

// 기본 브레드크럼
Breadcrumb(
  items: const [
    CoreBreadcrumbItem(label: '홈', href: '/'),
    CoreBreadcrumbItem(label: '카테고리', href: '/category'),
    CoreBreadcrumbItem(label: '상품 상세'),
  ],
  onItemTap: handleBreadcrumbNavigation,
)
// 기본 브레드크럼
Breadcrumb(
  items: const [
    CoreBreadcrumbItem(label: '홈', href: '/'),
    CoreBreadcrumbItem(label: '카테고리', href: '/category'),
    CoreBreadcrumbItem(label: '상품 상세'),
  ],
  onItemTap: handleBreadcrumbNavigation,
)

Props / Parameters#

속성타입기본값설명
items List<CoreBreadcrumbItem> 필수 탐색 경로 항목 목록 (마지막 = 현재)
onItemTap void Function(int)? null 비탐색(현재) 외 항목 탭 콜백 — 0-based 인덱스
variant CoreBreadcrumbVariant standard 시각 변형
breadcrumbStyle CoreBreadcrumbStyle? null 인스턴스 스타일 (Style 시스템 참조)

CoreBreadcrumbItemlabel (필수) 과 href (선택) 를 가집니다. 두 플랫폼 모두 탐색은 onItemTap 콜백으로 처리됩니다 — href 는 정보 제공용입니다. Web 에서는 상호작용 가능한 항목에 data-href 속성으로 노출될 뿐(툴링용), 네이티브 <a> 태그로 렌더링되지 않습니다.

스타일 시스템 (Style System)#

Breadcrumb 의 모든 chrome / dimensional / nested-slot 오버라이드는 CoreBreadcrumbStyle 단일 슬롯으로 흐릅니다. 시맨틱 / behaviour 필드 (items / onItemTap / variant) 는 위젯/컴포넌트 파라미터로 직접 전달합니다.

시맨틱 vs 스타일#

  • 시맨틱 / behaviour: 위젯/컴포넌트 파라미터로 직접 (items, onItemTap, variant)
  • chrome / dimensional / 슬롯 스타일: CoreBreadcrumbStyle 한 곳으로 (itemSeparatorGapStyle / itemColor / currentItemColor / itemHoverColor / itemTextStyle / separatorIconStyle / hoverDuration / clickableStyle)

Resolve chain#

CoreBreadcrumbStyle.defaultX                   // design system default
  → CoreBreadcrumbTheme.style                  // 프로젝트 공통
  → widget.breadcrumbStyle                     // 인스턴스별

CoreBreadcrumbStyle 필드#

필드타입설명
itemSeparatorGapStyle CoreGapStyle? Nested [CoreGapStyle] slot for the gap between item / separator / item — forwarded straight to Gap(gapStyle: …) . null defers to [defaultItemSeparatorGapStyle].
itemColor CoreColor? Override colour applied to inactive (link) items. null defers to [itemTextStyle]'s colour, then [defaultItemColor].
currentItemColor CoreColor? Override colour applied to the current (last) item.
itemHoverColor CoreColor? Override hover colour applied to an interactive link item. null defers to [defaultItemHoverColor].
itemTextStyle CoreTextStyle? Item text style (applies to every breadcrumb item).
separatorIconStyle CoreIconStyle? Separator icon style (size / colour of the chevron glyph).
hoverDuration Duration? Override colour-transition duration for link hover. null defers to [defaultHoverDuration].
clickableStyle CoreClickableStyle? Nested [CoreClickableStyle] slot for the composed per-item Clickable (interactive link items). Merged on top of [defaultClickableStyle] and raw-forwarded to Clickable(clickableStyle:) .

빠른 오버라이드 (Chain)#

이미 만든 Breadcrumb 인스턴스에 스타일을 빠르게 덧붙이고 싶다면 withStyle 체인을 쓸 수 있습니다. 생성자의 style 슬롯 인자와 동일하게 동작하지만, 이미 구성된 위젯 위에서 바로 이어 쓸 수 있습니다.

class BreadcrumbChainExample extends StatelessWidget {
  const BreadcrumbChainExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Breadcrumb(
      items: const [
        CoreBreadcrumbItem(label: 'Home', href: '/'),
        CoreBreadcrumbItem(label: 'Components', href: '/components'),
        CoreBreadcrumbItem(label: 'Breadcrumb'),
      ],
      onItemTap: (index) {},
    ).withStyle(
      const CoreBreadcrumbStyle(
        itemSeparatorGapStyle: CoreGapStyle(size: CoreSpace.space16),
        itemColor: CoreColor.token(CoreColors.onSurfaceVariant),
        currentItemColor: CoreColor.token(CoreColors.primary),
        itemHoverColor: CoreColor.token(CoreColors.tertiary),
        separatorIconStyle: CoreIconStyle(
          size: CoreSize.size12,
          color: CoreColor.token(CoreColors.outline),
        ),
      ),
    );
  }
}
class BreadcrumbChainExample extends StatelessComponent {
  const BreadcrumbChainExample({super.key});

  @override
  Component build(BuildContext context) {
    return Breadcrumb(
      items: const [
        CoreBreadcrumbItem(label: 'Home', href: '/'),
        CoreBreadcrumbItem(label: 'Components', href: '/components'),
        CoreBreadcrumbItem(label: 'Breadcrumb'),
      ],
      onItemTap: (index) {},
    ).withStyle(
      const CoreBreadcrumbStyle(
        itemSeparatorGapStyle: CoreGapStyle(size: CoreSpace.space16),
        itemColor: CoreColor.token(CoreColors.onSurfaceVariant),
        currentItemColor: CoreColor.token(CoreColors.primary),
        itemHoverColor: CoreColor.token(CoreColors.tertiary),
        separatorIconStyle: CoreIconStyle(
          size: CoreSize.size12,
          color: CoreColor.token(CoreColors.outline),
        ),
      ),
    );
  }
}

변형 (Variants)#

Breadcrumb 은 현재 단일 시각 변형(standard) 을 가집니다. chevron() 구분자가 기본이며, separator 아이콘 크기 / 색은 breadcrumbStyle.separatorIconStyle 로 오버라이드합니다.

Breadcrumb(
  items: const [
    CoreBreadcrumbItem(label: '대시보드', href: '/'),
    CoreBreadcrumbItem(label: '프로젝트', href: '/projects'),
    CoreBreadcrumbItem(label: 'CoUI'),
  ],
  breadcrumbStyle: const CoreBreadcrumbStyle(
    itemSeparatorGapStyle: CoreGapStyle(size: CoreSpace.space12),
  ),
)

동작 스펙 (Behavior)#

인터랙션#

  • 클릭/탭: 마지막 외 항목 클릭 시 onItemTap 콜백을 0-based 인덱스와 함께 호출 (마지막 항목은 현재 페이지이므로 비활성)
  • 호버: 클릭 가능한 항목 호버 시 텍스트 색이 onSurface 로 전환 (150ms ease-in-out)

상태 전환#

  • 마지막 항목은 현재 위치를 나타내며 onSurface 비활성 텍스트로 표시
  • 앞 항목들은 onSurfaceVariant 링크 스타일로 표시 (클릭 가능)

애니메이션#

  • 링크 호버 시 색상 전환 150ms ease-in-out

사용 가이드라인 (Usage Guidelines)#

✅ Do#

현재 페이지(마지막 항목)는 자동으로 클릭 불가로 표시

Breadcrumb(
  items: const [
    CoreBreadcrumbItem(label: '홈', href: '/'),
    CoreBreadcrumbItem(label: '설정', href: '/settings'),
    CoreBreadcrumbItem(label: '보안'), // 마지막 = 현재 페이지
  ],
  onItemTap: handleNavigation,
)

마지막 항목은 자동으로 비탐색 텍스트로 렌더링되어 현재 위치를 명확히 한다.


❌ Don't#

2단계 이하 계층에서 브레드크럼 남용하지 않기

// ❌ 단순 2단계 구조에 브레드크럼
Breadcrumb(
  items: const [
    CoreBreadcrumbItem(label: '홈', href: '/'),
    CoreBreadcrumbItem(label: '설정'),
  ],
)

2단계 이하는 뒤로가기 버튼 또는 간단한 Link로 충분하며 브레드크럼이 오히려 복잡도를 높인다.

✅ Do#

경로가 길면 좁은 화면에서 가로 스크롤로 흘려보내기

Breadcrumb 은 콘텐츠가 컨테이너를 넘으면 가로 스크롤(overflow-x-auto)로 처리하므로 줄바꿈으로 레이아웃이 깨지지 않는다.

접근성 (Accessibility)#

키보드 인터랙션#

동작
Tab다음 클릭 가능한 항목으로 포커스 이동
Enter포커스된 항목 활성화
Shift + Tab이전 항목으로 포커스 이동

스크린 리더#

  • Flutter: CoUISemantics(role: .navigation, label: CoUILocalizations.of(context).breadcrumbLabel, container: true) 로 래핑 — <nav> 에 대응하는 navigation landmark role
  • Web: <div role="navigation" aria-label="..."><nav> 요소가 아니라 ARIA role 로 랜드마크를 표현합니다. 현재 페이지 항목에 aria-current="page" 추가
  • 랜드마크 라벨은 두 플랫폼 모두 breadcrumbLabel 로케일 키에서 옵니다(예: 한국어 기본값 "탐색 경로", 영어 기본값 "Breadcrumb") — 하드코딩된 문자열이 아니라 활성 로케일을 따라갑니다

터치 타겟#

현재 Breadcrumb 항목은 별도의 터치 타겟 확장을 적용하지 않습니다 — 히트 영역은 렌더된 텍스트/패딩 크기를 그대로 따릅니다 (checkbox/toggle/slider 류가 쓰는 CoreTouchTarget.minimum 확장 마커가 아직 배선되지 않았습니다).

크로스 플랫폼 차이점 (Platform Differences)#

항목FlutterWeb
클래스명BreadcrumbBreadcrumb (동일)
링크 처리 onItemTap 콜백 onItemTap 콜백 + hrefdata-href 속성 노출 (native <a> 아님)
구분자chevron Iconchevron Icon
호버MouseRegion + 색 전환CSS :hover 토큰 클래스
  • Navigation: 앱 주요 섹션 간 이동에 사용
  • Tabs: 동일 계층의 콘텐츠를 탭으로 전환할 때 사용
  • Link: 단일 이전 페이지 이동 링크가 필요할 때 사용