Floating bottom action bar for bulk-selection feedback.
Appears at the bottom-center of the screen when items are selected, showing a count/message and action buttons (assign, delete, archive…). Common in Gmail, Notion, Figma, Linear.
Distinct from Toast (which is a passive notification). The Snackbar is
explicitly triggered by selection state and contains interactive actions.
Visibility is controlled server-side via the :visible attr — pair it
with a LiveView assign to show/hide on selection changes.
Zero JavaScript — visibility via :if.
Examples
<.snackbar visible={length(@selected) > 0}>
<:label>{length(@selected)} contacts selected</:label>
<:actions>
<.button size="sm" phx-click="assign_selected">Assign</.button>
<.button size="sm" variant="destructive" phx-click="delete_selected">Delete</.button>
</:actions>
</.snackbar>
<%!-- With icon --%>
<.snackbar visible={@selection_active}>
<:icon><.avatar size="sm" src={@current_user.avatar} /></:icon>
<:label>{@selected_count} items</:label>
<:actions><.button size="sm">Move</.button></:actions>
</.snackbar>
Summary
Functions
Renders a floating bottom action bar for bulk-selection feedback.
Functions
Renders a floating bottom action bar for bulk-selection feedback.
The bar slides up from the bottom center of the viewport using phx-mounted
and phx-remove JS transitions (no JavaScript hook needed). Visibility is
driven by the visible attribute — pair it with a LiveView assign to
react to selection changes.
The bar layout (left to right):
- Icon (optional
:iconslot) — avatar or custom icon - Label (required
:labelslot) — short message like "3 items selected" - Actions (optional
:actionsslot) — buttons on the right
The bar uses role="status" and aria-live="polite" so screen readers
announce the count change each time it appears or the count updates.
Integration with LiveView selection state
# LiveView handle_event
def handle_event("toggle_select", %{"id" => id}, socket) do
selected = toggle_id(socket.assigns.selected, id)
{:noreply, assign(socket, selected: selected)}
endExamples
<%!-- Contact table with bulk actions --%>
<.snackbar visible={length(@selected_ids) > 0}>
<:label>{length(@selected_ids)} contacts selected</:label>
<:actions>
<.button size={:sm} phx-click="assign_selected">Assign</.button>
<.button size={:sm} variant={:destructive} phx-click="delete_selected">Delete</.button>
</:actions>
</.snackbar>
<%!-- File manager with move/copy/delete --%>
<.snackbar visible={@selection_active}>
<:icon><.icon name="file" class="text-muted-foreground" /></:icon>
<:label>{@selected_count} items</:label>
<:actions>
<.button size={:sm} variant={:outline} phx-click="move_files">Move</.button>
<.button size={:sm} variant={:outline} phx-click="copy_files">Copy</.button>
<.button size={:sm} variant={:destructive} phx-click="delete_files">Delete</.button>
</:actions>
</.snackbar>Attributes
visible(:boolean) - Whenfalse, the snackbar is not rendered. Defaults totrue.class(:string) - Additional CSS classes for the root element. Defaults tonil.- Global attributes are accepted. HTML attributes forwarded to the root
<div>element.
Slots
icon- Optional icon or avatar on the left side.label(required) - Primary message text (e.g. '3 items selected').actions- Action buttons or links on the right side.