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
Add a 'Grid / List' view switch above the product list, and show the products in whichever layout is chosen.
A segmented control is a group of buttons for choosing one of a few fixed values or views. It makes a one-of-many choice like "Inbox / Drafts / Sent" obvious. A dropdown shows only the chosen value, and a row of separate buttons doesn't make clear which one is on; a segmented control shows all the options and the current choice together.
rx.segmented_control.root groups the rx.segmented_control.item elements, and each item has its visible text and a unique value.
rx.segmented_control.root(
rx.segmented_control.item("Inbox", value="inbox"),
rx.segmented_control.item("Drafts", value="drafts"),
rx.segmented_control.item("Sent", value="sent"),
default_value="inbox",
)Try the props
size
variant
color
radius
rx.segmented_control.root(
rx.segmented_control.item("Inbox", value="inbox"),
rx.segmented_control.item("Drafts", value="drafts"),
rx.segmented_control.item("Sent", value="sent"),
default_value="inbox",
size="2",
variant="surface",
color_scheme="indigo",
radius="medium",
)| Part | Prop | Values | Use |
|---|---|---|---|
root | default_value | An item's value | Initial selection (uncontrolled) |
root | value + on_change | State value, event | Manage the selection with State (controlled) |
root | type | "single" (default) "multiple" | Pick one, or several |
root | size | "1" "2" (default) "3" | Size |
root | variant | "surface" (default) "classic" | Background style |
root | color_scheme · radius | Radix color name, corner value | Color and corners |
item | value | String (unique) | This segment's value |
As in the official docs' basic example, wire a State value to value and an event that changes it to on_change. When you pick a segment, on_change passes the chosen item's value, and when the State changes, other parts of the page follow. Here the chosen value changes the text alignment.
on_change passes either a string or a list of strings depending on type, so annotate the handler's argument as str | list[str]. With just str, Reflex raises a type mismatch error.
Aligned left
class SegmentedAlignState(rx.State):
control: str = "left"
@rx.event
def set_segmented_align(self, value: str | list[str]):
if isinstance(value, str):
self.control = value
rx.vstack(
rx.segmented_control.root(
rx.segmented_control.item("Left", value="left"),
rx.segmented_control.item("Center", value="center"),
rx.segmented_control.item("Right", value="right"),
value=SegmentedAlignState.control,
on_change=SegmentedAlignState.set_segmented_align,
),
rx.card(
rx.text("Aligned " + SegmentedAlignState.control, align=SegmentedAlignState.control),
width="100%",
),
width="100%",
)With type="multiple", several segments can be on at once, and the value becomes a list. Items can hold icons instead of text, too. Below are bold, italic and underline buttons. Reflex 0.10 checks directly whether type is "multiple" when it builds the component, so give type a fixed value, not a State value. That's also why it isn't in the lab.
Sample text
value = bold
class SegmentedStyleState(rx.State):
styles: list[str] = ["bold"]
@rx.event
def set_segmented_styles(self, value: str | list[str]):
self.styles = [value] if isinstance(value, str) else list(value)
rx.vstack(
rx.segmented_control.root(
rx.segmented_control.item(rx.icon("bold", size=16), value="bold"),
rx.segmented_control.item(rx.icon("italic", size=16), value="italic"),
rx.segmented_control.item(rx.icon("underline", size=16), value="underline"),
type="multiple",
value=SegmentedStyleState.styles,
on_change=SegmentedStyleState.set_segmented_styles,
),
rx.text(
"Sample text",
weight=rx.cond(SegmentedStyleState.styles.contains("bold"), "bold", "regular"),
font_style=rx.cond(SegmentedStyleState.styles.contains("italic"), "italic", "normal"),
text_decoration=rx.cond(SegmentedStyleState.styles.contains("underline"), "underline", "none"),
),
rx.text("value = ", SegmentedStyleState.styles.join(", "), size="1", color_scheme="gray"),
)Depending on the chosen value, rx.cond switches between the grid and the list. Each item holds both an icon and text.
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
class SegmentedViewState(rx.State):
view: str = "grid"
@rx.event
def set_segmented_view(self, value: str | list[str]):
if isinstance(value, str):
self.view = value
rx.vstack(
rx.segmented_control.root(
rx.segmented_control.item(rx.icon("layout-grid", size=14), "Grid", value="grid"),
rx.segmented_control.item(rx.icon("list", size=14), "List", value="list"),
value=SegmentedViewState.view,
on_change=SegmentedViewState.set_segmented_view,
size="1",
),
rx.cond(
SegmentedViewState.view == "grid",
rx.grid(*[rx.card(rx.text("Item ", i), height="60px") for i in range(1, 7)], columns="3", spacing="2", width="100%"),
rx.vstack(*[rx.card(rx.text("Item ", i), width="100%") for i in range(1, 7)], spacing="2", width="100%"),
),
width="100%",
max_width="420px",
)Workshop notes
Put segmented_control.item("text", value=…) inside segmented_control.root.
default_value for uncontrolled; value + on_change to let State manage it (controlled).
The on_change handler's argument type is str | list[str].
With type="multiple", several segments can be on and the value becomes a list.
Shape it with size · variant (surface · classic) · color_scheme · radius.
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.