Skip to main content

Snackbar

MD3 snackbar: a brief message at the bottom of the screen with an optional action. Wrap your app in SnackbarProvider and call useSnackbar().show() — the provider queues snackbars, times them out, places them and animates them in and out.

Showing snackbars​

show() takes a message string or options and returns a promise that resolves with why the snackbar closed: 'action', 'dismiss', 'timeout' or 'escapeKeyDown'. Snackbars show one at a time; later calls queue behind the current one.

// Once, near the root (inside ThemeProvider):
<SnackbarProvider>
<App />
</SnackbarProvider>

// Anywhere below it:
const { show } = useSnackbar()

const reason = await show({ message: 'Conversation archived', actionLabel: 'Undo' })
if (reason === 'action') restoreConversation()

Duration​

duration is 'short' (4s), 'long' (10s), 'indefinite', or a number of milliseconds. It defaults to 'indefinite' when there is an action (the snackbar stays until the user acts) and 'short' otherwise. The timer pauses while the snackbar is hovered or has focus inside it. Add withDismissAction to show a close button — recommended for indefinite snackbars. close() from useSnackbar() closes the current one.

show({ message: 'Connection lost', duration: 'long', withDismissAction: true })
show({ message: 'Saved', duration: 2500 })

Long action​

actionOnNewLine places the action on its own line below the message, end-aligned — for a long action label. It is opt-in; the layout is never chosen automatically.

Message sent
Conversation archived
Your draft could not be synced to the server.

The Snackbar component​

Snackbar is the presentational bar the provider renders. Use it directly only when you manage placement and timing yourself: action takes { label, onClick } (rendered as a text button) or a custom node, and onDismiss(event, reason) adds the dismiss icon button. Standalone, it is a polite live region (role="status"); override role / aria-live when a surrounding host already provides the live region.

<Snackbar
message="Conversation archived"
action={{ label: 'Undo', onClick: undo }}
onDismiss={(event, reason) => hide()}
/>

Accessibility​

  • The provider mounts one persistent polite live region (role="status") and only swaps its content, so screen readers announce every message.
  • Escape dismisses a snackbar while focus is inside it; when a focused snackbar closes, focus returns to where it was before.
  • Auto-dismiss pauses on hover and focus (WCAG 2.2.1). Snackbars with an action stay until the user acts by default.
  • Information in an auto-dismissing snackbar must also be available elsewhere in the UI; for snackbars with an action, consider a documented shortcut that moves focus to it.
  • Keep messages short and plain — no inline links or icons. Localize the dismiss button with dismissLabel.

Props​

SnackbarProvider​

PropTypeDefaultDescription
classNamestring—Class for the host (the fixed, bottom-centered placement container).
styleCSSProperties—Style for the host — e.g. raise it above a bottom navigation bar with `{ bottom: 80 }`.

Snackbar​

PropTypeDefaultDescription
actionReactNode | SnackbarAction—Optional single action — an `{ label, onClick }` text button (rendered as an inverse-primary `Button variant="text"`) or a custom node (m3: never a filled or elevated button).
actionOnNewLinebooleanfalsePlaces the action on its own line below the message, end-aligned — for a long action label (m3 "two lines with longer action"; Compose `actionOnNewLine`). Opt-in only; the layout is never chosen automatically.
dismissLabelstringDismissAccessible label of the dismiss icon button.
message *ReactNode—The message text (supporting text). Keep it short and plain — m3 advises against stylized text, inline links and icons in snackbars.
onDismiss((event: SyntheticEvent<HTMLElement, Event>, reason: SnackbarDismissReason) => void)—When provided, shows a trailing dismiss (close) icon button, and pressing Escape while focus is inside the snackbar also dismisses it. Receives the triggering event and the reason.

useSnackbar().show() options​

OptionTypeDefaultDescription
messageReactNode—The message text. Keep it short and plain.
actionLabelstring—Label of the single action button; activating it resolves 'action'.
withDismissActionbooleanfalseShow a trailing dismiss (close) icon button.
duration'short' | 'long' | 'indefinite' | number'indefinite' with an action, else 'short'How long the snackbar stays; pauses on hover / focus.
actionOnNewLinebooleanfalsePlace the action on its own line.
dismissLabelstring'Dismiss'Accessible label of the dismiss icon button.