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
Charts

Radar Chart

rx.recharts.radar_chartrx.recharts.radarrx.recharts.polar_gridrx.recharts.polar_angle_axisrx.recharts.polar_radius_axis

Official docs

Workshop order

Please overlay two students' scores per subject as a spiderweb, so it's clear at a glance who is strong in which subject.

rx.recharts.radar_chart plots the scores of several items on axes radiating from the center and joins them into a polygon. Use it to compare the "shape" of subjects across five or six items measured on the same scale. Give the chart data and add one rx.recharts.radar(data_key=…) per series.

Circular charts use polar parts instead of Cartesian axes. polar_grid is the spiderweb grid, polar_angle_axis shows the item names around the edge, and polar_radius_axis is the scale running from the center outward.

radarchart_data = [
    {"subject": "Math", "Mina": 120, "Joon": 110},
    {"subject": "Science", "Mina": 98, "Joon": 130},
    {"subject": "English", "Mina": 86, "Joon": 130},
    {"subject": "History", "Mina": 99, "Joon": 100},
    {"subject": "Art", "Mina": 85, "Joon": 90},
    {"subject": "Music", "Mina": 65, "Joon": 85},
]


rx.recharts.radar_chart(
    rx.recharts.radar(data_key="Mina", stroke=rx.color("accent", 9), fill=rx.color("accent", 8)),
    rx.recharts.polar_grid(),
    rx.recharts.polar_angle_axis(data_key="subject"),
    rx.recharts.polar_radius_axis(angle=90, domain=[0, 150]),
    data=radarchart_data,
    width="100%",
    height=300,
)

Try the props

Change the fill strength (fill_opacity), the dots at the vertices (dot), the grid shape (grid_type), and the chart's inner and outer radius. The data is radarchart_data from above.

Try the props

color

fill_opacity

0.6

dot

grid_type

inner_radius

outer_radius

rx.recharts.radar_chart(
    rx.recharts.radar(
        data_key="Mina",
        stroke=rx.color("indigo", 9),
        fill=rx.color("indigo", 8),
        fill_opacity=0.6,
        dot=False,
    ),
    rx.recharts.polar_grid(grid_type="polygon"),
    rx.recharts.polar_angle_axis(data_key="subject"),
    rx.recharts.polar_radius_axis(angle=90, domain=[0, 150]),
    data=radarchart_data,
    inner_radius="0%",
    outer_radius="80%",
    width="100%",
    height=300,
)
A larger inner_radius hollows out the center, making differences between small values easier to see. grid_type="circle" draws the grid as circles.
PropValuesDefaultUse
radar_chart(data=)list of dictsnoneOne dict per item
radar_chart(cx=, cy=)number or percentage"50%"Center position
radar_chart(inner_radius=, outer_radius=)number or percentage0 / "80%"Radius of the inner and outer grid
radar_chart(start_angle=, end_angle=)number (degrees)90 / -270Angle of the first axis and direction of rotation
radar_chart(margin=)dict0Space around the chart
radar(data_key=)stringnoneKey of the value to draw
radar(stroke=, fill=, fill_opacity=)color / 0–1accent 9 / accent 3 / 0.6Border, fill and fill strength
radar(dot=)True / False / dictnoneDots at the vertices
radar(legend_type=, label=)legend icon / bool"rect"Legend shape; value labels
radar(animation_begin=, animation_duration=, animation_easing=)ms / ms / "ease" …0 / 1500 / "ease"Entrance animation
polar_grid(grid_type=)"polygon" "circle""polygon"Grid shape
polar_radius_axis(angle=, domain=)number / [min, max]Direction and range of the scale axis
Eventson_click on_mouse_enter on_mouse_leaveOn the chart. radar also has on_animation_start and on_animation_end

Overlaying several radars

With two radars, the polygons overlap on the same grid. Later series are drawn on top, so lower fill_opacity to let the series underneath show through. The chart's inner_radius and outer_radius set the size of the drawing and the empty space in the middle.

radarchart_data = [
    {"subject": "Math", "Mina": 120, "Joon": 110},
    {"subject": "Science", "Mina": 98, "Joon": 130},
    {"subject": "English", "Mina": 86, "Joon": 130},
    {"subject": "History", "Mina": 99, "Joon": 100},
    {"subject": "Art", "Mina": 85, "Joon": 90},
    {"subject": "Music", "Mina": 65, "Joon": 85},
]


rx.recharts.radar_chart(
    rx.recharts.radar(
        data_key="Mina",
        stroke=rx.color("accent", 9),
        fill=rx.color("accent", 8),
    ),
    rx.recharts.radar(
        data_key="Joon",
        stroke=rx.color("teal", 9),
        fill=rx.color("teal", 8),
        fill_opacity=0.6,
    ),
    rx.recharts.polar_grid(),
    rx.recharts.polar_angle_axis(data_key="subject"),
    rx.recharts.polar_radius_axis(angle=90, domain=[0, 150]),
    rx.recharts.legend(),
    data=radarchart_data,
    inner_radius="15%",
    outer_radius="80%",
    width="100%",
    height=300,
)

Dots, legend and animation

dot=True puts a dot on every vertex, and legend_type="line" turns the legend icon into a line. animation_begin, animation_duration and animation_easing control how it first draws. The example below unfolds slowly over 4 seconds.

