R

ReflexKR

Reflex Docs

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

The Component Workshop: Reflex's 100 Library Components
Data display

Spinner

rx.spinner

Official docs

Workshop order

When the 'Save draft' button is clicked, make a spinner turn in place of the floppy disk icon while it saves.

rx.spinner is a spinning indicator that tells the user work is in progress. Use it when you don't know how much is left; when you do, rx.progress is the better fit.

rx.spinner()

Try the props

When you give it children, the spinner shows while loading is on and the children show when it's off.

Try the props

size

loading

rx.spinner(rx.text("Content is ready"), size="2", loading=True)
Turn loading off and the child (the text) appears instead of the spinner. size runs from "1" to "3".
PropValuesDefaultUse
size"1" "2" "3""2"Size
loadingTrue / FalseTrueShows the spinner when on and the children when off

Sizes

size runs from "1" to "3". Next to text, match it to the font size.

rx.hstack(
    rx.spinner(size="1"),
    rx.spinner(size="2"),
    rx.spinner(size="3"),
    align="center",
    spacing="4",
)

A spinner inside a button

Buttons have their own loading prop: turn it on and a spinner replaces the label, and the button can't be clicked (first). For a button with an icon, swap just the icon slot for rx.spinner and block the button with disabled, so only the icon spins while the label stays (second). With loading=False, as in the third, the wrapped icon shows as usual.

rx.flex(
    rx.button("Bookmark", loading=True),
    rx.button(rx.spinner(loading=True), "Bookmark", disabled=True),
    rx.button(rx.spinner(rx.icon("bookmark"), loading=False), "Bookmark"),
    spacing="3",
    wrap="wrap",
)

Switching it with State

Pass a State value to loading, and the spinner shows only while the work runs; when it's done, the result appears in its place. No need to reserve space separately or use rx.cond.

Loaded 0 times

import asyncio


class SpinnerLoadState(rx.State):
    loading: bool = False
    loads: int = 0

    @rx.event(background=True)
    async def load_result(self):
        async with self:
            if self.loading:
                return
            self.loading = True
        await asyncio.sleep(1.5)
        async with self:
            self.loading = False
            self.loads += 1


rx.hstack(
    rx.button("Load", on_click=SpinnerLoadState.load_result, variant="soft"),
    rx.spinner(rx.text("Loaded ", SpinnerLoadState.loads, " times"), loading=SpinnerLoadState.loading),
    spacing="4",
    align="center",
)

Filling the order

While saving, the floppy disk icon turns into a spinner and the button is locked. When it's done, the icon comes back and a "Saved" badge appears.

import asyncio


class SpinnerSaveState(rx.State):
    saving: bool = False
    saved: bool = False

    @rx.event(background=True)
    async def save_draft(self):
        async with self:
            if self.saving:
                return
            self.saving = True
            self.saved = False
        await asyncio.sleep(1.2)
        async with self:
            self.saving = False
            self.saved = True


rx.hstack(
    rx.button(
        rx.spinner(rx.icon("save"), loading=SpinnerSaveState.saving),
        "Save draft",
        on_click=SpinnerSaveState.save_draft,
        disabled=SpinnerSaveState.saving,
    ),
    rx.cond(SpinnerSaveState.saved, rx.badge("Saved", color_scheme="green")),
    spacing="3",
    align="center",
)

Workshop notes

  • rx.spinner() signals a wait of unknown length; if you know how much is left, use rx.progress.

  • size "1" to "3".

  • Wrap children and the spinner shows while loading=True; with False, the children show.

  • To change the whole button, use button(loading=True); to spin just the icon, wrap the icon in rx.spinner.

← Previous

Data display · Progress

Next →

Data display · Scroll Area

Get news about new lessons

We'll email you when this course gets new lessons or a follow-up course opens.

We collect: your email address · Purpose: news about new lessons or the launch of this course · Kept until: you ask us to remove it. We never use it for anything else or share it. Reply to any notice email and we'll delete it right away.

Questions & answers

Ask anything about this lesson. Questions from every language version of this page appear together.

Shown as plain text, without links or formatting.

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
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex