TabPane | CoUI

TabPane

박스형 탭 + 통합 콘텐츠 패널

TabPane#

박스형 탭 스트립과 각 탭이 소유한 콘텐츠 패널을 하나로 묶은 자체 완결형 탭 카드입니다. 탭 바만 제공하는 Tabs 와 달리, CoreTabItem.content 슬롯의 위젯을 아래 패널에 함께 렌더합니다.

Live Preview#

Web
Manage your account settings.
Flutter
Loading Flutter...
class TabPaneExample extends StatefulComponent {
  const TabPaneExample({super.key});

  @override
  State<TabPaneExample> createState() => _TabPaneExampleState();
}

class _TabPaneExampleState extends State<TabPaneExample> {
  int _index = 0;

  @override
  Component build(BuildContext context) {
    return TabPane(
      tabs: [
        CoreTabItem(
          label: 'Account',
          content: div(
            [Text('Manage your account settings.').bodyMedium.onSurface],
            classes: 'p-${CoreSpace.scale.space16}',
          ),
        ),
        CoreTabItem(
          label: 'Password',
          content: div(
            [Text('Change your password here.').bodyMedium.onSurface],
            classes: 'p-${CoreSpace.scale.space16}',
          ),
        ),
      ],
      selectedIndex: _index,
      onChanged: (index) => setState(() => _index = index),
    );
  }
}
class TabPaneExample extends StatefulWidget {
  const TabPaneExample({super.key});

  @override
  State<TabPaneExample> createState() => _TabPaneExampleState();
}

class _TabPaneExampleState extends State<TabPaneExample> {
  int _index = 0;

  @override
  Widget build(BuildContext context) {
    return TabPane(
      tabs: [
        CoreTabItem(
          label: 'Account',
          content: Padding(
            padding: const EdgeInsets.all(CoreSpace.space16),
            child: Text('Manage your account settings.').bodyMedium.onSurface,
          ),
        ),
        CoreTabItem(
          label: 'Password',
          content: Padding(
            padding: const EdgeInsets.all(CoreSpace.space16),
            child: Text('Change your password here.').bodyMedium.onSurface,
          ),
        ),
      ],
      selectedIndex: _index,
      onChanged: (i) => setState(() => _index = i),
    );
  }
}

사용 시기 (When to Use)#

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

  • 탭과 그 콘텐츠 패널을 한 덩어리(카드)로 함께 보여줄 때
  • 각 탭이 자체 콘텐츠를 소유하고 드래그로 순서를 바꿀 수 있어야 할 때

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

  • Tabs: 탭 바만 필요하고 콘텐츠 영역을 직접 배치할 때 (pill / underline)
  • Accordion: 모든 섹션을 한 페이지에서 펼치고 접을 때

기본 사용법 (Basic Usage)#

TabPane(
  tabs: [
    CoreTabItem(label: 'Account', content: accountPanel),
    CoreTabItem(label: 'Password', content: passwordPanel),
  ],
  selectedIndex: index,
  onChanged: (i) => setState(() => index = i),
)

Props / Parameters#

속성타입기본값설명
tabs List<CoreTabItem> 필수 탭 목록 (content 슬롯이 콘텐츠 패널에 표시됨)
selectedIndexint필수현재 포커스된 탭 인덱스
onChanged CoreValueChanged<int>? null 탭 변경 콜백
reorderable bool false 드래그로 탭 순서 변경
onReorder void Function(List<CoreTabItem>)? null 탭 순서 변경 콜백
leading List<Widget> [] 탭 바 앞쪽 위젯
trailing List<Widget> [] 탭 바 뒤쪽 위젯
tabPaneStyle CoreTabPaneStyle? null 인스턴스 스타일

스타일 시스템 (Style System)#

모든 chrome / dimensional 오버라이드는 CoreTabPaneStyle 단일 슬롯으로 흐릅니다. behaviour (tabs / selectedIndex / onChanged / reorderable) 는 위젯/컴포넌트 파라미터로 직접 전달합니다.

Resolve chain#

CoreTabPaneStyle.defaultX          // 디자인 시스템 기본값
  → CoreTabPaneTheme.style         // 프로젝트 공통
  → widget.tabPaneStyle            // 인스턴스별

CoreTabPaneStyle 필드#

CoreTabPaneStylebackgroundColor / borderColor / borderRadius / borderWidth / barHeight / tabPadding / tabSpacing / dragOpacity / contentTextStyle / clickableStyle(합성된 boxed-tab Clickable 로 raw-forward) 를 가집니다.

동작 스펙 (Behavior)#

탭 전환#

  • 탭 클릭 시 해당 콘텐츠 패널이 즉시 표시
  • onChanged 콜백으로 탭 전환 이벤트 감지

드래그 정렬#

  • reorderable: true 일 때 탭을 드래그하여 순서 변경
  • onReorder 콜백이 재정렬된 CoreTabItem 목록을 전달
  • 탭이 많아지면 탭 바가 가로 스크롤되며 가장자리에 페이드 효과 표시

접근성 (Accessibility)#

  • Web: role="tab", role="tablist", role="tabpanel", aria-selected 적용
  • 선택된 탭은 박스형 chrome 으로 시각 구분되며 콘텐츠 패널과 연결됩니다

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

TabPane 은 Flutter / Web 에서 동일한 named properties API 를 사용합니다. 파라미터 이름·구조·동작이 양쪽 동일합니다.

  • Tabs — 콘텐츠 패널 없이 탭 바만 (pill / underline)
  • Accordion — 펼침/접힘 섹션