Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions docs/app/reflex_docs/pages/docs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ def get_previews_from_frontmatter(filepath: str) -> dict[str, str]:
recipes_list = defaultdict(list)
docs_ns = SimpleNamespace()

# Maps a library doc's filename-based key (the first element of its component
# list, e.g. "areachart") to a human-friendly display title from frontmatter
# (e.g. "Area Chart"). The sidebar uses this for labels while still deriving the
# URL from the filename key, so titles read correctly without breaking links.
library_display_titles: dict[str, str] = {}

doc_markdown_sources: dict[str, str] = {}


Expand All @@ -158,6 +164,7 @@ def get_previews_from_frontmatter(filepath: str) -> dict[str, str]:
"docs/recipes-overview.md": "Recipes Overview",
"docs/events/special_events.md": "Special Events Docs",
"docs/library/graphing/general/tooltip.md": "Graphing Tooltip",
"docs/library/graphing/general/index.md": "Charts and Data Visualization",
"docs/recipes/content/grid.md": "Grid Recipe",
"docs/hosting/deploy-to-gcp.md": "Deploy to GCP",
}
Expand Down Expand Up @@ -357,14 +364,37 @@ def handle_library_doc(
graphing_components[resolved.category].append(clist)
else:
component_list[resolved.category].append(clist)
# Library docs render via multi_docs (not make_docpage), so without this
# they'd inherit the generic site-wide meta description and a title-cased
# filename (e.g. "Barchart"). Derive a page-specific meta description from
# the doc's frontmatter/body prose, and prefer an explicit frontmatter
# `title:` for a human-friendly, keyword-rich page title.
try:
source: str | None = Path(actual_path).read_text(encoding="utf-8")
document = parse_document(source)
except Exception:
source, document = None, None
Comment thread
greptile-apps[bot] marked this conversation as resolved.
frontmatter = document.frontmatter if document is not None else None
metadata = dict(frontmatter.metadata) if frontmatter is not None else None
description = extract_doc_description(source, metadata) if source else None
display_title = (
frontmatter.title
if frontmatter is not None and frontmatter.title
else resolved.display_title
)
if frontmatter is not None and frontmatter.title:
# clist[0] is the filename-based key the sidebar links from; record the
# frontmatter title so the sidebar can show it as the label instead.
library_display_titles[clist[0]] = display_title
return multi_docs(
path=resolved.route,
virtual_path=doc,
actual_path=actual_path,
previews=previews,
component_list=clist,
title=resolved.display_title,
title=display_title,
ll_component_list=ll_clist,
description=description,
)


Expand All @@ -374,7 +404,7 @@ def get_component_docgen(virtual_doc: str, actual_path: str, title: str):
if resolved is None:
return None

if virtual_doc.startswith("docs/library"):
if virtual_doc.startswith("docs/library") and not virtual_doc.endswith("/index.md"):
return handle_library_doc(virtual_doc, actual_path, title, resolved)

if virtual_doc.startswith(CHANGELOG_VIRTUAL_PREFIX):
Expand Down
5 changes: 3 additions & 2 deletions docs/app/reflex_docs/pages/docs/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,7 @@ def multi_docs(
component_list: list,
title: str,
ll_component_list: list | None = None,
description: str | None = None,
):
components = [
component_docs(component_tuple, previews)
Expand Down Expand Up @@ -990,7 +991,7 @@ def links(current_page, ll_doc_exists, path):
)
return rx.fragment()

@docpage(set_path=path, t=title)
@docpage(set_path=path, t=title, description=description)
def out():
toc = get_docgen_toc(actual_path)
doc_content = Path(actual_path).read_text(encoding="utf-8")
Expand Down Expand Up @@ -1018,7 +1019,7 @@ def out():
class_name="flex flex-col w-full",
)