radarchart_data = [
    {"subject": "Math", "Mina": 120, "Joon": 110},
    {"subject": "Science", "Mina": 98, "Joon": 130},
    {"subject": "English", "Mina": 86, "Joon": 130},
    {"subject": "History", "Mina": 99, "Joon": 100},
    {"subject": "Art", "Mina": 85, "Joon": 90},
    {"subject": "Music", "Mina": 65, "Joon": 85},
]


rx.recharts.radar_chart(
    rx.recharts.radar(
        data_key="Mina",
        dot=True,
        stroke=rx.color("accent", 9),
        fill=rx.color("accent", 8),
        fill_opacity=0.6,
        legend_type="line",
        animation_begin=0,
        animation_duration=4000,
        animation_easing="ease-in",
    ),
    rx.recharts.polar_grid(),
    rx.recharts.polar_angle_axis(data_key="subject"),
    rx.recharts.polar_radius_axis(angle=90, domain=[0, 150]),
    rx.recharts.legend(),
    data=radarchart_data,
    width="100%",
    height=300,
)

Data that changes with State

In this example you distribute 100 points across five traits. Moving a slider changes traits in State and the chart redraws right away. The handler stops you from raising a trait by more than the points you have left. tick=False and axis_line=False on polar_radius_axis hide the scale, leaving only the shape.

Strength

15

Speed

15

Stamina

15

Wisdom

15

Charm

15

Remaining: 25

from typing import Any


class RadarChartTraitState(rx.State):
    budget: int = 100
    traits: list[dict[str, Any]] = [
        {"trait": "Strength", "value": 15},
        {"trait": "Speed", "value": 15},
        {"trait": "Stamina", "value": 15},
        {"trait": "Wisdom", "value": 15},
        {"trait": "Charm", "value": 15},
    ]

    @rx.var
    def remaining(self) -> int:
        return self.budget - sum(t["value"] for t in self.traits)

    @rx.event
    def set_trait(self, trait: str, value: list[float]):
        new = int(value[0])
        rows = []
        for t in self.traits:
            if t["trait"] == trait:
                new = min(new, self.remaining + t["value"])
                t = {**t, "value": new}
            rows.append(t)
        self.traits = rows


rx.flex(
    rx.box(
        rx.recharts.radar_chart(
            rx.recharts.radar(data_key="value", stroke=rx.color("accent", 9), fill=rx.color("accent", 8)),
            rx.recharts.polar_grid(),
            rx.recharts.polar_angle_axis(data_key="trait"),
            rx.recharts.polar_radius_axis(domain=[0, 100], tick=False, axis_line=False),
            data=RadarChartTraitState.traits,
            width="100%",
            height=260,
        ),
        flex="1 1 240px",
    ),
    rx.vstack(
        rx.foreach(
            RadarChartTraitState.traits,
            lambda t: rx.hstack(
                rx.text(t["trait"], size="2", width="5em"),
                rx.slider(
                    value=[t["value"].to(int)],
                    max=100,
                    on_change=lambda v: RadarChartTraitState.set_trait(t["trait"].to(str), v),
                    width="10em",
                ),
                rx.text(t["value"], size="2"),
                align="center",
            ),
        ),
        rx.text("Remaining: ", RadarChartTraitState.remaining, size="2", weight="bold"),
        flex="1 1 240px",
    ),
    spacing="4",
    wrap="wrap",
    align="center",
    width="100%",
)

Filling the order

The data keys are the students' names ("Mina", "Joon"), so those names show up as-is in the legend and tooltip. radar has no name prop in 0.10, so giving the keys readable names is the simplest approach. Both are lightly filled with fill_opacity=0.4 so the overlap stays readable, and color and dots together tell the series apart.

radarchart_data = [
    {"subject": "Math", "Mina": 120, "Joon": 110},
    {"subject": "Science", "Mina": 98, "Joon": 130},
    {"subject": "English", "Mina": 86, "Joon": 130},
    {"subject": "History", "Mina": 99, "Joon": 100},
    {"subject": "Art", "Mina": 85, "Joon": 90},
    {"subject": "Music", "Mina": 65, "Joon": 85},
]


rx.recharts.radar_chart(
    rx.recharts.polar_grid(),
    rx.recharts.polar_angle_axis(data_key="subject"),
    rx.recharts.polar_radius_axis(angle=90, domain=[0, 150], tick=False, axis_line=False),
    rx.recharts.radar(
        data_key="Mina",
        stroke=rx.color("accent", 9),
        fill=rx.color("accent", 8),
        fill_opacity=0.4,
        dot=True,
    ),
    rx.recharts.radar(
        data_key="Joon",
        stroke=rx.color("teal", 9),
        fill=rx.color("teal", 8),
        fill_opacity=0.4,
        dot=True,
    ),
    rx.recharts.graphing_tooltip(),
    rx.recharts.legend(),
    data=radarchart_data,
    width="100%",
    height=320,
)

Workshop notes

  • Put radar(data_key=…) and polar_grid, polar_angle_axis and polar_radius_axis inside radar_chart(data=…).

  • polar_angle_axis(data_key=) gives the item names around the edge; polar_radius_axis(domain=) the scale range.

  • Multiple series means multiple radars. Lower fill_opacity so overlaps show.

  • The chart's inner_radius, outer_radius, start_angle and end_angle set its shape and direction.

  • Give data a State value and inputs such as sliders reshape the polygon instantly.

← Previous

Charts · Pie Chart

Next →

Charts · Radial Bar Chart

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