Banner | CoUI

Banner

페이지 상단에 표시되는 알림 배너 컴포넌트

Banner#

페이지 상단에 중요한 정보, 경고, 오류 등을 표시하는 배너 컴포넌트입니다. CoBanner는 Flutter와 Web에서 동일한 named properties API를 제공하며, default/info/success/warning/destructive 5개 variant를 지원합니다.

Live Preview#

사용 시기 (When to Use)#

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

  • 페이지 전체에 영향을 미치는 시스템 상태 메시지를 표시할 때 (점검 공지, 서비스 알림)
  • 사용자가 취해야 할 중요한 액션을 안내할 때 (세션 만료 경고, 구독 만료 알림)
  • 사용자가 방금 완료한 작업의 결과를 페이지 상단에 지속적으로 표시할 때

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

  • Toast: 일시적으로 나타났다가 자동으로 사라지는 알림이 필요할 때
  • Alert: 특정 콘텐츠 영역 내에 인라인으로 표시하는 경고 메시지가 필요할 때
  • Dialog: 사용자의 즉각적인 응답이 필요한 중요한 알림에는 모달 다이얼로그 사용

기본 사용법 (Basic Usage)#

CoUI는 Flutter와 Web에서 동일한 API를 제공합니다. 아래 예제 코드는 양쪽 플랫폼에서 그대로 사용할 수 있습니다.

// 정보 배너
CoBanner.info(
  message: Text('시스템 점검이 예정되어 있습니다.'),
)

// 성공 배너 (해제 버튼 포함)
CoBanner.success(
  message: Text('저장이 완료되었습니다.'),
  onDismiss: handleDismiss,
)

// 경고 배너 (액션 포함)
CoBanner.warning(
  message: Text('세션이 곧 만료됩니다.'),
  description: Text('지금 연장하면 작업을 이어서 할 수 있습니다.'),
  action: CoButton(
    variant: CoreButtonVariant.outline,
    onPressed: handleExtendSession,
    child: Text('연장하기'),
  ),
  onDismiss: handleDismiss,
)

// 오류 배너
CoBanner.destructive(
  message: Text('요청을 처리하는 중 오류가 발생했습니다.'),
  onDismiss: handleDismiss,
)

Props / Parameters#

속성타입기본값설명
message Widget / Component 필수 배너에 표시할 메시지
description Widget? / Component? null 메시지 아래에 표시되는 선택적 보조 설명
variant CoreBannerVariant info 배너 변형 ( default_ , info , success , warning , destructive )
onDismiss VoidCallback? / CoreVoidCallback? null 닫기 버튼 클릭 핸들러. null이면 닫기 버튼 미표시
action Widget? / Component? null 배너 우측에 표시할 액션 위젯
showIcon bool true variant 별 기본 아이콘 표시 여부
bannerStyle CoreBannerStyle<Color>? / CoreBannerStyle<CoreColor>? null 인스턴스 스타일 (Style 시스템 참조)

스타일 시스템 (Style System)#