@docpage(set_path=path + "low", t=title + " (Low Level)")
@docpage(set_path=path + "low", t=title + " (Low Level)", description=description)
def ll():
ll_virtual = virtual_path.replace(".md", "-ll.md")
toc = get_docgen_toc(ll_actual_path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,13 @@ def get_category_children(category, category_list, prefix=""):
link=f"/library/{prefix or ''}{category.lower().replace(' ', '-')}/",
)
)
from reflex_docs.pages.docs import library_display_titles

for c in category_list:
# Prefer a frontmatter-provided display title (e.g. "Area Chart"); fall
# back to deriving one from the filename key (e.g. "Areachart").
item = SideBarItem(
names=get_display_name(c[0]),
names=library_display_titles.get(c[0], get_display_name(c[0])),
link=get_component_link(category, c, prefix=prefix),
)
category_item_children.append(item)
Expand Down
20 changes: 20 additions & 0 deletions docs/app/tests/test_doc_description.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,23 @@ def test_metadata_dict_short_description_falls_through_to_body():
result = extract_doc_description(LONG_PROSE, {"description": "Docs"})
assert result is not None
assert result.startswith("5 minutes of configuration")


def test_chart_frontmatter_meta_description_from_body():
"""A chart-style frontmatter meta_description is extracted from raw markdown.

Mirrors the graphing docs: a ``components:`` list followed by a long
``meta_description``. The list lines must be skipped and the description
returned verbatim (not stitched together with body prose).
"""
long_desc = (
"Create interactive bar charts in Python with Reflex. Build single, "
"stacked, and multi-series Recharts bar charts with custom colors."
)
source = (
"---\ncomponents:\n - rx.recharts.BarChart\n - rx.recharts.Bar\n"
"title: Bar Chart\n"
f"meta_description: {long_desc}\n---\n"
"# Bar Chart\n\nBar charts in Reflex are built on Recharts.\n"
)
assert extract_doc_description(source) == long_desc
16 changes: 13 additions & 3 deletions docs/library/graphing/charts/areachart.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
components:
- rx.recharts.AreaChart
- rx.recharts.Area
title: Area Chart
meta_description: "Create area charts in Python with Reflex. Build stacked, gradient, and multi-series Recharts area charts with custom axes, tooltips, legends, and colors — all in pure Python."
---

# Area Chart
Expand All @@ -11,7 +13,7 @@ import reflex as rx
import random
```

A Recharts area chart displays quantitative data using filled areas between a line connecting data points and the axis.
Area charts in Reflex are built on [Recharts](https://recharts.org/), a React charting library, and created in pure Python. A Recharts area chart displays quantitative data using filled areas between a line connecting data points and the axis.

## Basic Example

Expand Down Expand Up @@ -93,9 +95,9 @@ def area_sync():
)
```

## Stacking Charts
## Stacked Area Chart

The `stack_id` prop allows you to stack multiple graphs on top of each other. In the example, it is set to "1" for both charts, indicating that they should be stacked together. This means that the bars or areas of the charts will be vertically stacked, with the values of each chart contributing to the total height of the stacked areas or bars.
The `stack_id` prop allows you to stack multiple areas on top of each other, creating a stacked area chart. In the example, it is set to "1" for both charts, indicating that they should be stacked together. This means that the areas of the charts will be vertically stacked, with the values of each chart contributing to the total height of the stacked areas.

This is similar to the `sync_id` prop, but instead of synchronizing the interaction between the charts, it just stacks the charts on top of each other.

Expand Down Expand Up @@ -272,3 +274,11 @@ def area_stateful():
width="100%",
)
```

## Related Charts

Explore more chart types you can build with Reflex and Recharts in pure Python:

- [Line Chart](/docs/library/graphing/charts/linechart)
- [Bar Chart](/docs/library/graphing/charts/barchart)
- [Composed Chart](/docs/library/graphing/charts/composedchart)
53 changes: 50 additions & 3 deletions docs/library/graphing/charts/barchart.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
components:
- rx.recharts.BarChart
- rx.recharts.Bar
title: Bar Chart
meta_description: "Create interactive bar charts in Python with Reflex. Build grouped, stacked, and horizontal Recharts bar charts with custom colors, axes, tooltips, and legends — all in pure Python, no JavaScript."
---

# Bar Chart
Expand All @@ -11,7 +13,7 @@ import reflex as rx
import random
```

