MD3
Expressive
MATERIAL DESIGN 3 EXPRESSIVE

Snackbar

Snackbars provide brief messages about app processes at the bottom of the screen.

Snackbars inform users of a process that an app has performed or will perform. They appear temporarily, towards the bottom of the screen. They shouldn't interrupt the user experience, and they don't require user input to disappear.

Introduction

The MD3 Expressive Snackbar is a lightweight notification component used for low-priority feedback. It provides a non-disruptive way to confirm actions (e.g., "Message sent") or inform about background processes. Built with a queuing system, it ensures that messages are delivered sequentially without overlapping.

Anatomy

  • Container: A dark surface (bg-m3-inverse-surface, text-m3-inverse-on-surface) with rounded corners (4dp) and Level 3 elevation shadow that floats at the bottom of the screen.
  • Message Text: A short string describing the event (text-sm leading-5 font-normal).
  • Action (Optional): A single text button with MD3 interactive state layers for the user to respond to the notification (e.g., "Undo").
  • Close Affordance (Optional): A standard icon button (IconButton with colorStyle="standard") to dismiss the snackbar immediately.

Variants

Basic Snackbar

A simple message that appears and automatically dismisses after a short duration.

Loading demo...

With Action

Includes a text button for a follow-up action. The showSnackbar function returns a promise that resolves to 'action-performed' when the action is clicked.

Loading demo...

With Dismiss Button

Includes a dedicated close (X) icon button to dismiss the notification on demand.

Loading demo...

Multi-line / New Line Action

For longer messages or labels, the action can be placed on a new line (Column layout) to maintain readability.

Loading demo...

Features

Queuing System

If multiple snackbars are triggered in rapid succession, the system automatically queues them, showing one at a time to avoid overwhelming the user.

Loading demo...

Automatic Dismissal

Snackbars are temporary and dismiss themselves after a delay (default 4 000 ms for short, 7 000 ms for long, or custom millisecond duration).

State Layers & Motion

Action buttons and dismiss icon buttons feature MD3 Expressive state layers (hover, focus, pressed) and spring physics animations powered by Framer Motion.

Usage

Setup via MD3ThemeProvider

The recommended setup is enabling snackbars globally in your root layout via MD3ThemeProvider:

import { MD3ThemeProvider } from "@bug-on/m3-expressive";

export function Root({ children }: { children: React.ReactNode }) {
  return (
    <MD3ThemeProvider enableSnackbar>
      {children}
    </MD3ThemeProvider>
  );
}

Alternative Setup via SnackbarProvider

For standalone apps or scoped sections without MD3ThemeProvider:

import { SnackbarProvider } from "@bug-on/m3-expressive";

export function App({ children }: { children: React.ReactNode }) {
  return (
    <SnackbarProvider>
      {children}
    </SnackbarProvider>
  );
}

Triggering a Snackbar

Use the useSnackbar hook to access the showSnackbar function.

import { Button, useSnackbar } from "@bug-on/m3-expressive";

export function MyComponent() {
  const { showSnackbar } = useSnackbar();

  const handleSave = async () => {
    const result = await showSnackbar({
      message: "Profile updated",
      actionLabel: "Undo",
      duration: "short",
    });

    if (result === "action-performed") {
      // Undo logic...
    }
  };

  return <Button onClick={handleSave}>Save</Button>;
}

Best Practices

Do

  • Keep messages short and direct.
  • Use snackbars for non-critical confirmation messages.
  • Provide an "Undo" action for destructive operations if possible.
  • Ensure the snackbar doesn't obscure important UI elements like FABs or Navigation Bars.

Don't

  • Don't use snackbars for critical errors that require immediate attention (use a Dialog instead).
  • Don't put more than one action in a snackbar.
  • Avoid using snackbars for long-lasting or permanent information.

Accessibility

  • Roles: Uses role="status" with aria-live="polite" and aria-atomic="true" to ensure screen readers announce the message without interrupting the current task.
  • Duration: Provides enough time for users to read the message. The "long" (7 000 ms) duration is recommended for snackbars with actions.
  • Interaction: The action button and close affordance are reachable and focusable via keyboard.
  • Reduced Motion: Respects prefers-reduced-motion with clean fade transitions instead of spatial slide/spring motion.

API Reference

useSnackbar

Hook providing access to the snackbar system from the nearest SnackbarProvider or MD3ThemeProvider.

const { showSnackbar } = useSnackbar();
PropertyTypeDescription
showSnackbar(visuals: SnackbarVisuals) => Promise<SnackbarResult>Triggers a snackbar and returns a promise resolving to 'action-performed' or 'dismissed'.

useSnackbarState

Low-level hook that manages the snackbar queue and mutex state.

const { current, showSnackbar, _dismiss } = useSnackbarState();
Return PropertyTypeDescription
currentSnackbarData | nullCurrently active snackbar data, or null when idle.
showSnackbar(visuals: SnackbarVisuals) => Promise<SnackbarResult>Enqueues and displays a snackbar.
_dismiss(result: SnackbarResult) => voidInternal callback to dismiss the active snackbar.

SnackbarVisuals

Visual configuration passed to showSnackbar().

PropTypeDefaultDescription
messagestringRequired. Main notification message text.
actionLabelstringLabel for the optional text action button.
withDismissActionbooleanfalseWhen true, renders a close (X) icon button.
actionOnNewLinebooleanfalseWhen true, renders the action button below the message (Column layout).
duration"short" | "long" | number"short"Auto-dismiss duration ("short" = 4 000 ms, "long" = 7 000 ms, or custom milliseconds).
classNamestringAdditional CSS className applied to the snackbar container.

SnackbarResult

Type representing the outcome of a snackbar instance.

type SnackbarResult = "action-performed" | "dismissed";

SnackbarHostProps

Props for the SnackbarHost component.

PropTypeDefaultDescription
stateUseSnackbarStateReturnRequired. State returned by useSnackbarState().
classNamestringAdditional CSS className applied to the fixed host container.

Tokens & Exports

ExportTypeDescription
SnackbarProviderComponentContext provider that wires SnackbarHost and exposes useSnackbar.
SnackbarHostComponentAnimatePresence container that renders active snackbars sequentially.
SnackbarComponentPure display component for a single snackbar instance.
SnackbarContextContextReact Context holding the { showSnackbar } function.
useSnackbarHookConsumer hook to trigger snackbars imperatively.
useSnackbarStateHookLow-level queue and state management hook.
SnackbarVisualsInterfaceVisual configuration options for a snackbar.
SnackbarDataInterfaceRuntime state data including id, visuals, and resolve callback.
SnackbarResultTypeUnion type "action-performed" | "dismissed".
SnackbarDurationTypeUnion type "short" | "long" | number.