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
rx.tooltipOfficial docs
Workshop order
Our editing toolbar is all icons. Add a short label to each button that tells you what it does when you hover over it.
rx.tooltip is a small label that appears briefly when you hover over an element or move keyboard focus to it. Pass the element to wrap as a child and the text to show in the content prop. Its most common job is naming elements that have no text of their own, such as icon buttons.
rx.tooltip(
rx.button("Hover over me"),
content="This is the tooltip content.",
)Most tooltip props are about placement. Change a value, then hover over the button. delay_duration is how long (in milliseconds) the tooltip waits after the pointer arrives before it appears.
Try the props
content
side
align
side_offset
4
delay_duration
700
avoid_collisions
rx.tooltip(
rx.button("Hover me", variant="soft"),
content="Save changes",
side="top",
align="center",
side_offset=4,
delay_duration=700,
avoid_collisions=True,
)| Prop | Values | Default | Use |
|---|---|---|---|
content | string | - | Text shown in the tooltip |
side | "top" "right" "bottom" "left" | "top" | Side it opens on |
align | "start" "center" "end" | "center" | Where it lines up along that side |
side_offset · align_offset | number (px) | - | Gap from the element; extra shift from the aligned position |
avoid_collisions | True / False | True | Flip to the opposite side when it hits the edge of the screen |
collision_padding | number or per-side dict | - | Margin treated as the edge of the screen |
arrow_padding | number (px) | - | Space between the arrow and the corners |
sticky | "partial" "always" | "partial" | How closely it sticks to the element while scrolling |
hide_when_detached | True / False | False | Hide the tooltip when the element is covered |
delay_duration | milliseconds | 700 | Wait before it appears |
disable_hoverable_content | True / False | - | Close even when the pointer moves onto the tooltip |
default_open | True / False | - | Open on first render (uncontrolled) |
open | True / False | - | Drive the open state from State (controlled) |
force_mount | True / False | - | Keep it in the DOM while closed (for animation libraries) |
aria_label | string | - | Name read by screen readers |
on_open_change | event | - | Fires on open or close; passes the new open value (bool) |
on_escape_key_down | event | - | Esc is pressed |
on_pointer_down_outside | event | - | A press lands outside the tooltip |
side is only a preference. If there is no room on that side, avoid_collisions moves the tooltip to the opposite one.
rx.flex(
rx.tooltip(rx.button("top", variant="outline"), content="side=top", side="top"),
rx.tooltip(rx.button("right", variant="outline"), content="side=right", side="right"),
rx.tooltip(rx.button("bottom", variant="outline"), content="side=bottom", side="bottom"),
rx.tooltip(rx.button("left", variant="outline"), content="side=left", side="left"),
spacing="3",
wrap="wrap",
)Every time the tooltip opens or closes, on_open_change fires and the handler receives the new open value (True/False). The example below shows how many times that happened and the current state.
Opened or closed: 0 times
Tooltip open: no
class TooltipEventState(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: ", TooltipEventState.num_opens, " times"),
rx.text("Tooltip open: ", rx.cond(TooltipEventState.opened, "yes", "no")),
rx.tooltip(
rx.button("Hover over me"),
content="This is the tooltip content.",
on_open_change=TooltipEventState.count_opens,
),
direction="column",
spacing="3",
align="start",
)Bind open to a State value and your code decides whether the tooltip is open. Wire up on_open_change as well, so opening and closing it with the pointer gets written back to State. Below, you can pin the hint open with the button or open it by hovering over the input.
class TooltipControlState(rx.State):
show: bool = False
@rx.event
def set_show(self, value: bool):
self.show = value
@rx.event
def toggle(self):
self.show = not self.show
rx.flex(
rx.tooltip(
rx.input(placeholder="Coupon code", width="12em"),
content="Codes are 8 letters, e.g. SPRING24",
open=TooltipControlState.show,
on_open_change=TooltipControlState.set_show,
side="right",
),
rx.button(
rx.cond(TooltipControlState.show, "Hide hint", "Show hint"),
on_click=TooltipControlState.toggle,
variant="soft",
),
spacing="3",
align="center",
wrap="wrap",
)default_open=True opens the tooltip only at first; after that it follows the pointer as usual. With disable_hoverable_content on, the tooltip closes right away even if you move the pointer onto it. When content is too short to make sense on its own, give screen readers a separate name with aria_label.
rx.flex(
rx.tooltip(rx.button("default_open"), content="Open on first render", default_open=True, side="bottom"),
rx.tooltip(rx.button("disable_hoverable_content", variant="soft"), content="Closes as soon as you leave the button",
disable_hoverable_content=True),
rx.tooltip(rx.icon_button(rx.icon("info"), variant="ghost"), content="?", aria_label="More information about this field"),
spacing="3",
wrap="wrap",
align="center",
)Give each icon button a tooltip with its name, and set side="bottom" so they open below the toolbar. Shorten delay_duration too, so there is less waiting as the pointer slides along the bar.
rx.flex(
rx.tooltip(rx.icon_button(rx.icon("bold"), variant="ghost", aria_label="Bold"), content="Bold (Ctrl+B)", side="bottom", delay_duration=200),
rx.tooltip(rx.icon_button(rx.icon("italic"), variant="ghost", aria_label="Italic"), content="Italic (Ctrl+I)", side="bottom", delay_duration=200),
rx.tooltip(rx.icon_button(rx.icon("underline"), variant="ghost", aria_label="Underline"), content="Underline (Ctrl+U)", side="bottom", delay_duration=200),
rx.separator(orientation="vertical", size="1"),
rx.tooltip(rx.icon_button(rx.icon("link"), variant="ghost", aria_label="Insert link"), content="Insert link", side="bottom", delay_duration=200),
spacing="2",
align="center",
padding="6px",
border=f"1px solid {rx.color('gray', 6)}",
border_radius="8px",
width="fit-content",
)Workshop notes
rx.tooltip(element, content="text"): appears on hover or focus.
Placement is side · align · side_offset; screen edges are handled by avoid_collisions · collision_padding.
delay_duration controls how soon it appears (700ms by default).
on_open_change passes the new open value (bool). If you control open from State, always wire it up too.
A tooltip is a supplementary hint. Put anything people must know, or anything to click, in a Popover or Dialog.
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.