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

Line Chart

rx.recharts.line_chartrx.recharts.line

Official docs

Workshop order

Please draw the weekly visitor trends of the Seoul and Busan branches as two lines, so we can compare how they move differently.

rx.recharts.line_chart joins points with lines to show change over time. Use it when the ups and downs and the overall trend matter more than the sizes themselves. Give the chart container data and add one rx.recharts.line(data_key=…) per series.

The examples below use this linechart_data. Even without a color, lines are drawn in the theme's accent color.

linechart_data = [
    {"week": "W1", "seoul": 4000, "busan": 2400},
    {"week": "W2", "seoul": 3000, "busan": 1398},
    {"week": "W3", "seoul": 2000, "busan": 5800},
    {"week": "W4", "seoul": 2780, "busan": 3908},
    {"week": "W5", "seoul": 1890, "busan": 4800},
    {"week": "W6", "seoul": 2390, "busan": 3800},
    {"week": "W7", "seoul": 3490, "busan": 4300},
]


rx.recharts.line_chart(
    rx.recharts.line(data_key="seoul"),
    rx.recharts.line(data_key="busan"),
    rx.recharts.x_axis(data_key="week"),
    rx.recharts.y_axis(),
    data=linechart_data,
    width="100%",
    height=250,
)

Try the props

Most of a line's look is set on line. Wednesday's value in this data is None, so toggling connect_nulls shows the gap either bridged or left empty.

Try the props

curve

color

stroke_width

2

dash

dot

connect_nulls

hide

rx.recharts.line_chart(
    rx.recharts.line(
        data_key="sales",
        type_="monotone",
        stroke=rx.color("indigo", 9),
        stroke_width=2,
        stroke_dasharray="",
        dot=True,
        connect_nulls=False,
        hide=False,
    ),
    rx.recharts.x_axis(data_key="day"),
    rx.recharts.y_axis(),
    rx.recharts.graphing_tooltip(),
    data=[
        {"day": "Mon", "sales": 12},
        {"day": "Tue", "sales": 18},
        {"day": "Wed", "sales": None},
        {"day": "Thu", "sales": 15},
        {"day": "Fri", "sales": 24},
        {"day": "Sat", "sales": 20},
    ],
    width="100%",
    height=250,
)
stroke_dasharray is a string of "dash length gap length" in pixels. hide hides only the line and leaves the axes in place.
PropValuesDefaultUse
line_chart(data=)list of dictsnoneData used by the whole chart
line_chart(layout=)"horizontal" "vertical""horizontal"Horizontal or vertical flow
line_chart(margin=, sync_id=)dict / stringnoneSpace around the chart; link with other charts
line(data_key=)stringnoneKey of the value to draw
line(type_=)"monotone" "linear" "natural" "step" …none (straight)How points are joined
line(stroke=, stroke_width=)color / numberaccent 9 / 1Line color and thickness
line(stroke_dasharray=)string such as "5 5"noneDashed line
line(dot=, active_dot=)True / False / dictaccent dotData points; the dot shown on hover
line(connect_nulls=)True / FalseFalseDraw across empty values
line(hide=)True / FalseFalseHides the line
line(name=, unit=, legend_type=)stringTooltip and legend name, unit, legend icon
line(x_axis_id=, y_axis_id=)string or number0Which axis it attaches to
on_click on_mouse_enter …eventsAccepted by both the chart and the line. line also has on_animation_start and on_animation_end

Adding a grid, tooltip and legend

Chart parts attach as soon as you add them as children. cartesian_grid is the background grid, graphing_tooltip shows the values where the mouse is, and legend labels the series. Give each line type_="monotone" and the jagged lines become smooth curves.

linechart_data = [
    {"week": "W1", "seoul": 4000, "busan": 2400},
    {"week": "W2", "seoul": 3000, "busan": 1398},
    {"week": "W3", "seoul": 2000, "busan": 5800},
    {"week": "W4", "seoul": 2780, "busan": 3908},
    {"week": "W5", "seoul": 1890, "busan": 4800},
    {"week": "W6", "seoul": 2390, "busan": 3800},
    {"week": "W7", "seoul": 3490, "busan": 4300},
]


rx.recharts.line_chart(
    rx.recharts.line(data_key="seoul", type_="monotone", stroke=rx.color("accent", 9)),
    rx.recharts.line(data_key="busan", type_="monotone", stroke=rx.color("teal", 9)),
    rx.recharts.x_axis(data_key="week"),
    rx.recharts.y_axis(),
    rx.recharts.cartesian_grid(stroke_dasharray="3 3"),
    rx.recharts.graphing_tooltip(),
    rx.recharts.legend(),
    data=linechart_data,
    width="100%",
    height=280,
)

Axis titles

Put an rx.recharts.label inside an axis as a child to give it a title. Stand the y-axis title upright with custom_attrs={"angle": 270}. Leave room for the titles with a generous x-axis height and chart margin. The label position values are covered in detail on the Label page among the chart parts.

linechart_data = [
    {"week": "W1", "seoul": 4000, "busan": 2400},
    {"week": "W2", "seoul": 3000, "busan": 1398},
    {"week": "W3", "seoul": 2000, "busan": 5800},
    {"week": "W4", "seoul": 2780, "busan": 3908},
    {"week": "W5", "seoul": 1890, "busan": 4800},
    {"week": "W6", "seoul": 2390, "busan": 3800},
    {"week": "W7", "seoul": 3490, "busan": 4300},
]


