Toasts & Notifications#

bootstack has three transient message surfaces, each for a distinct job:

  • bs.toast() — a passive message that fades on its own, in a screen corner.

  • bs.Notification — a persistent corner message the user closes.

  • bs.Snackbar — an in-app message with a single action, at the window’s bottom edge.

They share one look (a compact card with an icon, message, and severity color) but differ in where they sit, how long they stay, and whether they ask for a response. Pick by the job, not the appearance.

Choosing a surface#

Surface

Use it for

Lifetime

Anchored to

Action

toast()

“FYI” that needs no response (Saved, Copied)

Auto-dismiss

A monitor corner

None

Notification

News that should wait to be seen (Backup finished)

Until closed

A monitor corner

Close only

Snackbar

Feedback on an action just taken, maybe reversible

Auto-dismiss

The window’s bottom

One (Undo)

A rule of thumb: reach for toast() first. Upgrade to Notification when the message must persist, and to Snackbar when it offers a single response. Anything that blocks the user until answered is a dialog (Dialogs & Alerts), not a message.

Toast#

bs.toast() shows a message and returns immediately — it is fire-and-forget. It floats in a corner of the monitor the app window is on, stacks under any toasts already there, and fades after duration. There is no close button: a toast is passive by definition.

At its simplest a toast is just its message on one line. The icon and the title are both optional — add an icon to lead the message, or a title for a two-line card:

bs.toast("Your changes were saved.")                          # message only
bs.toast("Battery at 12%.", icon="battery-half", accent="warning")  # icon + message
bs.toast("Could not reach the server.", title="Sync failed",  # title + message
         accent="danger")
A passive toast in a corner — light theme A passive toast in a corner — dark theme

The accent colors the icon and text (in a readable, dark-tinted shade) and gives the card a soft tint; omit it for a neutral toast. corner= overrides the default placement (bottom-right, top-right on Linux):

bs.toast("Pinned to the top-left.", corner="top-left", duration=6000)

Notification#

bs.Notification is the persistent sibling: same corner, same stacking, but it does not auto-dismiss. It carries a close button and stays until the user dismisses it or your code does. Build it, then show() — keep the handle if you want to dismiss() it later (e.g. when a job it announced is superseded). The title is the headline:

note = bs.Notification(
    "Backup complete",
    message="3.2 GB uploaded to the cloud.",
    detail="just now",
    icon="cloud-check",
    accent="success",
).show()

# later, when it no longer applies
note.dismiss()
A persistent notification with a close button — light theme A persistent notification with a close button — dark theme

A notification is message-only — it informs, it does not ask. If you need the user to do something, that is a snackbar action or a dialog.

Snackbar#

bs.Snackbar belongs to the app, not the screen: it sits at the bottom edge of the window and moves with it. It is for brief feedback on something that just happened, optionally with a single way to respond — the classic “Message archived. [Undo]”. Only one snackbar shows at a time; a new one replaces it. Use the bs.snackbar() verb for the common one-liner, or the class when you want to dismiss() it yourself:

bs.snackbar("Conversation archived.", action="Undo", on_action=restore)
bs.snackbar("Copied to clipboard.")                       # no action
A snackbar with an Undo action at the window bottom — light theme A snackbar with an Undo action at the window bottom — dark theme

The action fires on_action and then dismisses. Unlike a toast, a snackbar’s surface stays neutral — severity coloring is the corner surfaces’ job; the accent here only tints the action button. align= moves it along the bottom edge ('left', 'center', or 'right').

Reacting to dismissal#

All three take an on_dismiss callback, fired with no arguments whenever the message goes away — by timeout, the close button, the snackbar action, or a manual dismiss():

bs.toast("Synced.", on_dismiss=lambda: print("gone"))

Widget sizing#

All widgets accept self-placement kwargs via **kwargs. The parent container determines which options apply — stack-based parents use stack kwargs, grid-based parents use grid kwargs. Unrecognised keys are silently ignored.

Stack#

Used inside VStack, HStack, App, and other stack containers.

fill

Fill direction: 'x', 'y', 'both', or 'none'.

expand

Grow to consume extra space in the parent. True or False.

anchor

Alignment when the widget does not fill the available slot: 'n', 's', 'e', 'w', 'center', 'nw', etc.

margin

External spacing in pixels. Accepts an integer (equal on all sides), a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing (left and right). Accepts an integer or a 2-tuple (left, right) for asymmetric spacing. Overrides the horizontal component of margin=.

margin_y

Vertical external spacing (top and bottom). Accepts an integer or a 2-tuple (top, bottom) for asymmetric spacing. Overrides the vertical component of margin=.

Grid#

Used inside a Grid container.

row / column

Zero-based row and column indices.

rowspan / columnspan

Number of rows or columns to span.

sticky

Alignment and fill within the grid cell. Any combination of 'n', 's', 'e', 'w' — e.g. 'ew' stretches horizontally, 'nsew' fills the entire cell.

margin

External spacing in pixels. Accepts an integer, a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing. Accepts an integer or (left, right).

margin_y

Vertical external spacing. Accepts an integer or (top, bottom).

API#

The verbs and classes live on the Widgets API page. At a glance:

toast

Show a passive toast that dismisses itself, and return immediately.

Notification

A persistent corner message the user closes themselves.

Snackbar

A transient message at the app window's bottom edge with one action.

snackbar

Show a snackbar at the window's bottom edge, and return immediately.

Full Example#

 1
 2
 3with bs.App(title="Transient messages", size=(560, 360), padding=20, gap=12) as app:
 4    bs.Label("Transient messages", font="heading-lg")
 5    bs.Label("Three surfaces, each for a different job.", accent="secondary")
 6
 7    with bs.GroupBox("toast() — passive, auto-dismiss", fill="x"):
 8        with bs.HStack(gap=8):
 9            bs.Button("Saved", accent="success",
10                      on_click=lambda: bs.toast("Your changes were saved.",
11                                                icon="check-circle", accent="success"))
12            bs.Button("Low battery", accent="warning",
13                      on_click=lambda: bs.toast("Battery at 12%.",
14                                                icon="battery-half", accent="warning"))
15
16    with bs.GroupBox("Notification — persistent, closes on demand", fill="x"):
17        bs.Button("Notify",
18                  on_click=lambda: bs.Notification(
19                      "Backup complete",
20                      message="3.2 GB uploaded to the cloud.",
21                      detail="just now", icon="cloud-check", accent="success",
22                  ).show())
23
24    with bs.GroupBox("Snackbar — one action, window bottom edge", fill="x"):
25        with bs.HStack(gap=8):
26            bs.Button("Archive",
27                      on_click=lambda: bs.snackbar("Conversation archived.",
28                                                   action="Undo",
29                                                   on_action=lambda: bs.toast("Restored.")))
30            bs.Button("Copy",
31                      on_click=lambda: bs.snackbar("Copied to clipboard."))
32
33app.run()