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
Typography

Markdown

rx.markdownrx.markdown.plugin

Official docs

Workshop order

Next to the product review box, add a live preview that shows how the customer's Markdown will look.

rx.markdown takes a Markdown string and renders it as headings, lists, links, code and tables. It follows GitHub Flavored Markdown (GFM) and also handles math and syntax highlighting. Use it wherever the content is defined as text: long notices, help pages, posts written by users. The child must be a single string or State value.

Hello World!

Hello World!

Hello World!

Support us on Github.

Use reflex deploy to deploy your app with a single command.

rx.vstack(
    rx.markdown("## Hello World!"),
    rx.markdown("### Hello World!"),
    rx.markdown("#### Hello World!"),
    rx.markdown("Support us on [Github](https://github.com/reflex-dev/reflex)."),
    rx.markdown("Use `reflex deploy` to deploy your app with **a single command**."),
)

Try the props

What rx.markdown looks like is decided by its content, so in this lab you switch the four plugins that are on by default off and on. Each switch changes one part of the sentence.

Try the props

Old new price. Area: x2+y2x^2 + y^2. Raw HTML. Visit https://reflex.dev

use_gfm

use_math

use_katex

use_raw

rx.markdown("~~Old~~ **new** price. Area: $x^2 + y^2$. <mark>Raw HTML</mark>. Visit https://reflex.dev", use_gfm=True, use_math=True, use_katex=True, use_raw=True)
Turn off use_gfm and strikethrough and automatic URL links disappear; turn off use_math and the math goes; turn off use_raw and HTML tags are no longer interpreted. Turn off only use_katex and the math is not drawn but stays like code.
PropValuesDefaultUse
childone string or State valuerequiredThe Markdown source
component_map{"h1": function, "p": function, …}the site's default mapReflex components that render each Markdown element
use_gfmTrue / FalseTrueGFM (tables, strikethrough, automatic URL links, task lists)
use_mathTrue / FalseTrueParse $…$ math syntax (remark-math)
use_katexTrue / FalseTrueRender math with KaTeX (rehype-katex)
use_rawTrue / FalseTrueInterpret HTML tags in the source (rehype-raw)
use_unwrap_imagesTrue / FalseTrueRemove the <p> wrapped around images
remark_plugins · rehype_pluginslist of rx.markdown.plugin(…)noneAdd plugins

In Reflex 0.10, rx.markdown always renders an outer <div>, and style props such as padding go on that div. The only events are the standard ones.

Math

Anything wrapped in $ is rendered as a LaTeX formula.

Pythagorean theorem: a2+b2=c2a^2 + b^2 = c^2.

rx.markdown("Pythagorean theorem: $a^2 + b^2 = c^2$.")

Because $ is the math delimiter, text with two $ signs turns everything between them into math, and the words vanish or look odd. To show a real $, as in a price, write \$ instead. When you cannot know the content in advance, such as user posts or AI answers, pass it through content.replace("$", "\\$"). Below, the first line breaks and the second shows as written.

Coffee 4,cake4, cake 6.

Coffee $4, cake $6.

rx.vstack(
    rx.markdown("Coffee $4, cake $6."),
    rx.markdown(r"Coffee \$4, cake \$6."),
)

Code blocks and tables

Write a language name after three backticks and you get a syntax-highlighted code block. Separate cells with | and you get a table (GFM). Multi-line strings have their common leading indentation removed automatically.

import reflex as rx

app = rx.App()
app.add_page(index)
rx.markdown(
    """
```python
import reflex as rx

app = rx.App()
app.add_page(index)
```
"""
)
SyntaxDescription
HeaderTitle
ParagraphText
rx.markdown(
    """
| Syntax    | Description |
| --------- | ----------- |
| Header    | Title       |
| Paragraph | Text        |
"""
)

Adding plugins

