ui.banner
Banner
A full-width strip for news that concerns the whole page: six tones, three sizes, room for actions.Announcements
The four semantic tones pick their icon; primary and muted take the one you give them.Scheduled maintenance on Sunday, 02:00–03:00 UTC.
Your data export is ready to download.
You are viewing a read-only copy of this workspace.
Sync with Google Calendar has stopped.
Bretzel Conf 2026 — early-bird tickets end Friday.
This workspace was archived on 12 March.
def announcements() -> None:
with ui.vstack(gap="sm", classes="w-full"):
ui.banner("Scheduled maintenance on Sunday, 02:00–03:00 UTC.",
color="info")
ui.banner("Your data export is ready to download.", color="success")
ui.banner("You are viewing a read-only copy of this workspace.",
color="warning")
ui.banner("Sync with Google Calendar has stopped.", color="error")
ui.banner("Bretzel Conf 2026 — early-bird tickets end Friday.",
color="primary", icon="ticket")
ui.banner("This workspace was archived on 12 March.", color="muted")
With actions
Whatever you put inside the banner lines up on its right.Update availableVersion 2.4 brings recurring invoices and a faster dashboard.
Keep your boardsYour trial ends in 3 days.
def with_actions() -> None:
with ui.vstack(gap="sm", classes="w-full"):
with ui.banner("Version 2.4 brings recurring invoices and a faster "
"dashboard.", title="Update available", color="info"):
ui.button("Install now", size="sm")
ui.button("Later", size="sm", variant="ghost")
with ui.banner("Your trial ends in 3 days.", title="Keep your boards",
color="warning", icon="clock"):
ui.button("Choose a plan", size="sm", color="warning")
Sizes
Small — for a dense admin screen.
Medium — the default.
Large — for the one thing nobody should miss.
def sizes() -> None:
with ui.vstack(gap="sm", classes="w-full"):
ui.banner("Small — for a dense admin screen.", color="info", size="sm")
ui.banner("Medium — the default.", color="info", size="md")
ui.banner("Large — for the one thing nobody should miss.",
color="info", size="lg")
Above an application
Edge to edge at the top of a screen, where a status belongs to everything below it.You are impersonating Ada Lovelace. Every action is logged.
Invoices
184 paid, 3 overduePaid this quarter · 78%
def above_the_app() -> None:
with ui.card(padding="none", classes="w-full"), ui.vstack(gap="none"):
ui.banner("You are impersonating Ada Lovelace. Every action is "
"logged.", color="warning", icon="user-cog", size="sm")
with ui.vstack(gap="md", classes="p-6"):
with ui.hstack(gap="md", justify="between", wrap=True):
with ui.vstack(gap="none"):
ui.heading("Invoices", level=3, size="lg")
ui.text("184 paid, 3 overdue", color="muted", size="sm")
ui.button("New invoice", icon_left="plus")
ui.progress(78, label="Paid this quarter · 78%", show_label=True)
Closed on the server
on_close runs a Python function — the place to remember that this user has already seen it.PrivacyWe only use cookies that keep you signed in.
class Notice(PageState):
closed: bool = field(default=False)
def close_notice() -> None:
Notice().closed = True
def bring_back() -> None:
Notice().closed = False
@refreshable(deps=[Notice])
def cookie_notice() -> None:
if Notice().closed:
ui.button("Bring the notice back", icon_left="rotate-ccw",
variant="ghost", on_click=bring_back, classes="self-center")
else:
ui.banner("We only use cookies that keep you signed in.",
title="Privacy", color="muted", icon="cookie",
dismissible=True, on_close=close_notice)
def dismissible() -> None:
cookie_notice()