diff --git a/docs/app/reflex_docs/pages/docs/component.py b/docs/app/reflex_docs/pages/docs/component.py index 1c6bfd89137..df5ec11b21b 100644 --- a/docs/app/reflex_docs/pages/docs/component.py +++ b/docs/app/reflex_docs/pages/docs/component.py @@ -28,7 +28,10 @@ render_inline_markdown, render_markdown, ) -from reflex_docs.pages.docs.metadata import truncate_meta_description +from reflex_docs.pages.docs.metadata import ( + component_title_name, + truncate_meta_description, +) from reflex_docs.templates.docpage import docpage, h2_comp @@ -1038,6 +1041,7 @@ def links(current_page, ll_doc_exists, path): description=description, image=image, source_path=actual_path, + component_name=component_title_name([c[1] for c in component_list[1:]]), ) def out(): toc = get_docgen_toc(actual_path) @@ -1090,6 +1094,7 @@ def out(): description=ll_description, image=image, source_path=ll_actual_path, + component_name=component_title_name([c[1] for c in ll_list[1:]]), ) def ll(): ll_virtual = virtual_path.replace(".md", "-ll.md") diff --git a/docs/app/reflex_docs/pages/docs/library.py b/docs/app/reflex_docs/pages/docs/library.py index 2f6c8a2be87..4a35935bf5e 100644 --- a/docs/app/reflex_docs/pages/docs/library.py +++ b/docs/app/reflex_docs/pages/docs/library.py @@ -1,17 +1,9 @@ import reflex as rx -from reflex.utils.format import to_snake_case, to_title_case +from reflex.utils.format import to_snake_case +from reflex_docs.docgen_pipeline import render_markdown from reflex_docs.templates.docpage import docpage, h1_comp, h2_comp, text_comp_2 - - -def get_display_name(name: str) -> str: - normalized = to_snake_case(name) - if normalized == "html": - return "HTML" - if normalized == "svg": - return "SVG" - return to_title_case(normalized, sep=" ") - +from reflex_docs.utils.library import get_display_name HTML_COMPONENT_ORDER = { "html": 0, @@ -114,10 +106,43 @@ def generate_gallery( ) +LIBRARY_FAQ = """## How Reflex components compare + +Like Streamlit widgets, Reflex components are written in Python, but Reflex gives you full control over layout and styling. Instead of rerunning the whole script on each interaction as Streamlit does, Reflex runs event handlers that update state, and only the parts of the UI that depend on that state re-render. NiceGUI and Gradio also build web UIs in Python. Reflex's library covers forms, layouts, overlays, data tables, a spreadsheet-style data editor, and charts, with enterprise AG Grid and AG Charts components for data-heavy apps. + +## Frequently asked questions + +### Can I use Reflex components without learning React? + +Yes. Reflex components compile to React on the frontend, but you write everything in Python. You never touch JavaScript, JSX, or React hooks. + +### Do Reflex components work with pandas DataFrames? + +Yes. [`rx.data_table`](/docs/library/tables-and-data-grids/data-table/) takes a pandas DataFrame directly, with built-in search, sorting, and pagination. For editable grids, use [`rx.data_editor`](/docs/library/tables-and-data-grids/data-editor/) or the enterprise [AG Grid](/docs/enterprise/ag-grid/) component. + +### Can I style Reflex components with custom CSS? + +Yes. Every component accepts style props and a `class_name` prop. With the [Tailwind plugin](/docs/styling/tailwind/) enabled, you can pass Tailwind utility classes to `class_name`. For animations, keyframes, or other global styles, add [custom stylesheets](/docs/styling/custom-stylesheets/). + +### Are Reflex components accessible? + +Many core components are built on Radix UI primitives, which follow WAI-ARIA patterns and include keyboard navigation, focus management, and screen reader support. + +### Can I wrap my own React components? + +Yes. Reflex can wrap any React component from npm: declare its props and events in Python and Reflex generates the bindings. See the [wrapping React guide](/docs/wrapping-react/overview/). + +### Do I need to install components separately? + +No. All core components are included when you install Reflex. For enterprise components like AG Grid and AG Charts, install the `reflex-enterprise` package. +""" + + @docpage( set_path="/library/", right_sidebar=True, pseudo_right_bar=True, + page_title="Python UI Component Library · Reflex Docs", ) def library(): return rx.box( @@ -125,9 +150,10 @@ def library(): text="Component Library", ), text_comp_2( - text="Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. This page contains a list of all builtin components.", + text="Reflex provides 100+ UI components that work entirely in Python — no HTML, CSS, or JavaScript required. Build forms, tables, data grids, charts, and complete web interfaces using familiar Python syntax. Each component is fully documented with examples and integrates directly with your Python state.", ), component_grid(), + rx.el.div(render_markdown(LIBRARY_FAQ), class_name="mt-8"), rx.el.p( "Connect your components to data and events with the ", rx.el.a( diff --git a/docs/app/reflex_docs/pages/docs/metadata.py b/docs/app/reflex_docs/pages/docs/metadata.py index 345a1ed3d5b..a1640e014d5 100644 --- a/docs/app/reflex_docs/pages/docs/metadata.py +++ b/docs/app/reflex_docs/pages/docs/metadata.py @@ -1,10 +1,24 @@ """SEO metadata helpers for docs routes.""" +from collections.abc import Sequence +from os.path import commonprefix + +from reflex.utils.format import to_snake_case + GENERIC_DESCRIPTION_TEMPLATE = "{subject}: documentation, examples, and reference for building Python web applications with Reflex." +# Frontmatter components documented under a different public constructor. +_PUBLIC_NAME_OVERRIDES = { + "rx.lucide.Icon": "rx.icon", + "rx.toast.provider": "rx.toast", +} + +# Namespaces too broad to name a page on their own. +_GENERIC_NAMESPACES = {"", "rx", "rx.recharts"} + # Summaries for generated catalogs, reference pages, and pages without usable prose. PAGE_DESCRIPTIONS = { - "library": "Browse Reflex UI components for forms, layouts, data display, charts, and media, with Python examples and prop references.", + "library": "Build web UIs in pure Python with 100+ Reflex components for forms, tables, data grids, charts, layouts, and media. No JavaScript required.", "recipes": "Find reusable Reflex recipes for page layouts, content, and authentication, with examples you can adapt for your Python app.", "api-reference/app": "Configure rx.App, register pages, and customize application behavior with the App class attributes and methods reference.", "api-reference/component": "Explore the Component API for creating Reflex UI elements, managing props, and customizing component rendering and behavior.", @@ -38,6 +52,44 @@ } +def component_title_name(components: Sequence[str]) -> str | None: + """Return the public name a component page should lead its title with. + + Frontmatter lists implementation names (``rx.recharts.AreaChart``, + ``rx.dialog.root``); search titles need the name users call. Pages that + share one namespace use it (``rx.dialog``); otherwise the first, + primary component is used. HTML element collections get no name. + + Args: + components: The component names from a doc's frontmatter. + + Returns: + The public component name, or None when the page has none. + """ + names = list(dict.fromkeys(_public_component_name(c) for c in components)) + if not names or any(name.startswith("rx.el.") for name in names): + return None + namespace = ".".join(commonprefix([name.split(".") for name in names])) + return names[0] if namespace in _GENERIC_NAMESPACES else namespace + + +def _public_component_name(component: str) -> str: + """Map a frontmatter component reference to the name users call. + + Args: + component: A frontmatter component reference. + + Returns: + The public constructor name. + """ + if component in _PUBLIC_NAME_OVERRIDES: + return _PUBLIC_NAME_OVERRIDES[component] + module, _, name = component.rpartition(".") + if module == "rx.recharts": + return f"{module}.{to_snake_case(name)}" + return component.removesuffix(".root") + + def truncate_meta_description(description: str, max_len: int = 155) -> str: """Return a search-snippet-safe meta description. @@ -58,13 +110,20 @@ def truncate_meta_description(description: str, max_len: int = 155) -> str: return f"{truncated}…" -def docs_metadata(path: str, title: str, description: str | None) -> tuple[str, str]: +def docs_metadata( + path: str, + title: str, + description: str | None, + component_name: str | None = None, +) -> tuple[str, str]: """Build distinct search snippets using the page's product hierarchy. Args: path: The app-relative documentation route. title: The page heading. description: A summary extracted from the document, when available. + component_name: The public component name a library page documents, + which leads the title in place of the breadcrumb. Returns: The search title and description. @@ -101,4 +160,7 @@ def docs_metadata(path: str, title: str, description: str | None) -> tuple[str, summary = ( description or fallback or GENERIC_DESCRIPTION_TEMPLATE.format(subject=subject) ) - return f"{subject} · Reflex Docs", truncate_meta_description(summary) + heading = ( + f"{component_name}: Python {title} Component" if component_name else subject + ) + return f"{heading} · Reflex Docs", truncate_meta_description(summary) diff --git a/docs/app/reflex_docs/pages/library_previews.py b/docs/app/reflex_docs/pages/library_previews.py index 69fe89c3676..94b6afbafe7 100644 --- a/docs/app/reflex_docs/pages/library_previews.py +++ b/docs/app/reflex_docs/pages/library_previews.py @@ -1,20 +1,11 @@ import reflex as rx -from reflex.utils.format import to_snake_case, to_title_case +from reflex.utils.format import to_snake_case from reflex_site_shared.constants import REFLEX_ASSETS_CDN from reflex_docs.docgen_pipeline import render_markdown from reflex_docs.pages.docs.metadata import truncate_meta_description from reflex_docs.templates.docpage import docpage, h1_comp, text_comp_2 - - -def get_display_name(name: str) -> str: - normalized = to_snake_case(name) - if normalized == "html": - return "HTML" - if normalized == "svg": - return "SVG" - return to_title_case(normalized, sep=" ") - +from reflex_docs.utils.library import get_display_name HTML_COMPONENT_ORDER = { "html": 0, @@ -129,6 +120,28 @@ def get_component_list(component_type: str = "core"): raise ValueError(f"Unknown component type: {component_type}") +CHARTS_GUIDE = """## Choosing a charting library + +- **[Recharts](/docs/library/graphing/charts/)** (built in): declarative charts with a simple API for standard business charts like bar, line, area, and pie. Good for dashboards and reports. +- **[Plotly](/docs/library/graphing/other-charts/plotly/)** (`rx.plotly`): interactive scientific charts with zoom, pan, and hover, including 3D plots, contours, and statistical charts. +- **[Matplotlib](/docs/library/graphing/other-charts/pyplot/)** (`pyplot`): render any `matplotlib.pyplot` figure as a static image. Best when you already have Matplotlib code from notebooks or scripts. +- **AG Charts** (enterprise): high-performance charts with animations and advanced features. See the [AG Charts docs](/docs/enterprise/ag-chart/) for examples. +""" + +# Markdown guides shown between a category's intro and its component cards. +CATEGORY_GUIDES = { + "Tables-And-Data-Grids": """## Which table component should I use? + +- **`rx.table`**: a composable semantic table. Build headers, rows, and cells yourself for full control over structure and styling. Best for small datasets and custom layouts. +- **`rx.data_table`**: pass a pandas DataFrame or a list of rows and turn on search, sorting, and pagination with `search=True`, `sort=True`, and `pagination=True`. Read-only; best for displaying data from CSV files or database queries. +- **`rx.data_editor`**: a spreadsheet-like grid with cell selection and inline editing. Use it when users edit data directly, as in an admin panel or data entry form. +- **AG Grid** (enterprise): advanced filtering, column pivoting, row grouping, master-detail, tree data, and Excel export. See the [AG Grid docs](/docs/enterprise/ag-grid/) to get started. +""", + "Charts": CHARTS_GUIDE, + "Other-Charts": CHARTS_GUIDE, +} + + def create_previews( path: str, description: str, @@ -151,7 +164,7 @@ def page() -> rx.Component: component_list = get_component_list(type) if component_category == "State": - return rx.box( + return rx.el.div( h1_comp(text="State"), render_markdown( "Reflex state connects your components to application data. " @@ -175,15 +188,17 @@ def page() -> rx.Component: ), class_name="docs-library flex min-w-0 flex-col w-full mb-10", ) - return rx.box( - rx.box( + guide = CATEGORY_GUIDES.get(component_category) + return rx.el.div( + rx.el.div( h1_comp(text=get_display_name(component_category)), text_comp_2( text=description, ), class_name="flex flex-col w-full", ), - rx.box( + *([rx.el.div(render_markdown(guide), class_name="mb-8")] if guide else []), + rx.el.div( *[ component_card( name=component[0], @@ -259,7 +274,7 @@ def page() -> rx.Component: }, "tables_and_data_grids": { "path": "tables-and-data-grids", - "description": "Build tables and data grids in Python with Reflex. Includes a composable table, a searchable and sortable data table for pandas DataFrames, and an editable data grid — perfect for dashboards and data apps, all in pure Python.", + "description": "Build tables and data grids in Python with Reflex. Use rx.table for simple semantic tables, rx.data_table for searchable pandas DataFrames, rx.data_editor for spreadsheet-style editing, or the enterprise AG Grid component for advanced features like filtering, pivoting, and cell selection. All in pure Python.", "component_category": "Tables-And-Data-Grids", }, "typography": { diff --git a/docs/app/reflex_docs/templates/docpage/docpage.py b/docs/app/reflex_docs/templates/docpage/docpage.py index 04299b581ef..6b8dd0563ae 100644 --- a/docs/app/reflex_docs/templates/docpage/docpage.py +++ b/docs/app/reflex_docs/templates/docpage/docpage.py @@ -373,6 +373,7 @@ def docpage( image: str | None = None, source_path: str | None = None, show_breadcrumb: bool = True, + component_name: str | None = None, ): """A template that most pages on the reflex.dev site should use. @@ -392,6 +393,8 @@ def docpage( "Edit this page" link. Defaults to the Python file defining the page. show_breadcrumb: Whether to display the page breadcrumb. Mobile sidebar access remains available when the breadcrumb is hidden. + component_name: The public component name a library page documents, + used to lead its search title. Returns: A wrapper function that returns the full webpage. @@ -538,7 +541,9 @@ def wrapper(*args, **kwargs) -> rx.Component: from reflex_docs.pages.docs.metadata import docs_metadata - seo_title, seo_description = docs_metadata(path, title, description) + seo_title, seo_description = docs_metadata( + path, title, description, component_name + ) if page_title: seo_title = page_title diff --git a/docs/app/reflex_docs/templates/docpage/sidebar/sidebar_items/component_lib.py b/docs/app/reflex_docs/templates/docpage/sidebar/sidebar_items/component_lib.py index 526e789c2d6..012ae62b429 100644 --- a/docs/app/reflex_docs/templates/docpage/sidebar/sidebar_items/component_lib.py +++ b/docs/app/reflex_docs/templates/docpage/sidebar/sidebar_items/component_lib.py @@ -1,16 +1,9 @@ import reflex as rx -from reflex.utils.format import to_snake_case, to_title_case - -from ..state import SideBarItem +from reflex.utils.format import to_snake_case +from reflex_docs.utils.library import get_display_name -def get_display_name(name: str) -> str: - normalized = to_snake_case(name) - if normalized == "html": - return "HTML" - if normalized == "svg": - return "SVG" - return to_title_case(normalized, sep=" ") +from ..state import SideBarItem def is_html_category(category: str) -> bool: diff --git a/docs/app/reflex_docs/utils/library.py b/docs/app/reflex_docs/utils/library.py new file mode 100644 index 00000000000..4ec1a152a4d --- /dev/null +++ b/docs/app/reflex_docs/utils/library.py @@ -0,0 +1,21 @@ +"""Naming helpers shared by the component library pages and sidebar.""" + +from reflex.utils.format import to_snake_case, to_title_case + + +def get_display_name(name: str) -> str: + """Turn a library category or component key into a display label. + + Args: + name: A key such as ``Data-Display`` or ``data_table``. + + Returns: + The title-cased label, e.g. ``Data Display``. + """ + # Dashed keys like "Data-Display" snake-case to "data__display". + normalized = to_snake_case(name).replace("__", "_") + if normalized == "html": + return "HTML" + if normalized == "svg": + return "SVG" + return to_title_case(normalized, sep=" ") diff --git a/docs/app/tests/test_routes.py b/docs/app/tests/test_routes.py index 195e4d1b1d8..5efccb6491e 100644 --- a/docs/app/tests/test_routes.py +++ b/docs/app/tests/test_routes.py @@ -9,7 +9,7 @@ import pytest import reflex as rx -from reflex_docs.pages.docs.metadata import docs_metadata +from reflex_docs.pages.docs.metadata import component_title_name, docs_metadata @pytest.mark.parametrize( @@ -22,6 +22,38 @@ def test_metadata_preserves_acronyms_and_code_identifiers(title, expected): assert seo_title.startswith(expected + " · ") +@pytest.mark.parametrize( + ("components", "expected"), + [ + (["rx.data_table"], "rx.data_table"), + (["rx.input.slot"], "rx.input.slot"), + (["rx.lucide.Icon"], "rx.icon"), + (["rx.toast.provider"], "rx.toast"), + (["rx.dialog.root", "rx.dialog.trigger", "rx.dialog.content"], "rx.dialog"), + (["rx.text", "rx.text.em"], "rx.text"), + (["rx.recharts.AreaChart", "rx.recharts.Area"], "rx.recharts.area_chart"), + (["rx.recharts.GraphingTooltip"], "rx.recharts.graphing_tooltip"), + (["rx.stack", "rx.hstack", "rx.vstack"], "rx.stack"), + (["pyplot"], "pyplot"), + (["rx.el.abbr", "rx.el.b"], None), + (["rx.el.svg.circle", "rx.el.svg.rect"], None), + ([], None), + ], +) +def test_component_title_name(components, expected): + """Library titles lead with the public name users call.""" + assert component_title_name(components) == expected + + +def test_metadata_component_title_keeps_breadcrumb_description(): + """A component name leads the title, not the generic description.""" + title, description = docs_metadata( + "/library/overlay/dialog/", "Dialog", None, component_name="rx.dialog" + ) + assert title == "rx.dialog: Python Dialog Component · Reflex Docs" + assert description.startswith("Dialog · Overlay · Library: documentation") + + @pytest.fixture def routes_fixture(): from reflex_docs.pages import routes @@ -462,3 +494,45 @@ def test_routes_have_specific_descriptions(routes_fixture): ) ] assert not failures, failures + + +@pytest.mark.parametrize( + ("path", "expected"), + [ + ("/library/", "Python UI Component Library · Reflex Docs"), + ( + "/library/tables-and-data-grids/", + "Tables And Data Grids Component Library · Reflex Docs", + ), + ( + "/library/tables-and-data-grids/data-table/", + "rx.data_table: Python Data Table Component · Reflex Docs", + ), + ( + "/library/overlay/dialog/", + "rx.dialog: Python Dialog Component · Reflex Docs", + ), + ("/library/data-display/icon/", "rx.icon: Python Icon Component · Reflex Docs"), + ( + "/library/graphing/charts/areachart/", + "rx.recharts.area_chart: Python Area Chart Component · Reflex Docs", + ), + ( + "/library/forms/select/low/", + "rx.select: Python Select (Low Level) Component · Reflex Docs", + ), + ( + "/library/forms/input/low/", + "rx.input.slot: Python Input (Low Level) Component · Reflex Docs", + ), + ("/library/html/text/", "Text · HTML · Library · Reflex Docs"), + ( + "/library/dynamic-rendering/foreach/", + "Foreach · Dynamic Rendering · Library · Reflex Docs", + ), + ], +) +def test_library_route_titles(routes_fixture, path, expected): + """Published library pages carry the final title search engines see.""" + titles = {route.path: route.seo_title or route.title for route in routes_fixture} + assert titles[path] == expected diff --git a/docs/library/forms/checkbox.md b/docs/library/forms/checkbox.md index 1a941c649fa..717fc714ffb 100644 --- a/docs/library/forms/checkbox.md +++ b/docs/library/forms/checkbox.md @@ -1,6 +1,7 @@ --- components: - rx.checkbox +meta_description: "Add checkboxes to Python web forms with Reflex. rx.checkbox captures true/false input with state and form integration, all in pure Python." HighLevelCheckbox: | lambda **props: rx.checkbox("Basic Checkbox", **props) diff --git a/docs/library/forms/select.md b/docs/library/forms/select.md index e33f311ae2e..0b99c88423f 100644 --- a/docs/library/forms/select.md +++ b/docs/library/forms/select.md @@ -1,6 +1,7 @@ --- components: - rx.select +meta_description: "Build dropdown select menus in Python with Reflex. rx.select creates dropdowns from a list, with state binding and form integration." HighLevelSelect: | lambda **props: rx.select(["apple", "grape", "pear"], default_value="pear", **props) diff --git a/docs/library/graphing/other-charts/pyplot.md b/docs/library/graphing/other-charts/pyplot.md index 509715ab529..f0540483f6b 100644 --- a/docs/library/graphing/other-charts/pyplot.md +++ b/docs/library/graphing/other-charts/pyplot.md @@ -23,6 +23,18 @@ Pyplot (`reflex-pyplot`) lets you render any [Matplotlib](https://matplotlib.org `matplotlib.pyplot` is a collection of functions that make Matplotlib behave like MATLAB: each call (`plt.plot`, `plt.scatter`, `plt.bar`, and so on) builds up a figure by adding lines, bars, labels, or legends. In a normal script you would finish with `plt.show()` to open a window. In a Reflex app you instead pass the `Figure` object to the `pyplot` component, which serves it to the frontend and re-renders it whenever your state changes. +## Why use Matplotlib in a web app? + +Matplotlib is the most widely used plotting library in Python, with millions of users in scientific computing, data science, and machine learning. If you already have matplotlib code from Jupyter notebooks, research scripts, or data pipelines, you can reuse it directly in a Reflex web app without rewriting it for a different charting library. Common use cases include: + +- **Data science dashboards** — Turn notebook prototypes into shareable web apps with interactive controls +- **Scientific reports** — Display publication-quality figures with LaTeX labels and custom styling +- **Machine learning monitoring** — Plot training metrics, confusion matrices, and feature distributions +- **Financial analysis** — Render time series and portfolio performance charts +- **Engineering tools** — Visualize simulation results, sensor data, and system performance + +For declarative business charts like bar, line, and pie charts, consider using Reflex's built-in [Recharts components](/docs/library/graphing/charts/) instead. For interactive 3D plots and scientific visualizations, see the [Plotly component](/docs/library/graphing/other-charts/plotly/). + ## Installation Install the `reflex-pyplot` package using pip. diff --git a/docs/library/overlay/dialog.md b/docs/library/overlay/dialog.md index 08b965b7619..4b1c37c6f2d 100644 --- a/docs/library/overlay/dialog.md +++ b/docs/library/overlay/dialog.md @@ -6,6 +6,7 @@ components: - rx.dialog.content - rx.dialog.description - rx.dialog.close +meta_description: "Create modal dialogs in Python with Reflex. rx.dialog displays accessible modal windows with a title, description, and custom content." only_low_level: - True diff --git a/docs/library/overlay/drawer.md b/docs/library/overlay/drawer.md index 9c9b7b7e07e..e26b4699881 100644 --- a/docs/library/overlay/drawer.md +++ b/docs/library/overlay/drawer.md @@ -6,6 +6,7 @@ components: - rx.drawer.portal - rx.drawer.content - rx.drawer.close +meta_description: "Build slide-out panels and sidebars in Python with Reflex. rx.drawer creates accessible drawers from any screen edge, with state control and overlays." only_low_level: - True diff --git a/docs/library/overlay/hover_card.md b/docs/library/overlay/hover_card.md index 5b634528bda..2e6a5daf7dd 100644 --- a/docs/library/overlay/hover_card.md +++ b/docs/library/overlay/hover_card.md @@ -3,6 +3,7 @@ components: - rx.hover_card.root - rx.hover_card.content - rx.hover_card.trigger +meta_description: "Display rich hover cards in Python with Reflex. rx.hover_card shows detailed content on hover, for link previews and custom layouts." only_low_level: - True diff --git a/docs/library/tables-and-data-grids/data_table.md b/docs/library/tables-and-data-grids/data_table.md index c181c6ca677..8bc1c356188 100644 --- a/docs/library/tables-and-data-grids/data_table.md +++ b/docs/library/tables-and-data-grids/data_table.md @@ -13,11 +13,11 @@ import reflex as rx Reflex's data table component (`rx.data_table`) is a great way to display static data — such as a pandas DataFrame — as an interactive table in pure Python. You can pass a pandas dataframe to the data prop to create the table, with built-in search, sorting, and pagination. -In this example we will read data from a csv file, convert it to a pandas dataframe and display it in a data_table. +If you want to [add, edit or remove data](/docs/library/tables-and-data-grids/table/) in your app or deal with anything but static data then the [`rx.table`](/docs/library/tables-and-data-grids/table/) might be a better fit for your use case. -We will also add a search, pagination, sorting to the data_table to make it more accessible. +## Basic Example -If you want to [add, edit or remove data](/docs/library/tables-and-data-grids/table/) in your app or deal with anything but static data then the [`rx.table`](/docs/library/tables-and-data-grids/table/) might be a better fit for your use case. +The data_table component displays tabular data with optional search, sorting, and pagination features. ```python demo box rx.data_table( @@ -40,33 +40,106 @@ rx.data_table( ) ``` +## Using pandas DataFrames + +The data_table component works seamlessly with pandas DataFrames. Pass the DataFrame directly to the `data` prop and the column names are extracted automatically. + ```python import pandas as pd +import reflex as rx nba_data = pd.read_csv("data/nba.csv") -... + + +def index(): + return rx.data_table( + data=nba_data[["Name", "Height", "Age"]], + pagination=True, + search=True, + sort=True, + ) +``` + +📊 **Dataset source:** [nba.csv](https://media.geeksforgeeks.org/wp-content/uploads/nba.csv) + +## Sorting + +Enable sorting by setting `sort=True`. Users can click column headers to sort ascending or descending. + +```python +rx.data_table( + data=nba_data[["Name", "Team", "Salary"]], + sort=True, +) +``` + +You can also programmatically control the default sort order in your state: + +```python +class TableState(rx.State): + data: pd.DataFrame = pd.read_csv("data/nba.csv") + + @rx.var + def sorted_data(self) -> pd.DataFrame: + return self.data.sort_values("Name") + + +def index(): + return rx.data_table( + data=TableState.sorted_data, + sort=True, + ) +``` + +## Pagination + +Enable pagination by setting `pagination=True`. This automatically splits large datasets into pages and adds navigation controls. By default, the table shows 10 rows per page. + +```python rx.data_table( - data=nba_data[["Name", "Height", "Age"]], + data=nba_data, pagination=True, +) +``` + +## Search + +Enable search by setting `search=True`. The search box filters rows across all columns in real time as the user types. + +```python +rx.data_table( + data=nba_data, search=True, - sort=True, ) ``` -📊 **Dataset source:** [nba.csv](https://media.geeksforgeeks.org/wp-content/uploads/nba.csv) +Search is case-insensitive and matches partial strings. When combined with pagination, search results are automatically paginated. + +## Complete Example with State -The example below shows how to create a data table from from a list. +The example below builds a data table from rows and columns stored in state. Any event handler that updates `TableState.data` re-renders the table. ```python -class State(rx.State): - data: List = [["Lionel", "Messi", "PSG"], ["Christiano", "Ronaldo", "Al-Nasir"]] - columns: List[str] = ["First Name", "Last Name"] +import reflex as rx + + +class TableState(rx.State): + data: list[list[str]] = [ + ["Lionel", "Messi", "Argentina"], + ["Cristiano", "Ronaldo", "Portugal"], + ["Neymar", "Jr", "Brazil"], + ["Kylian", "Mbappé", "France"], + ] + columns: list[str] = ["First Name", "Last Name", "Country"] def index(): return rx.data_table( - data=State.data, - columns=State.columns, + data=TableState.data, + columns=TableState.columns, + pagination=True, + search=True, + sort=True, ) ``` @@ -74,6 +147,7 @@ def index(): Explore the other ways to work with tabular data in Reflex, all in pure Python: -- [Table](/docs/library/tables-and-data-grids/table/) -- [Data Editor](/docs/library/tables-and-data-grids/data-editor/) -- [Tables and Data Grids](/docs/library/tables-and-data-grids/) +- [Table](/docs/library/tables-and-data-grids/table/) — Composable semantic table for custom layouts +- [Data Editor](/docs/library/tables-and-data-grids/data-editor/) — Spreadsheet-style editable data grid +- [Tables and Data Grids](/docs/library/tables-and-data-grids/) — Overview of all table components +- [AG Grid](/docs/enterprise/ag-grid/) — Enterprise data grid with advanced features diff --git a/docs/library/typography/blockquote.md b/docs/library/typography/blockquote.md index ace089e28b2..5c5e9c0343b 100644 --- a/docs/library/typography/blockquote.md +++ b/docs/library/typography/blockquote.md @@ -1,6 +1,7 @@ --- components: - rx.blockquote +meta_description: "Add semantic blockquotes to your Python web app with Reflex. The rx.blockquote component displays quoted text with multiple size and weight options." --- ```python exec diff --git a/docs/library/typography/code.md b/docs/library/typography/code.md index 8db6cf613b2..8caf05eae14 100644 --- a/docs/library/typography/code.md +++ b/docs/library/typography/code.md @@ -1,6 +1,7 @@ --- components: - rx.code +meta_description: "Display inline code in Python with Reflex. The rx.code component renders monospaced code text with variants and color schemes, all in pure Python." --- ```python exec