Toast | CoUI

Toast

토스트 알림 컴포넌트

Toast#

사용자에게 간단한 피드백 메시지를 일시적으로 표시하는 토스트 컴포넌트입니다.

Live Preview#

사용 시기 (When to Use)#

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

  • 작업 결과(성공/실패)를 간단히 알릴 때
  • 되돌리기(undo) 액션을 제공할 때
  • 사용자 흐름을 방해하지 않는 비침입적 알림이 필요할 때

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

  • Dialog: 사용자 확인이 반드시 필요한 중요한 알림일 때
  • Alert / Banner: 페이지에 고정된 영구적 알림이 필요할 때
  • Tooltip: 특정 요소에 대한 설명이 필요할 때

기본 사용법 (Basic Usage)#

// 기본 토스트 카드
Toast(
  message: '저장되었습니다.',
  description: '변경사항이 성공적으로 저장되었습니다.',
  onDismiss: () {},
)

// destructive 변형
Toast(
  message: '오류가 발생했습니다.',
  description: '네트워크 연결을 확인해 주세요.',
  variant: CoreToastVariant.destructive,
  onDismiss: () {},
)

// showToast와 함께 사용
showToast(
  context: context,
  builder: (context, overlay) => Toast(
    message: '파일이 업로드되었습니다.',
    onDismiss: overlay.close,
  ),
)
// 기본 토스트 (default 변형)
Toast(
  message: '저장되었습니다.',
  description: '변경사항이 성공적으로 저장되었습니다.',
  onDismiss: handleDismiss,
)

// destructive 변형
Toast(
  message: '오류가 발생했습니다.',
  description: '네트워크 연결을 확인해 주세요.',
  variant: CoreToastVariant.destructive,
  onDismiss: handleDismiss,
)

스타일 시스템 — toastStyle (Epic #1302)#

Toast 의 panel chrome / 슬롯 미세 조정은 단일 toastStyle (CoreToastStyle) 으로 흐릅니다. 시맨틱 enum (variant) 은 위젯 파라미터.

Toast(
  message: '저장 완료',
  description: '변경사항이 적용되었습니다',
  variant: CoreToastVariant.destructive,
  onDismiss: handleDismiss,
  action: Button(
    variant: .ghost,
    onPressed: undo,
    child: Text('되돌리기'),
  ),
  toastStyle: CoreToastStyle(
    panelBackgroundColor: CoreColor.token(CoreColors.surface),
    panelBorderColor: CoreColor.token(CoreColors.outline),
    panelBorderRadius: CoreBorderRadius.all(12),
    panelPadding: CoreEdgeInsets.all(16),
    contentActionGapStyle: CoreGapStyle(size: 12),
    messageStyle: CoreTextStyle(
      fontSize: 14,
      fontWeight: CoreFontWeight.semiBold,
    ),
    descriptionStyle: CoreTextStyle(
      fontSize: 12,
      color: CoreColor.token(CoreColors.onSurfaceVariant),
    ),
    // actionButtonStyle 은 action 안의 Button 이 자동 적용 가능
    // (위처럼 variant 직접 주입 — Epic #1302 원칙 8 asChild)
  ),
)

CoreToastStyle 필드#

필드타입설명
panelBackgroundColor / panelBorderColor CoreColor? panel 배경 / 보더 색
panelBorderRadiusCoreBorderRadius?panel 보더 반경
panelPaddingCoreEdgeInsets?panel 내부 패딩
contentActionGapStyle CoreGapStyle? message+description 영역 ↔ action 슬롯 간격 (nested Gap 슬롯)
messageDescriptionGapStyle CoreGapStyle? message ↔ description 간격 (nested Gap 슬롯)
messageStyle CoreTextStyle? 메시지 (primary text) 스타일
descriptionStyle CoreTextStyle? 설명 (secondary text) 스타일
actionButtonStyle CoreButtonStyle? action 버튼 chrome 미세 조정 (variant 변경은 위젯 슬롯 주입)

asChild 패턴 — action 버튼 변경#

action 버튼의 시맨틱 (variant) 변경이 필요할 때는 action 슬롯에 직접 위젯을 주입합니다 (Epic #1302 원칙 8):

Toast(
  message: '...',
  action: Button(variant: .ghost, child: Text('되돌리기')),  // ← variant 직접
)

toastStyle.actionButtonStyle 은 chrome 미세 조정용 (paddingH / labelStyle 등).

Resolve chain#

design system default for variant
  → CoreToastTheme.style                       // 프로젝트 공통
  → CoreToastTheme.variantStyles[widget.variant]   // variant 별
  → 부모 컴포넌트 슬롯 오버라이드
  → widget.toastStyle                          // 인스턴스별

Props / Parameters#

속성타입기본값설명
messageString필수토스트 메시지
description String? null 보조 설명 텍스트
variant CoreToastVariant default_ 시각적 변형 (위젯 파라미터)
onDismiss VoidCallback? null 닫기 버튼 콜백 (null이면 닫기 버튼 없음)
actionWidget?null액션 위젯
toastStyle CoreToastStyle? null panel chrome / nested 슬롯 묶음

변형 (Variants)#

default_#

기본 토스트 스타일입니다. surface 배경에 onSurface 텍스트를 사용합니다.

Toast(
  message: 'Success',
  description: 'Your changes have been saved.',
  onDismiss: handleDismiss,
)

destructive#

오류/경고 토스트 스타일입니다. error 배경에 onError 텍스트를 사용합니다.

Toast(
  message: 'Error',
  description: 'Something went wrong.',
  variant: CoreToastVariant.destructive,
  onDismiss: handleDismiss,
)

Flutter 인프라 (ToastLayer)#

Flutter에서는 ToastLayershowToast()로 토스트 표시/스태킹/애니메이션을 관리합니다.

// 앱 최상단에 ToastLayer 배치
ToastLayer(
  maxStackedEntries: 3,
  expandMode: ExpandMode.expandOnHover,
  child: MyApp(),
)

// 토스트 표시
final overlay = showToast(
  context: context,
  builder: (context, overlay) => Toast(
    message: '처리 완료',
    onDismiss: overlay.close,
  ),
  location: ToastLocation.bottomRight,
  showDuration: Duration(seconds: 5),
);

// 프로그래밍 방식으로 닫기
overlay.close();

테마 커스터마이징#

CoreComponentTheme(
  toast: CoreToastTheme(
    style: CoreToastStyle(
      panelBorderRadius: CoreBorderRadius.all(12),
    ),
  ),
)

접근성 (Accessibility)#

스크린 리더#

  • Flutter: Semantics(liveRegion: true) 적용으로 스크린 리더에 자동 알림
  • Web: role="status", aria-live="polite" 적용으로 비침입적 알림

닫기 버튼#

  • onDismiss가 제공되면 aria-label="Close" 속성이 있는 닫기 버튼 렌더링

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

항목FlutterWeb
토스트 카드Toast (통일)Toast (통일)
인프라ToastLayer + showToast()외부 관리
스태킹내장 (hover 확장, 최대 개수)외부 관리
닫기 방식스와이프 + 클릭 + 프로그래밍닫기 버튼 클릭
  • Dialog: 사용자 확인이 필요한 모달 알림
  • Alert: 페이지에 고정된 알림
  • Banner: 페이지 상단의 전체 너비 알림