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

Area Chart

rx.recharts.area_chartrx.recharts.area

Official docs

Workshop order

Please make a graph that stacks monthly web and app visitors, so the overall trend and each one's share are visible at a glance.

rx.recharts.area_chart is an area chart: a line with the space beneath it filled in. Use it to show how a quantity changes over time, together with the total size of several values added up. You give the chart container (area_chart) the data, and put the series to draw (area) and the axes inside it as children.

The data is a list of dicts. Each dict is one slot on the x-axis, and data_key is the key that picks which value in that dict to draw. Every example on this page uses the areachart_data below.

areachart_data = [
    {"month": "Jan", "web": 4000, "app": 2400},
    {"month": "Feb", "web": 3000, "app": 1398},
    {"month": "Mar", "web": 2000, "app": 5800},
    {"month": "Apr", "web": 2780, "app": 3908},
    {"month": "May", "web": 1890, "app": 4800},
    {"month": "Jun", "web": 2390, "app": 3800},
]


rx.recharts.area_chart(
    rx.recharts.area(data_key="web"),
    rx.recharts.x_axis(data_key="month"),
    rx.recharts.y_axis(),
    data=areachart_data,
    width="100%",
    height=250,
)

A chart's width and height accept only numbers (pixels) or percentage strings such as "100%". CSS units like "20em" go on the box that wraps the chart. Axes (x_axis, y_axis), grids, tooltips and legends are covered in detail on the chart parts pages; here we use only what we need.

Try the props

The two areas are stacked with stack_id="1". Change the curve shape, color, stroke width, dots and stacking mode. The data is areachart_data from above.

Try the props

curve

color

stroke_width

1

dot

stack_offset

