Snackbar
Transient bar at the bottom of the screen, with an optional action.
Installation
npx axiom add snackbarpnpm dlx axiom add snackbaryarn dlx axiom add snackbarbun x axiom add snackbarAlso copies: portal.
Installs: react-native-reanimated, react-native-gesture-handler, react-native-safe-area-context, react-native-worklets.
The store, timer and swipe live in use-snackbar.ts. Colors come from snackbar.default.default.{background,foreground,action} in the component tokens.
Usage
Mount <SnackbarHost /> once at the root, then show snackbars from code.
import { SnackbarHost, snackbar } from "@/components/ui/snackbar";
snackbar.show({
message: "Message archived",
action: { label: "Undo", onPress: unarchive },
});API
snackbar.show(options)
| Option | Type | Default | Description |
|---|---|---|---|
message | string | — | One line, two at most. Describes what just happened. |
action | { label: string; onPress: () => void } | — | One text action, usually “Undo” or “Retry”. Pressing it also dismisses the snackbar. |
duration | 'short' | 'long' | 'indefinite' | number | 'short' | short is 4s, long 8s (default when there is an action). indefinite stays until dismissed or replaced. |
icon | IconName | — | Leading icon. Use sparingly: the message should be enough. |
onDismiss | (reason: 'timeout' | 'action' | 'swipe' | 'replaced' | 'dismiss') => void | — | Called when the snackbar leaves, with the reason. Commit a destructive action here if it wasn’t undone. |
Only one snackbar is visible. Calling show while one is on screen replaces it: the current one slides out with reason 'replaced', the new one slides in.
| Method | Description |
|---|---|
snackbar.dismiss() | Hides the current snackbar. |
SnackbarHost
| Prop | Type | Default | Description |
|---|---|---|---|
bottomOffset | number | 0 | Extra space on top of the default gap (bottom safe area + 16pt), to sit above a BottomTabBar or a ToolBar. |
swipeToDismiss | boolean | true | Swipe down, left or right to dismiss. |
The snackbar uses background.inverse and content.inverse, so it stands out in both light and dark. It is announced to screen readers when it appears, and its duration is extended when a screen reader is on.
Use cases
Undo a destructive action
Delete right away, offer Undo, and only commit on the server when the snackbar leaves without it.
function deleteTask(task: Task) {
hideLocally(task.id);
snackbar.show({
message: `"${task.title}" deleted`,
action: { label: "Undo", onPress: () => restoreLocally(task.id) },
onDismiss: (reason) => reason !== "action" && api.deleteTask(task.id),
});
}Retry after a network error
The action gives a way to try again without hunting for the button that failed.
sendMutation.mutate(message, {
onError: () =>
snackbar.show({
message: "Message not sent",
duration: "indefinite",
action: {
label: "Retry",
onPress: () => sendMutation.mutate(message),
},
}),
});Above a tab bar
bottomOffset keeps the snackbar above the navigation, so it never covers the tabs.
<SnackbarHost bottomOffset={tabBarHeight} />