The Component Workshop: Reflex's 100 Library Components
·
Course overview
Layout
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
Typography
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
Forms
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
Data display
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
Disclosure
·
Tabs
·
Accordion
·
Segmented Control
Overlay
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
Dynamic rendering
·
Cond
·
Match
·
Foreach
·
Auto Scroll
Media
·
Image
·
Audio
·
Video
Tables and data grids
·
Table
·
Data Table
·
Data Editor
Charts
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
Chart parts
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
Other chart libraries
·
Plotly
·
Pyplot
HTML elements
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
Other tools
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
Workshop order
When someone clicks 'Save' on the settings screen, show a notification in the corner that says 'Saving…' and then changes to 'Saved' once it is done.
rx.toast is a notification that pops up in a corner of the screen for a moment and then goes away on its own. Unlike a dialog, it does not block what the user is doing, so use it when you only need to report a result, such as "Saved". rx.toast(...) is not a component but an event. Put it straight into a button's on_click, or hand it back from an event handler with yield or return.
rx.button("Show Toast", on_click=rx.toast("Hello, World!"))The look and behavior of a notification are passed to rx.toast as keyword arguments. Change a value, then click the button. duration is how long (in milliseconds) it stays before closing on its own.
Try the props
message
description
position
duration
4000
close_button
invert
dismissible
rx.button(
"Show toast",
on_click=rx.toast(
"Event created",
description="Sunday, December 3 at 9:00 AM",
position="bottom-right",
duration=4000,
close_button=False,
invert=False,
dismissible=True,
),
)| Option | Values | Use |
|---|---|---|
description | string | Small text under the title |
title | string | Title (added in 0.10; can be used instead of the first argument) |
position | "top-left" "top-center" "top-right" "bottom-left" "bottom-center" "bottom-right" | Corner the notification appears in |
duration | milliseconds | Time before it closes on its own (sonner default 4000) |
close_button | True / False | Show a close (×) button |
invert | True / False | Dark notification on a light screen, and vice versa |
important | True / False | Make screen readers announce it more urgently |
dismissible | True / False | With False, it cannot be swiped away |
action · cancel | {"label": text, "on_click": event} | Primary button · secondary button. Clicking one closes the notification |
id | string | Name of the notification. Sending again with the same id updates that notification |
unstyled · style · class_name | - | Turn off the default look, style it yourself |
on_dismiss | event | The close button is clicked or it is swiped away |
on_auto_close | event | It closed on its own after duration |
There are per-type functions rx.toast.success, rx.toast.error, rx.toast.warning, rx.toast.info and rx.toast.loading, plus rx.toast.dismiss(id) as the event that closes one.
An event handler can send a notification with yield rx.toast(...) once its work is done. The handler below pretends to fetch data, waits one second, and then shows a notification. In an async handler, await asyncio.sleep lets the server do other work while it waits.
import asyncio
class ToastFetchState(rx.State):
@rx.event
async def fetch_data(self):
# Simulate fetching data for a 1-second delay
await asyncio.sleep(1)
# Shows a toast when the data is fetched
yield rx.toast("Data fetched!")
rx.button("Get Data", on_click=ToastFetchState.fetch_data)Pass dicts with label and on_click to action and cancel, and buttons appear inside the notification. Clicking one runs its event and closes the notification. Clicking close (×) or swiping it away calls on_dismiss; closing on its own when time runs out calls on_auto_close. Check the log below to see which event fired.
class ToastActionState(rx.State):
log: list[str] = []
@rx.event
def add_log(self, line: str):
self.log = (self.log + [line])[-4:]
rx.flex(
rx.button(
"Delete item",
on_click=rx.toast(
"Item deleted",
action={"label": "Undo", "on_click": ToastActionState.add_log("Undo clicked")},
cancel={"label": "Dismiss", "on_click": ToastActionState.add_log("Dismiss clicked")},
close_button=True,
on_dismiss=ToastActionState.add_log("Closed or swiped away"),
on_auto_close=ToastActionState.add_log("Closed automatically"),
),
),
rx.vstack(rx.foreach(ToastActionState.log, lambda line: rx.code(line)), spacing="1"),
direction="column",
spacing="3",
align="start",
)Success, error, warning and info each have a function with its own icon and color. Reflex's default toaster uses rich_colors=True, so each type also gets its own background color.
rx.hstack(
rx.button("Success", on_click=rx.toast.success("Success!"), color_scheme="green"),
rx.button("Error", on_click=rx.toast.error("Error!"), color_scheme="red"),
rx.button("Warning", on_click=rx.toast.warning("Warning!"), color_scheme="orange"),
rx.button("Info", on_click=rx.toast.info("Info!"), color_scheme="blue"),
wrap="wrap",
)0.10 also has rx.toast.loading and rx.toast.dismiss. A loading notification never closes on its own, so replace it by sending another notification with the same id, or close it with rx.toast.dismiss. Calling it without an id, as in rx.toast.dismiss(), closes every notification.
rx.flex(
rx.button("Start", on_click=rx.toast.loading("Uploading…", id="upload-demo"), variant="soft"),
rx.button("Finish", on_click=rx.toast.success("Upload complete", id="upload-demo"), variant="soft", color_scheme="green"),
rx.button("Dismiss all", on_click=rx.toast.dismiss(), variant="soft", color_scheme="gray"),
spacing="3",
wrap="wrap",
)If the per-type looks don't fit, pass CSS to style and style it yourself. position can also be set per notification.
rx.button(
"Custom",
on_click=rx.toast(
"Custom Toast!",
position="top-right",
style={
"background-color": "green",
"color": "white",
"border": "1px solid green",
"border-radius": "0.5em",
},
),
)To show notifications, the app needs a toaster (rx.toast.provider) somewhere. In Reflex 0.10, rx.App puts one in its toaster setting by default, so you usually don't need to add it yourself (the official docs describe it as included in overlay_component). To change the notification defaults for the whole app, pass a toaster when you create rx.App. Since that affects the whole site, this page shows it as code only.
app = rx.App(
toaster=rx.toast.provider(
position="top-center",
close_button=True,
visible_toasts=3,
toast_options=rx.toast.options(duration=6000),
),
)| Toaster prop | Use |
|---|---|
position | Default position (Reflex default "bottom-right") |
rich_colors | Per-type background colors (Reflex default True) |
expand | Show stacked notifications expanded (Reflex default True) |
close_button | Close button on every notification (default False) |
visible_toasts · gap · offset | How many are visible at once, space between them, distance from the screen edge |
theme · invert · dir | Light or dark (follows the site's color mode by default), inversion, text direction |
hotkey | Shortcut that moves focus to the toaster |
toast_options | Default options for every notification (rx.toast.options(...)) |
loading_icon · pause_when_page_is_hidden | Loading icon; pause the timer while the tab is hidden |
The save handler first sends a loading notification and, once the work is done, sends a success notification with the same id. So instead of a new notification stacking up, 'Saving…' turns into 'Saved'.
Email notifications
Saved versions: 0
import asyncio
class ToastSaveState(rx.State):
saved_at: int = 0
@rx.event
async def save(self):
yield rx.toast.loading("Saving settings…", id="toast-save")
await asyncio.sleep(1)
self.saved_at += 1
yield rx.toast.success(
"Settings saved",
id="toast-save",
description=f"Version {self.saved_at}",
duration=3000,
)
rx.card(
rx.flex(
rx.box(
rx.text("Email notifications", weight="bold"),
rx.text("Saved versions: ", ToastSaveState.saved_at, size="2", color_scheme="gray"),
),
rx.spacer(),
rx.button("Save", on_click=ToastSaveState.save),
align="center",
spacing="3",
),
max_width="420px",
)Workshop notes
rx.toast("text", ...) is an event. Put it in on_click, or yield or return it from a handler.
Look: description · position · duration · close_button · invert; buttons: action · cancel dicts.
Types: success · error · warning · info · loading; closing: rx.toast.dismiss(id).
Sending again with the same id updates that notification (loading → done).
rx.App includes a toaster by default. App-wide defaults: rx.App(toaster=rx.toast.provider(...)).
Get news about new lessons
We'll email you when this course gets new lessons or a follow-up course opens.
R
ReflexKR
Learn Python and Reflex by doing. Every example was run and verified on Reflex 0.10.0.
ReflexKR is free, with no banner ads. If it helped you, you can support it with a coffee. ☕ Buy us a coffee
Affiliate disclosure© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Questions & answers
Ask anything about this lesson. Questions from every language version of this page appear together.