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초 자동 해제)
플레이그라운드#
컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.
import { ToastProvider, useToast } from '@wds/ui-web';
<ToastProvider><App /></ToastProvider>해부#
토스트는 훅·포털로만 떠서 인라인 렌더가 안 되므로, 실제 구조·토큰을 미러링한 정적 specimen 위에 실측을 핀으로 얹습니다.
저장 완료
변경사항이 반영되었습니다
- width
- 20rem (320px)
- padding
- 12 · 16px
space-3 · space-4 - gap
- 12px
space-3 - radius
- 14px
radius.lg - accent border
- 3px (좌측)
- icon
- 20px
icon.size-md - title / desc
- 14 / 12px
body-2 · caption
변형#
variant 4종(info·success·warning·error)은 좌측 3px accent 보더와 아이콘 잉크(*-text)로 구분됩니다 — 색은 이름이 아니라 실제 스와치 + 측정된 대비(아이콘 잉크 vs 표면, 라이트 기준)로 확인하세요.
동기화 시작
- accent
color.info- icon
color.info-text
저장 완료
- accent
color.success- icon
color.success-text
토큰 만료 임박
- accent
color.warning- icon
color.warning-text
저장 실패
- accent
color.error- icon
color.error-text
- info(기본) · success —
role="status"로 조용히(polite) 낭독 - warning · error —
role="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 | 타입 | 기본값 | 설명 |
|---|---|---|---|
children | ReactNode | — | 앱 트리 — Provider 하위에서만 useToast 사용 가능 |
closeLabel | string | '닫기' | 닫기 버튼 aria-label |
useToast().toast(options)#
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
title | string | — | 토스트 제목 (필수) |
description | string | — | 보조 설명 — 미제공 시 영역 미렌더 |
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-visible2px 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/pressed | color.surface-hover / color.surface-pressed |
| 모션 | duration.normal + ease.emphasized-decelerate(입장) / ease.standard(퇴장) |