Banner 의 모든 chrome / dimensional / nested-slot 오버라이드는 CoreBannerStyle<Clr> 단일 슬롯으로 흐릅니다 (Epic #1302 원칙 6/7/8). 시맨틱 enum (variant) 과 behaviour (message / description / action / onDismiss / showIcon) 는 위젯 파라미터로 직접 전달합니다.

시맨틱 vs 스타일#

  • 시맨틱 enum / behaviour: 위젯/컴포넌트 파라미터로 직접 (variant, message, description, action, onDismiss, showIcon)
  • chrome / dimensional / 슬롯 스타일: CoreBannerStyle 한 곳으로 (backgroundColor / foregroundColor / borderColor / borderWidth / borderRadius / paddingH / paddingV / gap / titleStyle / descriptionStyle / iconStyle / actionButtonStyle / closeButtonStyle)

Resolve chain#

design system default for banner
  → CoreBannerTheme.style                  // 프로젝트 공통
  → parent component slot override
  → widget.bannerStyle                     // 인스턴스별

각 nested 슬롯 스타일 (titleStyle / descriptionStyle / iconStyle / actionButtonStyle / closeButtonStyle) 은 자기 컴포넌트의 자체 resolve chain 으로 다시 한 번 머지됩니다.

슬롯 매핑 (CoreBannerStyle 13 필드)#

필드타입 (Flutter)적용 영역
backgroundColor Color? 배너 배경 색 (variant 기본값 위에 오버라이드)
foregroundColorColor?메시지 / 설명 / 아이콘 전경 색
borderColorColor?좌측 액센트 보더 색
borderWidthdouble?보더 두께 (px)
borderRadiusdouble?모서리 반지름 (px)
paddingHdouble?좌/우 패딩 (px)
paddingVdouble?위/아래 패딩 (px)
gapdouble?아이콘 / 콘텐츠 / 액션 간격 (px)
titleStyle CoreTextStyle<Color>? 메시지 텍스트 스타일
descriptionStyle CoreTextStyle<Color>? 설명 텍스트 스타일
iconStyle CoreIconStyle<Color>? variant 아이콘 스타일
actionButtonStyle CoreButtonStyle<Color>? 액션 버튼 슬롯에 패스스루되는 chrome (호스트가 CoButton 을 주입한 경우 전달)
closeButtonStyle CoreButtonStyle<Color>? 닫기 버튼 chrome (현재 구현은 foregroundColor / labelStyle.color 만 적용; 완전 CoButton wrap 은 #1322 이월)

Migration — 옛 평면 chrome → 새 위치 매핑#

기존 CoreBannerTheme 의 평면 chrome (backgroundColor / borderColor / borderRadius) 은 호환을 위해 유지되지만, 새 코드는 bannerStyle 슬롯을 사용하세요:

기존 (legacy theme 필드)새 위치
CoreBannerTheme.backgroundColor bannerStyle.backgroundColor 또는 CoreBannerTheme.style.backgroundColor
CoreBannerTheme.borderColor bannerStyle.borderColor 또는 CoreBannerTheme.style.borderColor
CoreBannerTheme.borderRadius bannerStyle.borderRadius 또는 CoreBannerTheme.style.borderRadius
인스턴스 padding 오버라이드 (불가능)bannerStyle.paddingH / paddingV
인스턴스 메시지 텍스트 스타일 (불가능)bannerStyle.titleStyle
인스턴스 설명 텍스트 스타일 (불가능)bannerStyle.descriptionStyle
인스턴스 아이콘 사이즈/색 (불가능)bannerStyle.iconStyle

사용 예 (Flutter)#

CoBanner.warning(
  message: Text('세션이 곧 만료됩니다.'),
  description: Text('지금 연장하면 작업을 이어서 할 수 있습니다.'),
  bannerStyle: CoreBannerStyle(
    paddingH: 24,
    paddingV: 16,
    borderRadius: 12,
    titleStyle: CoreTextStyle(fontSize: 14, fontWeight: 600),
    descriptionStyle: CoreTextStyle(fontSize: 12),
    iconStyle: CoreIconStyle(size: 20),
  ),
  onDismiss: handleDismiss,
)

사용 예 (Web)#

CoBanner.warning(
  message: text('세션이 곧 만료됩니다.'),
  description: text('지금 연장하면 작업을 이어서 할 수 있습니다.'),
  bannerStyle: CoreBannerStyle<CoreColor>(
    paddingH: 24,
    paddingV: 16,
    borderRadius: 12,
  ),
  onDismiss: handleDismiss,
)

변형 (Variants)#

Info#

일반적인 정보 전달에 사용합니다.

CoBanner.info(
  message: Text('새로운 업데이트가 있습니다.'),
)

Success#

성공적인 작업 완료를 알릴 때 사용합니다.

CoBanner.success(
  message: Text('변경 사항이 저장되었습니다.'),
)

Warning#

사용자의 주의가 필요한 상황에 사용합니다.

CoBanner.warning(
  message: Text('구독이 7일 후 만료됩니다.'),
)

Destructive (Error)#

오류 또는 실패 상태를 알릴 때 사용합니다.

CoBanner.destructive(
  message: Text('네트워크 연결에 실패했습니다.'),
)

동작 스펙 (Behavior)#

인터랙션#

  • 닫기 버튼 클릭: onDismiss 콜백 실행. 배너 숨김 처리는 부모 위젯에서 상태로 관리
  • 액션 버튼 클릭: action 위젯에 정의된 콜백 실행
  • 호버: 닫기 버튼 opacity 상승

상태 전환#

  • 배너 표시: 슬라이드 다운 또는 페이드인 (부모에서 AnimatedSwitcher 사용 권장)
  • 배너 닫기: onDismiss 호출 후 부모에서 상태를 변경하여 제거

테마 오버라이드#

프로젝트 레벨에서 CoreComponentTheme.banner로 기본값을 재정의할 수 있습니다.

CoreComponentTheme(
  banner: CoreBannerTheme(
    backgroundColor: CoreColor(0xFFF8F9FA),
    borderColor: CoreColor(0xFF6366F1),
    borderRadius: 12.0,
    showIcon: true,
  ),
)

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

✅ Do#

중요도에 맞는 variant 사용

// 시스템 점검 공지: info
CoBanner.info(
  message: Text('2026-03-15 02:00~04:00 시스템 점검이 예정되어 있습니다.'),
)

// 보안 경고: warning
CoBanner.warning(
  message: Text('비밀번호를 90일 이상 변경하지 않았습니다.'),
  action: TextButton(
    onPressed: handleChangePassword,
    child: Text('변경하기'),
  ),
)

올바른 variant를 사용하면 사용자가 메시지의 중요도를 즉시 파악할 수 있습니다.


❌ Don't#

여러 배너를 동시에 표시 금지

// ❌ 여러 배너 동시 표시
Column(
  children: [
    CoBanner.info(message: Text('점검 예정')),
    CoBanner.success(message: Text('저장 완료')),
    CoBanner.warning(message: Text('세션 만료')),
  ],
)

여러 배너가 동시에 표시되면 사용자에게 압도적인 느낌을 주고 콘텐츠 영역을 지나치게 차지합니다. 가장 중요한 하나만 표시하세요.

✅ Do#

해제 가능한 배너에는 항상 onDismiss 제공

CoBanner.info(
  message: Text('새로운 기능이 추가되었습니다. 지금 확인해보세요!'),
  onDismiss: handleDismissBanner,
  action: TextButton(
    onPressed: handleLearnMore,
    child: Text('자세히 보기'),
  ),
)

사용자가 불필요한 배너를 닫을 수 있어야 콘텐츠에 집중할 수 있습니다.


❌ Don't#

destructive variant를 일반 정보 표시에 남용 금지

// ❌ 단순 안내에 destructive variant 사용
CoBanner.destructive(
  message: Text('이 기능은 프리미엄 회원 전용입니다.'),
)

destructive variant는 실제 오류 상황에만 사용해야 합니다. 남용하면 사용자가 진짜 오류를 놓칠 수 있습니다.

✅ Do#

액션이 필요한 배너에는 action 버튼을 추가하세요.

CoBanner.warning(
  message: Text('구독이 3일 후 만료됩니다.'),
  action: TextButton(
    onPressed: handleRenewSubscription,
    child: Text('갱신하기'),
  ),
  onDismiss: handleDismiss,
)

사용자가 즉각적인 조치를 취할 수 있도록 명확한 액션 버튼을 제공하면 전환율이 높아집니다.

접근성 (Accessibility)#

키보드 인터랙션#

동작
Tab배너 내 인터랙티브 요소(액션 버튼, 닫기 버튼)로 이동
Enter / Space포커스된 버튼 활성화
Escape닫기 버튼이 있는 경우 배너 닫기

스크린 리더#

  • Flutter: Semantics(container: true, label: 'Banner') 적용
  • Web: role="banner" 속성 자동 적용

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

CoBanner는 Flutter와 Web에서 동일한 named properties API를 사용합니다. 플랫폼별로 타입이 다른 부분만 차이가 있습니다.

항목FlutterWeb
message / description / action 타입 Widget Component
onDismiss 콜백 타입 VoidCallback? CoreVoidCallback?
배치 방식 Column 최상단 또는 Scaffold 내 삽입 페이지 상단 고정 (position: sticky)
애니메이션AnimatedSwitcher 등 Flutter 애니메이션CSS transition
  • Toast: 자동으로 사라지는 일시적 알림에 사용
  • Alert: 특정 섹션 내 인라인 메시지에 사용
  • Status: 시스템이나 사용자 상태 표시에 사용