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
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.
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**."),
)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: . 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)| Prop | Values | Default | Use |
|---|---|---|---|
| child | one string or State value | required | The Markdown source |
component_map | {"h1": function, "p": function, …} | the site's default map | Reflex components that render each Markdown element |
use_gfm | True / False | True | GFM (tables, strikethrough, automatic URL links, task lists) |
use_math | True / False | True | Parse $…$ math syntax (remark-math) |
use_katex | True / False | True | Render math with KaTeX (rehype-katex) |
use_raw | True / False | True | Interpret HTML tags in the source (rehype-raw) |
use_unwrap_images | True / False | True | Remove the <p> wrapped around images |
remark_plugins · rehype_plugins | list of rx.markdown.plugin(…) | none | Add 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.
Anything wrapped in $ is rendered as a LaTeX formula.
Pythagorean theorem: .
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 6.
Coffee $4, cake $6.
rx.vstack(
rx.markdown("Coffee $4, cake $6."),
rx.markdown(r"Coffee \$4, cake \$6."),
)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)
```
"""
)| Syntax | Description |
|---|---|
| Header | Title |
| Paragraph | Text |
rx.markdown(
"""
| Syntax | Description |
| --------- | ----------- |
| Header | Title |
| Paragraph | Text |
"""
)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.
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.
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,
)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!
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.
Get news about new lessons
We'll email you when this course gets new lessons or a follow-up course opens.
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© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Questions & answers
Ask anything about this lesson. Questions from every language version of this page appear together.