Toast
Transient notification that stacks, auto-dismisses, and can be swiped to close.
Preview component
Basic
A button pushes an event, the LiveView responds with Fluxon.send_toast/3. No client state, no JS.
Semantic colors
Pass color: :info | :success | :warning | :danger to drive the surface tint and the leading icon. Omit color for the neutral default; danger toasts are announced assertively for screen readers.
Title and description
Pass description: to render secondary text below the title.
Custom dismiss timer
Override the toaster's default timer with dismiss_after: 10_000 (milliseconds) when the message needs more reading time. Hovering anywhere on the toaster pauses every running timer.
Persistent until dismissed
Pass dismiss_after: nil to keep the toast visible until it is closed manually, or until Fluxon.dismiss_toast/2 is called.
Non-dismissible
Set dismissible: false to hide the close button. The toast then disappears only on auto-dismiss or via Fluxon.dismiss_toast/2.
Hide the icon
Pass icon: false to suppress the leading color icon for a denser, text-only toast.
Link action
Use type: :link with :href, :navigate, or :patch to choose how the action navigates: plain anchor, cross-LiveView push, or same-LiveView patch.
Callback action
An action with type: :event pushes the named event back to the LiveView when clicked, then auto-dismisses the toast. The canonical pattern is a destructive action paired with an Undo affordance.
Multiple actions with variants
Pass actions: with a list of action maps. Each accepts a Button variant: so a primary action can sit next to a quieter secondary one.
Inline action layout
Each action's position: controls where it renders. The default is :below (stacked under the title). Pass position: :inline to place the button in the same row as the title. Pair with dismissible: false when the inline action is itself a meaningful close affordance, so the X doesn't crowd the row.
Dismiss-only action
For labeled acknowledgments ("Got it", "OK") that close the toast with no other side effect, use type: :dismiss. Pair it with dismissible: false so the X is hidden and the labeled button is the only way to close, otherwise you end up with two redundant dismiss controls.
Keep open after action
Action clicks dismiss the toast by default. Pass dismiss: false on an action to keep the toast visible after firing, for retry or multi-step flows.
Rich HEEx content
Pass content: with a HEEx fragment to replace the title and description with arbitrary markup (avatars, multi-line layouts, custom widgets). The first argument is still used as the toast's accessible label. send_toast/3 only.
Loading toast resolved to success
Fluxon.send_toast_loading/3 shows an indeterminate spinner and returns {socket, id}. After the async work completes, Fluxon.resolve_toast/4 swaps it for a final color and animates the transition.
Loading toast resolved to error
Same lifecycle, resolved with :danger and a description: explaining the failure.
Loading resolved with action
Resolutions accept the same options as send_toast/3, including action: and a longer dismiss_after: so the result stays on screen long enough to click through.
Multi-step progress
Call resolve_toast/4 repeatedly with :loading to update the same toast as work moves through phases, then resolve to a final color when done. One toast changes titles in place instead of stacking a flurry of separate notifications.
Custom progress bar
The built-in progress bar tracks the dismiss timer. For real progress (uploads, batched work) render your own bar inside :content and call resolve_toast/4 with :loading each tick. When the work finishes, resolve to :success with a link to the result.
Programmatic dismiss by id
Pass an explicit :id when sending the toast, then call Fluxon.dismiss_toast/2 with that id to close it later from anywhere in your code (background events, scheduled cleanup, etc.).
Client-side trigger
Fluxon.send_toast/2 returns a %JS{} command, so a toast can fire straight from phx-click with no server event. Ideal for purely UI feedback ("Copied!", "Saved", "Removed") where the action lives entirely in the browser. The payload is server-rendered at template time, so HEEx content and icons still work the same as the socket form.
Chain a toast with a server event
Compose Fluxon.send_toast/2 into an existing JS pipeline for optimistic feedback. The toast appears immediately while the server event flies in parallel; the server can then send a follow-up toast with the same id to confirm or override the outcome.
Dismiss a toast from a phx-click
Fluxon.dismiss_toast/1 returns a %JS{} command keyed to a toast id. Pair it with a server-shown persistent toast to give the user a way to clear it from anywhere on the page; the dismiss runs entirely in the browser, no round-trip needed.
Stack cap
The toaster caps the visible stack at max_toasts (default 5). When the cap is hit, the oldest toast animates out to make room.
Custom width
Pass any Tailwind width utility through the class attr to override the default max-w-sm, for example max-w-md, max-w-lg, or an arbitrary value like w-[420px].
Switch position at runtime
The position attr drives where the stack anchors. The toaster element opts out of LiveView patching (phx-update="ignore"), so swapping an assign will not re-render it. Drive position from a URL parameter and key the toaster element by position; LiveView then tears down the old node and mounts a fresh one.
Survives push_navigate
Fluxon.put_toast/3 rides on Phoenix flash, so the toast persists across push_navigate/2, controller redirects, and full-page reloads. Reach for it when the response navigates and the notification should follow.
Setup
Mount the toaster exactly once in your root layout and pass @flash. Available positions are top-right (default), top-left, top-center, bottom-right, bottom-left, and bottom-center. Top positions stack newer toasts above older ones; bottom positions stack newer below.
The toaster is already mounted in this site's layout. Click any preview above to see it surface a toast.