ComponentsP3 본문

Toast

전역 알림 스택 — ToastProvider + useToast 3분할 구조. 5초 자동 해제에 hover 일시정지, error/warning은 role="alert"로 즉시 낭독됩니다.

마지막 업데이트 2026-06-11

한눈에#

발사는 훅 호출입니다 — 트리 상단에 ToastProvider를 두고, 클라이언트 컴포넌트에서 useToast()로 발사합니다. 아래 버튼으로 각 variant를 직접 쏴서 우하단 스택을 확인하세요.

  • 전역 스택
  • useToast 훅
  • 5초 자동 해제
  • hover 일시정지

우하단 z.toast 레이어에 세로로 쌓이고, hover하면 남은 시간이 보존됩니다

import { ToastProvider, useToast } from '@wds/ui-web';

function SaveButton() {
  const { toast } = useToast();
  return (
    <Button onClick={() => toast({ title: '저장 완료', variant: 'success' })}>
      저장
    </Button>
  );
}

// 앱 루트
<ToastProvider>
  <App />
</ToastProvider>;

사용 시점#

작업 결과처럼 흘려보내도 되는 일시 피드백이면 Toast — 머물러야 하거나 차단이 필요하면 다른 컴포넌트입니다.

쓴다

저장 완료처럼 흐름을 막지 않고 지나가는 일시 피드백(5초 자동 해제)

대신 Alert

폼 오류 요약·페이지 공지처럼 머물러야 할 인라인 배너

대신 Modal

결제 확인·삭제 경고처럼 반드시 읽고 확인/차단해야 할 때

플레이그라운드#

컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.

import { ToastProvider, useToast } from '@wds/ui-web';

<ToastProvider><App /></ToastProvider>

해부#

토스트는 훅·포털로만 떠서 인라인 렌더가 안 되므로, 실제 구조·토큰을 미러링한 정적 specimen 위에 실측을 핀으로 얹습니다.

success 변형 — 실 토큰 미러링 specimen에 실측 핀

저장 완료

변경사항이 반영되었습니다

width
20rem (320px)
padding
12 · 16pxspace-3 · space-4
gap
12pxspace-3
radius
14pxradius.lg
accent border
3px (좌측)
icon
20pxicon.size-md
title / desc
14 / 12pxbody-2 · caption

변형#

variant 4종(info·success·warning·error)은 좌측 3px accent 보더와 아이콘 잉크(*-text)로 구분됩니다 — 색은 이름이 아니라 실제 스와치 + 측정된 대비(아이콘 잉크 vs 표면, 라이트 기준)로 확인하세요.

동기화 시작

info
accent
color.info
icon
color.info-text
AA · 6.7:1

저장 완료

success
accent
color.success
icon
color.success-text
AA · 5.0:1

토큰 만료 임박

warning
accent
color.warning
icon
color.warning-text
AA · 5.0:1

저장 실패

error
accent
color.error
icon
color.error-text
AA · 6.5:1
  • info(기본) · successrole="status"로 조용히(polite) 낭독
  • warning · errorrole="alert"로 즉시(assertive) 낭독

accent 보더는 색 단독에 의존하지 않는 보조 신호이고(의미는 아이콘 + 제목이 전달), 아이콘 잉크(*-text)는 AA 4.5:1 이상을 보장합니다(DD-6). 다크 테마에서도 네 변형 모두 AA를 유지합니다.

크기#

size prop이 없습니다 — 폭 20rem 고정(좁은 화면에서는 뷰포트에 맞게 축소), 우하단 z.toast 레이어에 세로로 쌓입니다.

상태#

  • 자동 해제TOAST_AUTO_DISMISS_MS(5초) 후 퇴장
  • hover 일시정지 — 마우스를 올리면 남은 시간이 보존되고, 이탈 시 재개됩니다
  • 닫기 버튼 — 즉시 해제 (closeLabel, 기본 '닫기')
  • 입·퇴장 모션 — opacity/transform 250ms, prefers-reduced-motion에서는 없음

Props#

ToastProvider#

Prop타입기본값설명
childrenReactNode앱 트리 — Provider 하위에서만 useToast 사용 가능
closeLabelstring'닫기'닫기 버튼 aria-label

useToast().toast(options)#

Prop타입기본값설명
titlestring토스트 제목 (필수)
descriptionstring보조 설명 — 미제공 시 영역 미렌더
variant'info' | 'success' | 'warning' | 'error''info'의미 색 + 라이브 리전 등급 결정

useToast()ToastProvider 바깥에서 호출하면 명시적 에러를 던집니다.

접근성#

  • error/warning은 role="alert"(assertive), info/success는 role="status"(polite) — 라이브 리전에는 상태 텍스트만 담습니다(WCAG 4.1.3)
  • hover 일시정지로 읽을 시간을 연장할 수 있습니다 — 자동 해제 단독에 의존하지 않습니다
  • 닫기 버튼은 시각 32px + 44px 히트 영역, :focus-visible 2px primary 링
  • 아이콘은 장식(aria-hidden) — 의미는 variant 색 + 제목 텍스트가 전달합니다
  • prefers-reduced-motion: reduce에서 입·퇴장 애니메이션이 제거됩니다

토큰#

component 토큰 없이 semantic을 직접 소비합니다(신설 기준 §4 미충족).

속성토큰
카드color.surface-raised · color.border · radius.lg · shadow.lg
스택z.toast · space.2/4
변형 보더color.info/success/warning/error (좌측 3px)
아이콘 잉크color.*-text (AA 보장 잉크)
제목/설명color.text + font-weight.semibold / color.text-muted + font-size.caption
닫기 hover/pressedcolor.surface-hover / color.surface-pressed
모션duration.normal + ease.emphasized-decelerate(입장) / ease.standard(퇴장)

관련#