Snackbar
작업 결과나 짧은 상태 메시지를 일시적으로 전달하는 Next.js Client Component입니다.
기본
info · success · warning · danger 의미 색상으로 짧은 피드백을 전달합니다.
위치 · 여러 개 동작 테스트
8개 위치는 본문이 아닌 브라우저 뷰포트를 기준으로 계산됩니다. 이 데모는 openOnLoad 옵션으로 처음 로드할 때 하단 가운데 Snackbar를 호출하며, 같은 위치에 여러 개가 생성되면 독립적으로 쌓입니다.
간단한 메시지
showIcon을 끄고 children으로 메시지를 전달할 수 있습니다.
형태
기본형은 radius-md를 사용하고, round 유형은 Snackbar 높이 비율에 맞춘 캡슐형 모서리와 크기별 가로 패딩을 적용합니다.
호출 · 닫기 효과
fade는 제자리에서 투명도를 전환하고, slide는 상단·하단·중간 좌우 위치에 따라 가장 가까운 브라우저 가장자리 방향으로 호출·퇴장합니다. none은 즉시 표시하고 닫습니다.
크기
sm · md · lg 세 가지 크기를 제공합니다.
액션
action 영역에 실행 취소 등 하나의 명확한 후속 동작을 배치합니다.
닫기 가능
닫기 버튼은 onClose에 close 사유와 클릭 이벤트를 전달합니다.
자동 닫기
duration을 밀리초로 지정하면 시간이 지난 뒤 onClose에 timeout 사유를 전달합니다. 호버하거나 내부 요소에 포커스하면 남은 시간이 일시정지됩니다.
접근성
Snackbar는 포커스를 강제로 이동하지 않고 라이브 영역으로 상태 변화를 전달합니다.
- 일반적인 작업 결과는
role="status"로 정중하게 알리고, 즉시 확인해야 하는 오류에만role="alert"를 사용합니다. - 자동 닫기는 기본적으로 비활성화되어 있습니다. 사용하는 경우에도 내용을 읽고 액션을 수행할 충분한 시간을 제공하세요.
- 호버 또는 Snackbar 내부 포커스 중에는 자동 닫기 타이머가 멈춥니다. 닫기 가능한 Snackbar는 내부 포커스 상태에서 Esc로도 닫을 수 있습니다.
- 운영체제에서 모션 감소를 설정한 경우 Fade·Slide 시간을 최소화해 움직임을 줄입니다.
- 아이콘은 장식 요소로 숨겨지므로 상태를 색상이나 아이콘에만 의존하지 말고 메시지 텍스트로 명확하게 설명하세요.
- 액션은 하나의 짧고 명확한 동작으로 제공하고, 닫기 버튼에는 구체적인 closeLabel을 사용하세요.
API · Props
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
color | 'info' | 'success' | 'warning' | 'danger' | info | 의미 색상. danger는 color_error |
message | ReactNode | — | 메시지. children이 있으면 대체됨 |
closable | boolean | false | 닫기 버튼과 내부 포커스 상태의 Escape 닫기 지원 |
closeLabel | string | 알림 닫기 | 닫기 버튼의 접근성 라벨 |
showIcon | boolean | true | 의미 색상에 대응하는 기본 아이콘 표시 |
round | boolean | false | 높이 비율에 맞춘 캡슐형 모서리와 가로 패딩 적용 |
size | 'sm' | 'md' | 'lg' | md | snackbar_sm · snackbar_lg |
duration | number | 0 | 자동 닫기 시간(ms). 0이면 유지하며, 호버·내부 포커스 중에는 타이머 일시정지 |
motion | 'fade' | 'slide' | 'none' | fade | 호출·닫기 효과. slide는 placement 방향을 따름 |
placement | SnackbarPlacement | 상위 Region 값 | Region 없이 사용하거나 Slide 방향을 직접 재정의할 때 지정 |
role | string | status | status는 polite, alert는 assertive 라이브 영역으로 설정 |
icon | ReactNode | — | 기본 아이콘을 대체하는 콘텐츠 |
action | ReactNode | ({ close }) => ReactNode | — | 후속 동작. render 함수의 close로 퇴장 효과 실행 |
className | string | — | snackbar 루트에 추가 클래스 |
ripple | boolean | true | 클릭 파장(ripple). 닫기·트리거 버튼에 적용 · true 활성 · false 비활성 |
API · SnackbarRegion
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
placement | 'top-start' | 'top-center' | 'top-end' | 'middle-start' | 'middle-end' | 'bottom-start' | 'bottom-center' | 'bottom-end' | bottom-center | 고정 위치. start와 end는 RTL에서도 논리 방향을 따름 |
label | string | — | Snackbar 영역의 접근성 라벨 |
children | ReactNode | — | 같은 위치에 세로로 쌓을 Snackbar 목록 |
className | string | — | snackbar_region에 추가 클래스 |
API · Children
| Children | 설명 |
|---|---|
children | 메시지 콘텐츠 (message prop 대체) |
icon | 커스텀 아이콘 |
action | 버튼·링크 등 후속 동작 |
API · Events
| 이벤트 | 설명 |
|---|---|
onClose(reason, event) | 퇴장 효과 후 호출. reason은 'close' · 'action' · 'timeout' |
클래스 · 속성
| 클래스 | 설명 |
|---|---|
snackbar | Snackbar 루트 |
snackbar_sm · snackbar_lg | 크기 변형 |
snackbar_round | 높이 비율에 맞춘 캡슐형 모서리 |
snackbar_motion-fade · snackbar_motion-slide | 호출·닫기 모션 유형 |
snackbar_placement-{placement} | Slide 진입·퇴장 방향 |
is-entering · is-open · is-leaving | Snackbar 모션 생명주기 상태 |
snackbar_icon-wrap · snackbar_icon | 아이콘 영역 |
snackbar_message | 메시지 영역 |
snackbar_action · snackbar_close | 액션·닫기 영역 |
snackbar_region | 고정 위치와 다중 Snackbar 스택 컨테이너 |
snackbar_region-{placement} | 상단·중간·하단의 8개 위치 변형 |
color_info · color_success · color_warning · color_error | 의미 색상 |
aria-live · aria-atomic · aria-relevant | 메시지 전체를 스크린 리더에 알리는 라이브 영역 속성 |
data-ripple | 클릭 파장 활성. data-ripple="surface"는 절대 위치 보조 버튼용 |
data-ripple="false" | 해당 요소 ripple 비활성 |
data-no-ripple | 하위 전체 ripple 비활성 |
디자인 토큰
| 토큰 | 기본값 | 설명 |
|---|---|---|
--color-snackbar-info-bg · --color-snackbar-success-bg | 테마별 불투명 색상 | 정보·성공 Snackbar 불투명 배경 |
--color-snackbar-warning-bg · --color-snackbar-error-bg | 테마별 불투명 색상 | 경고·오류 Snackbar 불투명 배경 |
--color-snackbar-*-border | 테마별 불투명 색상 | 의미 색상별 불투명 테두리 |
--snackbar-min-width · --snackbar-max-width | 18rem · 36rem | 기본 최소·최대 너비 |
--snackbar-padding-y · --snackbar-padding-x | var(--space-sm) · var(--space-md) | 기본 패딩 |
--snackbar-gap · --snackbar-action-gap | var(--space-sm) | 콘텐츠·액션 간격 |
--snackbar-font-size · --snackbar-line-height | var(--text-size-base) · 1.5 | 기본 타이포 |
--snackbar-icon-size · --snackbar-close-size | 1.25rem · 2rem | 아이콘·닫기 버튼 크기 |
--snackbar-round-padding-x | var(--space-lg) | 기본 round 유형 가로 패딩 |
--snackbar-round-padding-x-sm · --snackbar-round-padding-x-lg | var(--space-md) · var(--space-xl) | sm·lg round 유형 가로 패딩 |
--snackbar-motion-duration · --snackbar-motion-distance | 200ms · 1rem | Fade·Slide 시간과 이동 거리 |
--snackbar-motion-easing | cubic-bezier(0.2, 0, 0, 1) | 호출·닫기 가속 곡선 |
--snackbar-region-offset · --snackbar-region-gap | var(--space-md) · var(--space-sm) | 화면 가장자리 간격·Snackbar 사이 간격 |
--snackbar-region-inset-block-start · --snackbar-region-inset-block-end | var(--snackbar-region-offset) | 상단·하단 안전 영역 |
--snackbar-region-inset-inline-start · --snackbar-region-inset-inline-end | var(--snackbar-region-offset) | 좌측·우측 안전 영역 |
--snackbar-region-z-index | 1200 | 고정 Snackbar 스택 레이어 |
--snackbar-padding-y-sm · --snackbar-padding-x-sm · --snackbar-font-size-sm | var(--space-xs) · var(--space-sm) · var(--text-size-sm) | sm 크기 |
--snackbar-padding-y-lg · --snackbar-padding-x-lg · --snackbar-font-size-lg | var(--space-md) · var(--space-lg) · var(--text-size-lg) | lg 크기 |