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
Disclosure

Segmented Control

rx.segmented_control.rootrx.segmented_control.item

Official docs

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

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",
)
size sets the size, variant the background style, color_scheme the color of the selected segment, and radius the corners.
PartPropValuesUse
rootdefault_valueAn item's valueInitial selection (uncontrolled)
rootvalue + on_changeState value, eventManage the selection with State (controlled)
roottype"single" (default) "multiple"Pick one, or several
rootsize"1" "2" (default) "3"Size
rootvariant"surface" (default) "classic"Background style
rootcolor_scheme · radiusRadix color name, corner valueColor and corners
itemvalueString (unique)This segment's value

Connecting to State

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%",
)

Picking several

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"),
)

Filling the order

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.

← Previous

Disclosure · Accordion

Next →

Overlay · Tooltip

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