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
When someone hovers over an author's name on a comment, show a small card with that person's photo and bio.
rx.hover_card is a card that pops up when you hover over an element such as a link. It is bigger than a tooltip and is meant for previews with rich content, such as a photo or several lines of text. It is built from three parts.
hover_card.root: wraps all the parts of the hover card.hover_card.trigger: wraps the element (usually a link) that opens the card on hover.hover_card.content: the content shown when it is open.Hover over the text to see the card. Hover over me
rx.text(
"Hover over the text to see the card. ",
rx.hover_card.root(
rx.hover_card.trigger(
rx.link("Hover over me", color_scheme="blue", underline="always"),
),
rx.hover_card.content(
rx.text("This is the hovercard content."),
),
),
)Placement and size go on hover_card.content. Change a value, then hover over the link.
Try the props
text
side
align
size
avoid_collisions
rx.hover_card.root(
rx.hover_card.trigger(rx.link("Hover over me", underline="always")),
rx.hover_card.content(
rx.text("Preview of the linked page"),
side="bottom",
align="center",
size="2",
avoid_collisions=True,
),
)| Part | Prop | Values | Use |
|---|---|---|---|
root | open_delay | milliseconds (int) | Wait after the pointer arrives before opening |
root | close_delay | milliseconds (int) | Wait after the pointer leaves before closing |
root | open · default_open | True / False | Drive the open state from State (controlled) · open at first (uncontrolled) |
root | on_open_change | event | Fires on open or close; passes the new open value (bool) |
content | side · align | position name | Side it opens on and where it lines up |
content | side_offset · align_offset | int (px) | Gap from the link; extra shift from the aligned position |
content | size | "1" "2" "3" | Padding size |
content | avoid_collisions · collision_padding | bool · number | Move away from the screen edge, and the margin for that |
content | sticky · hide_when_detached | "partial" "always" · bool | How closely it sticks while scrolling; hide when the link is covered |
trigger and content only have the common events; neither defines events of its own.
Content can hold grids and images too. rx.inset(side="left") runs the image to the card's left edge, with a title and description on the right. Set the card width directly on content, as in style={"width": 360}.
Hover over the text to see the card. Hover over me
rx.text(
"Hover over the text to see the card. ",
rx.hover_card.root(
rx.hover_card.trigger(
rx.link("Hover over me", color_scheme="blue", underline="always"),
),
rx.hover_card.content(
rx.grid(
rx.inset(
side="left",
pr="current",
background="url('https://picsum.photos/id/1062/240/320') center/cover",
height="full",
),
rx.box(
rx.heading("Kitsune", size="3"),
rx.text("A curious fox who lives in the workshop and inspects every new part.", size="2"),
padding_left="12px",
),
columns="120px 1fr",
),
style={"width": 360},
),
),
)A card that pops up whenever the pointer merely passes by is annoying. open_delay sets how long to wait before opening, and close_delay how long before closing, in milliseconds. Hover over the two links one after the other to feel the difference.
rx.flex(
rx.hover_card.root(
rx.hover_card.trigger(rx.link("Fast (open_delay=100)", underline="always")),
rx.hover_card.content(rx.text("Opened after 100 ms")),
open_delay=100,
close_delay=100,
),
rx.hover_card.root(
rx.hover_card.trigger(rx.link("Slow (open_delay=1200)", underline="always")),
rx.hover_card.content(rx.text("Opened after 1200 ms")),
open_delay=1200,
close_delay=600,
),
spacing="5",
wrap="wrap",
)The on_open_change of hover_card.root passes True when it opens and False when it closes.
Opened or closed: 0 times
Hover card open: no
Hover over the text to see the hover card. Hover over me
class HoverCardEventState(rx.State):
num_opens: int = 0
opened: bool = False
@rx.event
def count_opens(self, value: bool):
self.opened = value
self.num_opens += 1
rx.flex(
rx.text("Opened or closed: ", HoverCardEventState.num_opens, " times"),
rx.text("Hover card open: ", rx.cond(HoverCardEventState.opened, "yes", "no")),
rx.text(
"Hover over the text to see the hover card. ",
rx.hover_card.root(
rx.hover_card.trigger(
rx.link("Hover over me", color_scheme="blue", underline="always"),
),
rx.hover_card.content(
rx.text("This is the hover card content."),
),
on_open_change=HoverCardEventState.count_opens,
),
),
direction="column",
spacing="3",
)Bind open to a State value and a switch can keep the card open. Because on_open_change is wired to the same handler, the switch also moves when you hover over the link and move away.
open
class HoverCardControlState(rx.State):
pinned: bool = False
@rx.event
def set_pinned(self, value: bool):
self.pinned = value
rx.flex(
rx.hover_card.root(
rx.hover_card.trigger(rx.link("Release notes", underline="always")),
rx.hover_card.content(rx.text("v2.4: faster search, new export button.", size="2")),
open=HoverCardControlState.pinned,
on_open_change=HoverCardControlState.set_pinned,
),
rx.switch(checked=HoverCardControlState.pinned, on_change=HoverCardControlState.set_pinned),
rx.text("open", size="2", color_scheme="gray"),
spacing="3",
align="center",
)Hovering over the author's name link shows a card with an avatar, name and bio. Raise open_delay a little so the card does not pop up for a pointer that is just passing through.
Great tutorial! — @mina
rx.text(
"Great tutorial! — ",
rx.hover_card.root(
rx.hover_card.trigger(rx.link("@mina", weight="bold")),
rx.hover_card.content(
rx.flex(
rx.avatar(src="https://picsum.photos/id/64/120/120", fallback="MK", size="4", radius="full"),
rx.box(
rx.heading("Mina Kim", size="3"),
rx.text("@mina", size="2", color_scheme="gray"),
rx.text("Frontend developer. Writes about Python web apps.", size="2", margin_top="6px"),
),
spacing="3",
),
side="top",
align="start",
style={"width": 300},
),
open_delay=400,
),
size="2",
)Workshop notes
Three parts: root · trigger · content. It opens on hover and closes when the pointer leaves (no click needed).
open_delay · close_delay (milliseconds, int) keep it from reacting to a passing pointer.
Placement and size go on content (side, align, side_offset, size "1"~"3").
on_open_change passes the new open value (bool). If you control it with open, wire both up.
It never opens on touch screens without a pointer, so keep anything essential on the linked page as well.
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.