Beyond the default plugins, you can add remark (Markdown stage) and rehype (HTML stage) plugins with remark_plugins and rehype_plugins. Create one with rx.markdown.plugin(package@version, exported name), and when it needs options, pass a (plugin, options dict) tuple.

# Emoji shortcodes :smile: → emoji characters
rx.markdown(
    "Hello :smile:! :rocket:",
    remark_plugins=[rx.markdown.plugin("remark-emoji@5.0.2", "remarkEmoji")],
)

# Filter untrusted HTML with safe, GitHub-like rules
rx.markdown(
    'Some **bold** text and a <script>alert("XSS")</script>.',
    use_raw=True,
    rehype_plugins=[rx.markdown.plugin("rehype-sanitize@5.0.1", "rehypeSanitize")],
)

# A plugin with options: give headings ids and turn each whole heading into a link to its id
rx.markdown(
    "## Heading 2\n### Heading 3",
    rehype_plugins=[
        rx.markdown.plugin("rehype-slug@6.0.0", "rehypeSlug"),
        (
            rx.markdown.plugin("rehype-autolink-headings@7.1.0", "rehypeAutolinkHeadings"),
            {"behavior": "wrap", "properties": {"className": ["heading-link"]}},
        ),
    ],
)

Every plugin installs a new npm package into the app's frontend, so this page only shows them as code.

component_map: choosing the component for each element

The keys of component_map are Markdown element names (h1, p, code, pre, a …), and the values are functions that take the text and return a Reflex component. pre (code blocks) and a (links) receive **props besides the text, so pass them along: pre carries the language name, a the address. Elements you leave out keep their default look.

Hello World!

Here is some code:

component = rx.text("Hello World!")

And a link to Reflex.

markdown_custom_map = {
    "h1": lambda text: rx.heading(text, as_="h2", size="5", margin_y="0.5em"),
    "p": lambda text: rx.text(text, color_scheme="green", margin_y="0.5em"),
    "code": lambda text: rx.code(text, color_scheme="purple"),
    "pre": lambda text, **props: rx.code_block(text, **props, theme=rx.code_block.themes.dark, margin_y="1em"),
    "a": lambda text, **props: rx.link(text, **props, color_scheme="crimson", underline="always"),
}


rx.markdown(
    r"""
# Hello World!

Here is some `code`:

```python
component = rx.text("Hello World!")
```

And a link to [Reflex](https://reflex.dev/).
""",
    component_map=markdown_custom_map,
)

Filling the order

Keep the content in State and rx.markdown(State.value) re-renders whenever the value changes. Type in the left box and the preview on the right updates at once. Since this is text written by users, use_raw=False keeps HTML tags from being interpreted.

Thanks for the fast delivery!

  • Box was intact
  • Size fits

Rating: 5/5

class MarkdownPreviewState(rx.State):
    source: str = "**Thanks** for the *fast* delivery!\n\n- Box was intact\n- Size fits\n\nRating: `5/5`"

    @rx.event
    def set_source(self, value: str):
        self.source = value


rx.grid(
    rx.text_area(
        value=MarkdownPreviewState.source,
        on_change=MarkdownPreviewState.set_source,
        rows="9",
        width="100%",
    ),
    rx.box(
        rx.markdown(MarkdownPreviewState.source, use_raw=False),
        padding="0 14px",
        border=f"1px solid {rx.color('gray', 6)}",
        border_radius="8px",
        min_height="100%",
    ),
    columns={"initial": "1", "sm": "2"},
    spacing="3",
    width="100%",
)

Workshop notes

  • rx.markdown(one string or State value). GFM, math and HTML are on by default.

  • Turn default plugins off with use_gfm, use_math, use_katex, use_raw and use_unwrap_images.

  • Write a real $ in the text as \$ (prices, AI answers).

  • component_map swaps the component for each element. pre and a receive **props.

  • Use use_raw=False when showing user text. Add plugins with remark_plugins and rehype_plugins.

← Previous

Typography · Code

Next →

Typography · Blockquote

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