A bar chart presents categorical data with rectangular bars with heights or lengths proportional to the values that they represent.
Bar charts in Reflex are built on [Recharts](https://recharts.org/), a React charting library, and let you visualize categorical data in pure Python. A bar chart presents categorical data with rectangular bars whose heights or lengths are proportional to the values that they represent.

For a bar chart we must define an `rx.recharts.bar()` component for each set of values we wish to plot. Each `rx.recharts.bar()` component has a `data_key` which clearly states which variable in our data we are tracking. In this simple example we plot `uv` as a bar against the `name` column which we set as the `data_key` in `rx.recharts.x_axis`.

Expand Down Expand Up @@ -46,7 +48,7 @@ def bar_simple():

## Multiple Bars

Multiple bars can be placed on the same `bar_chart`, using multiple `rx.recharts.bar()` components.
Multiple bars can be placed on the same `bar_chart`, using multiple `rx.recharts.bar()` components. Drawn side by side like this, they form a grouped (or clustered) bar chart.

```python demo graphing
data = [
Expand Down Expand Up @@ -80,6 +82,43 @@ def bar_double():
)
```

## Stacked Bar Chart

To build a stacked bar chart, give each `rx.recharts.bar()` the same `stack_id`. Instead of being drawn side by side, the bars are stacked on top of one another, which is ideal for showing part-to-whole composition (also called a segmented bar chart). Set `stack_offset="expand"` on the `bar_chart` to turn it into a 100% stacked bar chart.

```python demo graphing
data = [
{"name": "Page A", "uv": 4000, "pv": 2400, "amt": 2400},
{"name": "Page B", "uv": 3000, "pv": 1398, "amt": 2210},
{"name": "Page C", "uv": 2000, "pv": 9800, "amt": 2290},
{"name": "Page D", "uv": 2780, "pv": 3908, "amt": 2000},
{"name": "Page E", "uv": 1890, "pv": 4800, "amt": 2181},
{"name": "Page F", "uv": 2390, "pv": 3800, "amt": 2500},
{"name": "Page G", "uv": 3490, "pv": 4300, "amt": 2100},
]


def bar_stacked():
return rx.recharts.bar_chart(
rx.recharts.bar(
data_key="uv",
stack_id="1",
fill=rx.color("accent", 8),
),
rx.recharts.bar(
data_key="pv",
stack_id="1",
fill=rx.color("green", 8),
),
rx.recharts.x_axis(data_key="name"),
rx.recharts.y_axis(),
rx.recharts.legend(),
data=data,
width="100%",
height=300,
)
```

## Ranged Charts

You can also assign a range in the bar by assigning the data_key in the `rx.recharts.bar` to a list with two elements, i.e. here a range of two temperatures for each date.
Expand Down Expand Up @@ -189,7 +228,7 @@ def bar_features():

## Vertical Example

The `layout` prop allows you to set the orientation of the graph to be vertical or horizontal, it is set horizontally by default.
The `layout` prop allows you to set the orientation of the graph to be vertical or horizontal, it is set horizontally by default. Setting `layout="vertical"` makes the bars run left-to-right, which is how you create a horizontal bar chart in Reflex.

```md alert info
# Include margins around your graph to ensure proper spacing and enhance readability. By default, provide margins on all sides of the chart to create a visually appealing and functional representation of your data.
Expand Down Expand Up @@ -225,3 +264,11 @@ def bar_vertical():
```

To learn how to use the `sync_id`, `stack_id`,`x_axis_id` and `y_axis_id` props check out the of the area chart [documentation](/docs/library/graphing/charts/areachart), where these props are all described with examples.

## Related Charts

Explore more chart types you can build with Reflex and Recharts in pure Python:

- [Line Chart](/docs/library/graphing/charts/linechart)
- [Area Chart](/docs/library/graphing/charts/areachart)
- [Composed Chart](/docs/library/graphing/charts/composedchart)
58 changes: 57 additions & 1 deletion docs/library/graphing/charts/composedchart.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
components:
- rx.recharts.ComposedChart
title: Composed Chart
meta_description: "Build composed charts in Python with Reflex. Combine bars, lines, and areas in a single Recharts composed chart with shared axes, tooltips, and legends — all in pure Python."
---

```python exec
Expand All @@ -9,7 +11,7 @@ import reflex as rx

# Composed Chart

A `composed_chart` is a higher-level component chart that is composed of multiple charts, where other charts are the children of the `composed_chart`. The charts are placed on top of each other in the order they are provided in the `composed_chart` function.
Composed charts in Reflex are built on [Recharts](https://recharts.org/), a React charting library, and created in pure Python. A `composed_chart` (also called a combo chart) is a higher-level component chart that is composed of multiple charts, where other charts are the children of the `composed_chart`. The charts are placed on top of each other in the order they are provided in the `composed_chart` function.

```md alert info
# To learn more about individual charts, checkout: **[area_chart](/docs/library/graphing/charts/areachart)**, **[line_chart](/docs/library/graphing/charts/linechart)**, or **[bar_chart](/docs/library/graphing/charts/barchart)**.
Expand Down Expand Up @@ -41,3 +43,57 @@ def composed():
width="100%",
)
```

## When to Use a Composed Chart

A composed chart is useful whenever a single chart type can't tell the whole story. Common combinations include overlaying a trend `line` on top of `bar` totals, drawing an `area` for a range with a `line` for the actual value, or comparing a cumulative measure against a per-period one. Because each series — `rx.recharts.bar()`, `rx.recharts.line()`, and `rx.recharts.area()` — is a child of `rx.recharts.composed_chart()`, they all share the same `data`, x-axis, tooltip, and legend. Series are drawn in the order you list them, so later children render on top of earlier ones.

## Composed Chart with a Dual Axis

When two series use very different scales (for example, a count and a dollar amount), a single y-axis makes the smaller series unreadable. Add a second y-axis and point each series at one with the `y_axis_id` prop: here the `orders` bars use the left axis and the `revenue` line uses the right axis.

```python demo graphing
data = [
{"name": "Mon", "orders": 40, "revenue": 2400},
{"name": "Tue", "orders": 30, "revenue": 1398},
{"name": "Wed", "orders": 55, "revenue": 9800},
{"name": "Thu", "orders": 27, "revenue": 3908},
{"name": "Fri", "orders": 62, "revenue": 4800},
{"name": "Sat", "orders": 48, "revenue": 3800},
{"name": "Sun", "orders": 35, "revenue": 4300},
]


def composed_dual_axis():
return rx.recharts.composed_chart(
rx.recharts.bar(
data_key="orders",
bar_size=20,
fill=rx.color("accent", 8),
y_axis_id="left",
),
rx.recharts.line(
data_key="revenue",
type_="monotone",
stroke=rx.color("green", 9),
y_axis_id="right",
),
rx.recharts.x_axis(data_key="name"),
rx.recharts.y_axis(y_axis_id="left"),
rx.recharts.y_axis(y_axis_id="right", orientation="right"),
rx.recharts.cartesian_grid(stroke_dasharray="3 3"),
rx.recharts.graphing_tooltip(),
rx.recharts.legend(),
data=data,
height=300,
width="100%",
)
```

## Related Charts

Explore more chart types you can build with Reflex and Recharts in pure Python:

- [Bar Chart](/docs/library/graphing/charts/barchart)
- [Line Chart](/docs/library/graphing/charts/linechart)
- [Area Chart](/docs/library/graphing/charts/areachart)
Loading
Loading