rx.recharts.line_chart(
    rx.recharts.line(
        data_key="seoul",
        stroke=rx.color("accent", 9),
        stroke_width=2,
        type_="natural",
    ),
    rx.recharts.x_axis(
        rx.recharts.label(value="Week", position="center"),
        data_key="week",
        height=60,
        axis_line=False,
        tick_line=False,
    ),
    rx.recharts.y_axis(
        rx.recharts.label(value="Visits", position="left", custom_attrs={"angle": 270}),
        axis_line=False,
        tick_line=False,
    ),
    rx.recharts.graphing_tooltip(),
    data=linechart_data,
    margin={"left": 20, "right": 20, "top": 20},
    width="100%",
    height=300,
)

Turning it vertical (layout)

With layout="vertical" the lines flow from top to bottom. Switch the x-axis to numbers (type_="number") and the y-axis to categories (type_="category"), and set margin on all four sides so labels don't get cut off.

linechart_data = [
    {"week": "W1", "seoul": 4000, "busan": 2400},
    {"week": "W2", "seoul": 3000, "busan": 1398},
    {"week": "W3", "seoul": 2000, "busan": 5800},
    {"week": "W4", "seoul": 2780, "busan": 3908},
    {"week": "W5", "seoul": 1890, "busan": 4800},
    {"week": "W6", "seoul": 2390, "busan": 3800},
    {"week": "W7", "seoul": 3490, "busan": 4300},
]


rx.recharts.line_chart(
    rx.recharts.line(data_key="seoul", stroke=rx.color("accent", 9)),
    rx.recharts.line(data_key="busan", stroke=rx.color("teal", 9)),
    rx.recharts.x_axis(type_="number"),
    rx.recharts.y_axis(data_key="week", type_="category"),
    data=linechart_data,
    layout="vertical",
    margin={"top": 20, "right": 20, "left": 20, "bottom": 20},
    width="100%",
    height=300,
)

Data that changes with State

data and type_ are connected to State values. Press the button and the values wobble a little; the two select boxes change each line's shape independently. State lives separately in each browser tab, so other people's screens are unaffected. Using two axes with y_axis_id and linking charts with sync_id are covered on the area chart page.

import random
from typing import Any


class LineChartLiveState(rx.State):
    data: list[dict[str, Any]] = [
        {"week": "W1", "seoul": 4000, "busan": 2400},
        {"week": "W2", "seoul": 3000, "busan": 1398},
        {"week": "W3", "seoul": 2000, "busan": 5800},
        {"week": "W4", "seoul": 2780, "busan": 3908},
        {"week": "W5", "seoul": 1890, "busan": 4800},
    ]
    seoul_type: str = "monotone"
    busan_type: str = "monotone"

    @rx.event
    def set_seoul_type(self, value: str):
        self.seoul_type = value

    @rx.event
    def set_busan_type(self, value: str):
        self.busan_type = value

    @rx.event
    def munge(self):
        self.data = [
            {**row, "seoul": row["seoul"] + random.randint(-500, 500), "busan": row["busan"] + random.randint(-1000, 1000)}
            for row in self.data
        ]


rx.vstack(
    rx.recharts.line_chart(
        rx.recharts.line(data_key="seoul", type_=LineChartLiveState.seoul_type, stroke=rx.color("accent", 9)),
        rx.recharts.line(data_key="busan", type_=LineChartLiveState.busan_type, stroke=rx.color("teal", 9)),
        rx.recharts.x_axis(data_key="week"),
        rx.recharts.y_axis(),
        data=LineChartLiveState.data,
        margin={"top": 20, "right": 20, "left": 20, "bottom": 20},
        width="100%",
        height=280,
    ),
    rx.hstack(
        rx.button("Munge data", on_click=LineChartLiveState.munge),
        rx.select(
            ["monotone", "linear", "step", "stepBefore", "stepAfter"],
            value=LineChartLiveState.seoul_type,
            on_change=LineChartLiveState.set_seoul_type,
        ),
        rx.select(
            ["monotone", "linear", "step", "stepBefore", "stepAfter"],
            value=LineChartLiveState.busan_type,
            on_change=LineChartLiveState.set_busan_type,
        ),
        wrap="wrap",
    ),
    width="100%",
)

Filling the order

The two branches' lines are told apart by both color and line style (solid and dashed). Not relying on color alone keeps the chart readable in black-and-white print and for color-blind users.

linechart_data = [
    {"week": "W1", "seoul": 4000, "busan": 2400},
    {"week": "W2", "seoul": 3000, "busan": 1398},
    {"week": "W3", "seoul": 2000, "busan": 5800},
    {"week": "W4", "seoul": 2780, "busan": 3908},
    {"week": "W5", "seoul": 1890, "busan": 4800},
    {"week": "W6", "seoul": 2390, "busan": 3800},
    {"week": "W7", "seoul": 3490, "busan": 4300},
]


rx.recharts.line_chart(
    rx.recharts.cartesian_grid(stroke_dasharray="3 3", vertical=False),
    rx.recharts.line(data_key="seoul", name="Seoul", type_="monotone", stroke=rx.color("accent", 9), stroke_width=2),
    rx.recharts.line(
        data_key="busan",
        name="Busan",
        type_="monotone",
        stroke=rx.color("teal", 9),
        stroke_width=2,
        stroke_dasharray="5 4",
    ),
    rx.recharts.x_axis(data_key="week"),
    rx.recharts.y_axis(),
    rx.recharts.graphing_tooltip(),
    rx.recharts.legend(),
    data=linechart_data,
    width="100%",
    height=300,
)

Workshop notes

  • Put one line(data_key=…) per series inside line_chart(data=…).

  • type_ sets how points are joined (monotone, linear, step…); stroke, stroke_width and stroke_dasharray shape the line.

  • dot for points, connect_nulls to bridge empty values, hide to hide a line.

  • Axis titles are rx.recharts.label inside the axis; make room with margin and the axis height.

  • Give data and type_ State values and buttons and select boxes change the chart.

← Previous

Charts · Bar Chart

Next →

Charts · Composed 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