rx.recharts.area_chart(
    rx.recharts.area(
        data_key="web",
        type_="monotone",
        stroke=rx.color("indigo", 9),
        fill=rx.color("indigo", 5),
        stroke_width=1,
        dot=False,
        stack_id="1",
    ),
    rx.recharts.area(
        data_key="app",
        type_="monotone",
        stroke=rx.color("teal", 9),
        fill=rx.color("teal", 5),
        stroke_width=1,
        dot=False,
        stack_id="1",
    ),
    rx.recharts.x_axis(data_key="month"),
    rx.recharts.y_axis(),
    rx.recharts.graphing_tooltip(),
    data=areachart_data,
    stack_offset="none",
    width="100%",
    height=250,
)
type_ is how the points are joined. Switch stack_offset to expand and each month sums to 100%, so only the proportions show.
PropValuesDefaultUse
area_chart(data=)list of dictsnoneData used by the whole chart
area_chart(width=, height=)number or "100%""100%"Chart size. A numeric height is the safe choice
area_chart(layout=)"horizontal" "vertical""horizontal"Horizontal or vertical flow
area_chart(stack_offset=)"none" "expand" "wiggle" "silhouette"noneHow the baseline of stacked areas is computed
area_chart(sync_id=)stringnoneCharts with the same value move their tooltips and brushes together
area_chart(margin=){"top": 5, ...}noneSpace around the chart
area_chart(base_value=)number, "dataMin" "dataMax" "auto""auto"The floor value the area starts from
area(data_key=)stringnoneKey of the value to draw
area(type_=)"monotone" "linear" "natural" "step" …"monotone"Curve interpolation
area(stroke=, fill=)coloraccent 9 / accent 5Line color and fill color
area(stroke_width=)number1Line thickness
area(dot=, active_dot=)True / False / dictFalse / accent dotShow dots; the dot shown on hover
area(stack_id=)stringnoneAreas with the same value stack on top of each other
area(name=, unit=)stringdata_keyName and unit shown in the tooltip and legend
area(connect_nulls=)True / FalseFalseDraw across empty values (None)
area(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 area. area also has on_animation_start and on_animation_end

Stacked areas (stack_id)

areas with the same stack_id stack one on top of another from the bottom up. The top edge becomes the total, so you can read the overall size and each part at the same time. stack_offset sets the stacking baseline: usually "none", and "expand" when you only care about proportions.

areachart_data = [
    {"month": "Jan", "web": 4000, "app": 2400},
    {"month": "Feb", "web": 3000, "app": 1398},
    {"month": "Mar", "web": 2000, "app": 5800},
    {"month": "Apr", "web": 2780, "app": 3908},
    {"month": "May", "web": 1890, "app": 4800},
    {"month": "Jun", "web": 2390, "app": 3800},
]


rx.recharts.area_chart(
    rx.recharts.area(
        data_key="web",
        stroke=rx.color("accent", 9),
        fill=rx.color("accent", 6),
        stack_id="1",
    ),
    rx.recharts.area(
        data_key="app",
        stroke=rx.color("teal", 9),
        fill=rx.color("teal", 6),
        stack_id="1",
    ),
    rx.recharts.x_axis(data_key="month"),
    rx.recharts.y_axis(),
    rx.recharts.legend(),
    data=areachart_data,
    stack_offset="none",
    margin={"top": 5, "right": 5, "bottom": 5, "left": 5},
    width="100%",
    height=280,
)

Gradient fills

Painting the area dark at the top and transparent at the bottom makes the line stand out. Define an SVG gradient inside the chart with rx.el.svg.defs and point to it with fill="url(#id)". Give each gradient an id that is unique on the page.

areachart_data = [
    {"month": "Jan", "web": 4000, "app": 2400},
    {"month": "Feb", "web": 3000, "app": 1398},
    {"month": "Mar", "web": 2000, "app": 5800},
    {"month": "Apr", "web": 2780, "app": 3908},
    {"month": "May", "web": 1890, "app": 4800},
    {"month": "Jun", "web": 2390, "app": 3800},
]


rx.recharts.area_chart(
    rx.el.svg.defs(
        rx.el.svg.linear_gradient(
            rx.el.svg.stop(offset="5%", stop_color=rx.color("accent", 9), stop_opacity=0.8),
            rx.el.svg.stop(offset="95%", stop_color=rx.color("accent", 9), stop_opacity=0),
            id="areachart_gradient",
            x1=0,
            x2=0,
            y1=0,
            y2=1,
        ),
    ),
    rx.recharts.area(
        data_key="web",
        stroke=rx.color("accent", 9),
        fill="url(#areachart_gradient)",
        type_="natural",
    ),
    rx.recharts.x_axis(data_key="month"),
    rx.recharts.y_axis(),
    rx.recharts.graphing_tooltip(),
    data=areachart_data,
    width="100%",
    height=280,
)

Multiple axes

When you draw two values of completely different magnitudes on one chart, give it two axes. Name each axis with y_axis_id and connect each area to it with the same y_axis_id. The x-axis works the same way with x_axis_id. Two scales confuse readers easily, though, so use this only when the units really differ.

areachart_data = [
    {"month": "Jan", "web": 4000, "app": 2400},
    {"month": "Feb", "web": 3000, "app": 1398},
    {"month": "Mar", "web": 2000, "app": 5800},
    {"month": "Apr", "web": 2780, "app": 3908},
    {"month": "May", "web": 1890, "app": 4800},
    {"month": "Jun", "web": 2390, "app": 3800},
]


rx.recharts.area_chart(
    rx.recharts.area(
        data_key="web",
        stroke=rx.color("accent", 9),
        fill=rx.color("accent", 5),
        y_axis_id="left",
    ),
    rx.recharts.area(
        data_key="app",
        stroke=rx.color("teal", 9),
        fill=rx.color("teal", 5),
        y_axis_id="right",
    ),
    rx.recharts.x_axis(data_key="month"),
    rx.recharts.y_axis(y_axis_id="left"),
    rx.recharts.y_axis(y_axis_id="right", orientation="right"),
    rx.recharts.graphing_tooltip(),
    rx.recharts.legend(),
    data=areachart_data,
    width="100%",
    height=280,
)

Turning it vertical (layout)

With layout="vertical" the areas flow from top to bottom. The axes swap roles too: the x-axis becomes the numbers (type_="number") and the y-axis the categories (type_="category"). Set margin on all four sides so labels don't get cut off.

areachart_data = [
    {"month": "Jan", "web": 4000, "app": 2400},
    {"month": "Feb", "web": 3000, "app": 1398},
    {"month": "Mar", "web": 2000, "app": 5800},
    {"month": "Apr", "web": 2780, "app": 3908},
    {"month": "May", "web": 1890, "app": 4800},
    {"month": "Jun", "web": 2390, "app": 3800},
]


rx.recharts.area_chart(
    rx.recharts.area(
        data_key="web",
        stroke=rx.color("accent", 8),
        fill=rx.color("accent", 3),
    ),
    rx.recharts.x_axis(type_="number"),
    rx.recharts.y_axis(data_key="month", type_="category"),
    data=areachart_data,
    layout="vertical",
    margin={"top": 20, "right": 20, "bottom": 20, "left": 20},
    width="100%",
    height=300,
)

Linking charts (sync_id)

Charts with the same sync_id share their tooltip position and brush range. Hover over the top chart and the bottom one shows the tooltip for the same month; narrow the range with the brush below and the top chart narrows with it. You can link area charts with bar, line and composed charts as well.

areachart_data = [
    {"month": "Jan", "web": 4000, "app": 2400},
    {"month": "Feb", "web": 3000, "app": 1398},
    {"month": "Mar", "web": 2000, "app": 5800},
    {"month": "Apr", "web": 2780, "app": 3908},
    {"month": "May", "web": 1890, "app": 4800},
    {"month": "Jun", "web": 2390, "app": 3800},
]


rx.vstack(
    rx.recharts.area_chart(
        rx.recharts.area(data_key="web", stroke=rx.color("accent", 9), fill=rx.color("accent", 5)),
        rx.recharts.x_axis(data_key="month"),
        rx.recharts.y_axis(),
        rx.recharts.graphing_tooltip(),
        data=areachart_data,
        sync_id="areachart_sync",
        width="100%",
        height=180,
    ),
    rx.recharts.area_chart(
        rx.recharts.area(data_key="app", stroke=rx.color("teal", 9), fill=rx.color("teal", 5)),
        rx.recharts.x_axis(data_key="month"),
        rx.recharts.y_axis(),
        rx.recharts.graphing_tooltip(),
        rx.recharts.brush(data_key="month", height=24),
        data=areachart_data,
        sync_id="areachart_sync",
        width="100%",
        height=210,
    ),
    width="100%",
)

A chart driven by State

Give data a State value and the chart redraws with an animation every time the value changes. Here, clicking the button or an area changes the numbers, and the select box changes type_ from State as well. Assigning a whole new list makes sure the change gets through.

import random
from typing import Any


class AreaChartLiveState(rx.State):
    data: list[dict[str, Any]] = [
        {"month": "Jan", "web": 4000, "app": 2400},
        {"month": "Feb", "web": 3000, "app": 1398},
        {"month": "Mar", "web": 2000, "app": 5800},
        {"month": "Apr", "web": 2780, "app": 3908},
        {"month": "May", "web": 1890, "app": 4800},
        {"month": "Jun", "web": 2390, "app": 3800},
    ]
    curve: str = "monotone"

    @rx.event
    def shuffle(self):
        self.data = [
            {**row, "web": random.randint(500, 6000), "app": random.randint(500, 6000)}
            for row in self.data
        ]

    @rx.event
    def set_curve(self, value: str):
        self.curve = value


rx.vstack(
    rx.hstack(
        rx.button("Shuffle", on_click=AreaChartLiveState.shuffle),
        rx.select(
            ["monotone", "linear", "natural", "step", "basis"],
            value=AreaChartLiveState.curve,
            on_change=AreaChartLiveState.set_curve,
        ),
    ),
    rx.recharts.area_chart(
        rx.recharts.area(
            data_key="web",
            type_=AreaChartLiveState.curve,
            on_click=AreaChartLiveState.shuffle,
        ),
        rx.recharts.area(
            data_key="app",
            type_=AreaChartLiveState.curve,
            stroke=rx.color("teal", 9),
            fill=rx.color("teal", 5),
            on_click=AreaChartLiveState.shuffle,
        ),
        rx.recharts.x_axis(data_key="month"),
        rx.recharts.y_axis(),
        rx.recharts.cartesian_grid(stroke_dasharray="3 3"),
        rx.recharts.legend(),
        data=AreaChartLiveState.data,
        width="100%",
        height=300,
    ),
    width="100%",
)

Filling the order

The two areas are stacked with the same stack_id, and a gradient fades out the bottom. name sets the label shown in the legend and tooltip, and keeping only the horizontal grid lines gives it a calm look.

areachart_data = [
    {"month": "Jan", "web": 4000, "app": 2400},
    {"month": "Feb", "web": 3000, "app": 1398},
    {"month": "Mar", "web": 2000, "app": 5800},
    {"month": "Apr", "web": 2780, "app": 3908},
    {"month": "May", "web": 1890, "app": 4800},
    {"month": "Jun", "web": 2390, "app": 3800},
]


rx.recharts.area_chart(
    rx.el.svg.defs(
        rx.el.svg.linear_gradient(
            rx.el.svg.stop(offset="5%", stop_color=rx.color("accent", 9), stop_opacity=0.7),
            rx.el.svg.stop(offset="95%", stop_color=rx.color("accent", 9), stop_opacity=0.1),
            id="areachart_order_web",
            x1=0, x2=0, y1=0, y2=1,
        ),
        rx.el.svg.linear_gradient(
            rx.el.svg.stop(offset="5%", stop_color=rx.color("teal", 9), stop_opacity=0.7),
            rx.el.svg.stop(offset="95%", stop_color=rx.color("teal", 9), stop_opacity=0.1),
            id="areachart_order_app",
            x1=0, x2=0, y1=0, y2=1,
        ),
    ),
    rx.recharts.cartesian_grid(stroke_dasharray="3 3", vertical=False),
    rx.recharts.area(
        data_key="web",
        name="Web",
        stroke=rx.color("accent", 9),
        stroke_width=2,
        fill="url(#areachart_order_web)",
        stack_id="visits",
    ),
    rx.recharts.area(
        data_key="app",
        name="App",
        stroke=rx.color("teal", 9),
        stroke_width=2,
        fill="url(#areachart_order_app)",
        stack_id="visits",
    ),
    rx.recharts.x_axis(data_key="month"),
    rx.recharts.y_axis(),
    rx.recharts.graphing_tooltip(),
    rx.recharts.legend(),
    data=areachart_data,
    width="100%",
    height=300,
)

Workshop notes

  • Put area(data_key=…) plus x_axis and y_axis as children inside area_chart(data=list).

  • width and height take only numbers or percentage strings. CSS units go on the outer box.

  • The same stack_id stacks areas, and stack_offset="expand" turns it into a 100% proportion chart.

  • Define gradients in rx.el.svg.defs and use them with fill="url(#id)".

  • sync_id links tooltips across charts, and a State value in data brings the chart to life.

← Previous

Tables and data grids · Data Editor

Next →

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