Toast
Toast와 useToast usage를 기준으로 non-modal feedback UI의 옵션, stacking, accessibility 규칙을 정리한 가이드 페이지입니다.
Toast
Toast는 modal popup과 별도로 관리되는 전역 feedback UI입니다. 현재 화면을 막지 않고 짧은 상태 변화를 전달하며, 여러 개가 동시에 열리면 화면 하단에서 위로 차곡차곡 쌓입니다.
message | tone | duration | id | onOpenComplete | onCloseComplete | className
ReactNode | ToastTone | number | string | (() => void) | (() => void) | string- `message`는 toast에 표시할 실제 안내 문구이고, string뿐 아니라 ReactNode도 그대로 넣을 수 있습니다.
- `tone`은 현재 `default | error` 두 가지를 지원하고, error는 더 강한 색과 role="alert"로 동작합니다.
- `duration`은 자동 닫힘 시간(ms)이고, `0` 이하로 주면 자동으로 닫히지 않습니다.
- `id`를 지정하면 특정 toast만 선택적으로 닫을 수 있고, `onOpenComplete` / `onCloseComplete`는 애니메이션 완료 시점 콜백입니다.
아직 실행된 callback이 없습니다.
useToast()
{ open: (options) => string; close: (id?: string) => void; closeAll: () => void; toasts: Array<{ id: string; status: "open" | "closing"; tone: "default" | "error" }>; }- `useToast()`는 modal popup처럼 component를 등록하지 않고, 옵션 객체만 넘겨서 가벼운 feedback 메시지를 전역 stack에 추가합니다.
- `open()`은 생성된 id를 반환하고, `close(id?)`는 특정 toast 또는 마지막 toast를 닫습니다.
- 여러 toast가 열린 상태에서는 `closeAll()`로 현재 열린 toast 전체를 closing 상태로 바꿔서 한 번에 정리합니다.
const toast = useToast();
toast.open({
id: "profile-saved-toast",
message: "프로필이 저장되었습니다.",
tone: "default",
duration: 2400,
});useToastStack()
Array<{ id: string; status: "open" | "closing"; tone: "default" | "error" }>- 현재 열린 toast stack을 그대로 조회할 수 있어서, 자동 닫힘과 수동 닫힘이 섞인 상태도 바로 확인할 수 있습니다.
- ToastHost는 이 stack 순서대로 렌더하고, CSS column 방향을 이용해 화면 하단에서 위로 쌓이게 처리합니다.
열린 toast가 없습니다.
Toast 기본 규칙
non-modal | auto dismiss | stack upward | no focus steal- Toast는 Alert/Confirm처럼 사용자의 응답을 기다리는 modal이 아니라, 현재 작업을 끊지 않고 짧게 피드백만 전달하는 non-modal UI입니다.
- backdrop, focus trap, `Escape` 닫기 같은 modal 동작은 없고, 기본적으로는 지정한 시간 뒤 자동으로 사라집니다.
- 여러 개가 동시에 열리면 화면 하단 기준으로 위로 쌓이고, 각각 자신의 duration을 기준으로 독립적으로 닫힙니다.
- `tone = default`
- `duration = 2400`
- portal root: `#toast-root`
- stack direction: bottom to top
- focus 이동 없음 / background inert 없음
접근성 규칙
tone="default" => role="status", tone="error" => role="alert"- 기본 tone은 role="status"와 aria-live="polite"로 동작해서 현재 작업 흐름을 방해하지 않는 보조 알림으로 읽힙니다.
- error tone은 role="alert"와 aria-live="assertive"로 바뀌어서 실패나 주의 메시지를 더 빠르게 전달합니다.
- toast는 포커스를 가져오지 않기 때문에, 바로 확인이나 선택이 필요한 내용은 Toast보다 Alert/Confirm이 더 적합합니다.
사용자의 현재 흐름을 유지하면서 짧게 안내할 때 적합합니다.
즉시 다시 시도하거나 상태를 확인해야 하는 실패 피드백에 적합합니다.
Toast options 한눈에 보기
useToast().open()에 넘기는 ToastOpenOptions와 내부 runtime props 차이를 정리했습니다.
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
message | React.ReactNode | - | Required | Toast에 표시할 실제 안내 문구입니다. string뿐 아니라 ReactNode도 그대로 넣을 수 있습니다. |
tone | "default" | "error" | "default" | Optional | default는 일반 상태 안내, error는 더 강한 시각 톤과 `role="alert"`를 사용합니다. |
duration | number | 2400 | Optional | 자동 닫힘 시간(ms)입니다. 0 이하로 주면 자동으로 닫히지 않고 수동 close가 필요합니다. |
id | string | auto generated id | Optional | 특정 toast를 직접 추적하거나 close(id) 대상으로 삼고 싶을 때 사용합니다. |
onOpenComplete | () => void | undefined | Optional | 진입 애니메이션이 끝난 뒤 1회 실행됩니다. |
onCloseComplete | () => void | undefined | Optional | 퇴장 애니메이션이 끝나고 ToastHost가 인스턴스를 제거한 뒤 실행됩니다. |
className | string | undefined | Optional | Toast 루트 스타일 확장용 클래스입니다. |
ToastOpenOptions입니다. 내부 ToastProps의 open, onRequestClose, onExited는 ToastHost가 주입합니다. 반대로 onCloseComplete는 host 단계에서 소비되는 hook-side 옵션입니다.Toast hook API 한눈에 보기
전역 Toast stack 제어와 상태 조회에 사용하는 hook API를 표로 정리했습니다.
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
useToast().open | (options: ToastOpenOptions) => string | - | Required | 새 Toast를 전역 store stack에 추가하고 생성된 id를 반환합니다. |
useToast().close | (id?: string) => void | - | Required | id를 주면 해당 Toast를 닫고, 생략하면 현재 stack의 마지막 Toast를 닫습니다. |
useToast().closeAll | () => void | - | Required | 현재 열린 Toast 전체를 closing 상태로 전환해 한 번에 정리합니다. |
useToast().toasts | ToastSnapshot[] | - | Required | 현재 toast stack snapshot입니다. id, status, tone만 담은 가벼운 조회용 배열입니다. |
useToastStack() | () => ToastSnapshot[] | - | Required | store snapshot만 필요할 때 직접 사용할 수 있는 selector hook입니다. useToast().toasts와 같은 구조를 반환합니다. |
useToast()는 modal popup처럼 component 등록 없이 옵션 객체만 넘겨서 feedback 메시지를 stack에 추가합니다. 실제 렌더링은 앱 루트의 ToastHost가 #toast-root에 portal로 처리합니다.