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
Under each post in the review list, show when it was written as relative time, like '3 minutes ago' or '2 hours ago'. Hovering should reveal the exact time too.
rx.moment is a date display component that wraps react-moment. It formats dates the way you want and handles relative times like "5 minutes ago" and time zone conversion in the browser.
The examples on this page use date_now from the State below. It holds the time (UTC) when the server started; click "Update" and it changes to the current time, which every example below picks up. The Reflex docs keep a datetime in State as is, but here it is stored as an ISO string. rx.moment accepts both.
from datetime import datetime, timezone
class MomentDateState(rx.State):
date_now: str = datetime.now(timezone.utc).isoformat()
@rx.event
def update_moment_date(self):
self.date_now = datetime.now(timezone.utc).isoformat()
rx.vstack(
rx.moment(MomentDateState.date_now),
rx.button("Update", on_click=MomentDateState.update_moment_date, size="1", variant="soft"),
)format tokens follow moment.js rules (YYYY year, MM month, DD day, HH hour, mm minute, ss second, ddd weekday). Turn on from_now and relative time is shown instead of the format.
Try the props
format
tz
from_now
from_now_short
with_title
rx.moment("2026-01-01T09:00:00Z", format="YYYY-MM-DD HH:mm", tz="Asia/Seoul", from_now=False, from_now_short=False, with_title=False)| Prop | Values | Use |
|---|---|---|
First argument / date | String, datetime, date … | The date to show; without it, the current time |
format | A format like "YYYY-MM-DD" | Display format |
from_now / to_now | True / False | Relative time like "5 minutes ago" / "in 5 minutes" |
from_now_short | True / False | Short form like "1h", "2d" |
from_now_during | Milliseconds | Relative time only for that long, then format |
add / subtract | rx.MomentDelta(...) | Adds or subtracts time for display only |
tz | A time zone like "Asia/Seoul" | Show in that time zone |
locale | "fr" "ko" … | Language of this component; default "en" |
interval | Milliseconds (0 stops it) | Re-render periodically |
with_title / title_format | Full date shown on hover, and its format | |
diff · unit · decimal | Difference between two dates | |
duration · duration_from_now · trim | Show elapsed time | |
unix · parse · local | How to interpret the input date; output in local time | |
on_change | Event | On first appearance and whenever the date re-renders |
Often "how long ago" is easier to read than the date itself. from_now shows the time from now to that date ("2 hours ago"), and to_now the opposite direction ("in 2 hours"). from_now_short shortens it to something like "2h". With from_now_during=100000, relative time is shown for only 100 seconds, after which the date follows format.
from datetime import datetime, timezone
class MomentDateState(rx.State):
date_now: str = datetime.now(timezone.utc).isoformat()
@rx.event
def update_moment_date(self):
self.date_now = datetime.now(timezone.utc).isoformat()
rx.vstack(
rx.moment(MomentDateState.date_now, from_now=True),
rx.moment(MomentDateState.date_now, to_now=True),
rx.moment("2026-01-01T09:00:00Z", from_now=True, from_now_short=True),
rx.moment(MomentDateState.date_now, from_now_during=100000, format="YYYY-MM-DD HH:mm"),
)Shape the output however you like with format.
from datetime import datetime, timezone
class MomentDateState(rx.State):
date_now: str = datetime.now(timezone.utc).isoformat()
@rx.event
def update_moment_date(self):
self.date_now = datetime.now(timezone.utc).isoformat()
rx.vstack(
rx.moment(MomentDateState.date_now, format="YYYY-MM-DD"),
rx.moment(MomentDateState.date_now, format="HH:mm:ss"),
rx.moment(MomentDateState.date_now, format="ddd, MMM D YYYY, h:mm A"),
)Pass an rx.MomentDelta to add or subtract, and the date shifts only on screen while the State date stays as it is. The keys are years, quarters, months, weeks, days, hours, minutes and seconds, and Reflex 0.10 also has milliseconds. The left column adds 2 of each; the right column subtracts 2.
from datetime import datetime, timezone
class MomentDateState(rx.State):
date_now: str = datetime.now(timezone.utc).isoformat()
@rx.event
def update_moment_date(self):
self.date_now = datetime.now(timezone.utc).isoformat()
rx.grid(
*[
rx.moment(MomentDateState.date_now, add=rx.MomentDelta(**{unit: 2}), format="YYYY-MM-DD - HH:mm:ss")
for unit in ["years", "quarters", "months", "weeks", "days", "hours", "minutes", "seconds"]
],
*[
rx.moment(MomentDateState.date_now, subtract=rx.MomentDelta(**{unit: 2}), format="YYYY-MM-DD - HH:mm:ss")
for unit in ["years", "quarters", "months", "weeks", "days", "hours", "minutes", "seconds"]
],
rows="8",
flow="column",
column_gap="6",
row_gap="1",
width="max-content",
)rx.moment defaults to English, and only a component given a locale switches to that language. Other components and pages are unaffected. A fixed language name loads only that language file; a State value loads all language files.
from datetime import datetime, timezone
class MomentDateState(rx.State):
date_now: str = datetime.now(timezone.utc).isoformat()
@rx.event
def update_moment_date(self):
self.date_now = datetime.now(timezone.utc).isoformat()
rx.vstack(
rx.moment(MomentDateState.date_now, format="dddd D MMMM YYYY"),
rx.moment(MomentDateState.date_now, format="dddd D MMMM YYYY", locale="fr"),
rx.moment(MomentDateState.date_now, format="LL dddd", locale="ko"),
rx.moment(MomentDateState.date_now, from_now=True, locale="ko"),
)With tz, the same moment is shown in that region's local time. z in the format is the time zone abbreviation.
from datetime import datetime, timezone
class MomentDateState(rx.State):
date_now: str = datetime.now(timezone.utc).isoformat()
@rx.event
def update_moment_date(self):
self.date_now = datetime.now(timezone.utc).isoformat()
rx.vstack(
rx.moment(MomentDateState.date_now, tz="America/Los_Angeles", format="YYYY-MM-DD HH:mm z"),
rx.moment(MomentDateState.date_now, tz="Europe/Paris", format="YYYY-MM-DD HH:mm z"),
rx.moment(MomentDateState.date_now, tz="Asia/Seoul", format="YYYY-MM-DD HH:mm z"),
)Without a date, it uses the browser's current time. Give it an interval (in milliseconds) and it re-renders at that interval, becoming a clock. It runs entirely in the browser without talking to the server.
rx.moment(interval=1000, format="HH:mm:ss")on_change fires when the component first appears and every time the date re-renders, passing the date string. Even with interval=0, which means no periodic re-rendering, it fires once on first appearance. It fires again when the component reappears after a refresh or navigation, and in dev mode it may fire twice at first because of React Strict Mode. Turn on the switch and it fires every 2 seconds.
on_change fired 0 times
class MomentTickState(rx.State):
updating: bool = False
ticks: int = 0
last: str = ""
@rx.event
def on_moment_tick(self, date: str):
self.ticks += 1
self.last = date
@rx.event
def set_moment_updating(self, value: bool):
self.updating = value
rx.vstack(
rx.hstack(
rx.moment(
format="HH:mm:ss",
interval=rx.cond(MomentTickState.updating, 2000, 0),
on_change=MomentTickState.on_moment_tick,
),
rx.switch(checked=MomentTickState.updating, on_change=MomentTickState.set_moment_updating),
align="center",
),
rx.text("on_change fired ", MomentTickState.ticks, " times", size="2"),
rx.text(MomentTickState.last, size="1", color_scheme="gray"),
)These features appear only in the official docs' props table. From the top: date difference (days), date difference (months, decimal), time elapsed between two times, time elapsed from that date until now, interpreting a Unix timestamp (seconds), reading with a given format (parse), and relative time that reveals the full date on hover.
from datetime import datetime, timezone
class MomentDateState(rx.State):
date_now: str = datetime.now(timezone.utc).isoformat()
@rx.event
def update_moment_date(self):
self.date_now = datetime.now(timezone.utc).isoformat()
rx.vstack(
rx.moment("2026-10-24", diff="2026-01-01", unit="days"),
rx.moment("2026-10-24", diff="2026-01-01", unit="months", decimal=True),
rx.moment(date="2026-10-24T12:00:00Z", duration="2026-10-24T09:30:00Z"),
rx.moment("2026-01-01T00:00:00Z", duration_from_now=True, interval=1000),
rx.moment("1767225600", unix=True, format="YYYY-MM-DD"),
rx.moment("24/10/2026", parse="DD/MM/YYYY", format="YYYY-MM-DD"),
rx.moment(MomentDateState.date_now, from_now=True, with_title=True, title_format="YYYY-MM-DD HH:mm:ss"),
)Put a small relative time under each review, and use with_title so hovering shows the exact time. With interval=30000, "a few seconds ago" updates on its own to "a minute ago" and so on every 30 seconds.
Jin left a review
from datetime import datetime, timezone
class MomentDateState(rx.State):
date_now: str = datetime.now(timezone.utc).isoformat()
@rx.event
def update_moment_date(self):
self.date_now = datetime.now(timezone.utc).isoformat()
rx.card(
rx.hstack(
rx.avatar(fallback="JK", size="3", radius="full"),
rx.vstack(
rx.text("Jin left a review", weight="bold", size="2"),
rx.moment(
MomentDateState.date_now,
from_now=True,
with_title=True,
title_format="YYYY-MM-DD HH:mm",
interval=30000,
font_size="12px",
color=rx.color("gray", 11),
),
spacing="0",
),
align="center",
),
max_width="320px",
)Workshop notes
Format with rx.moment(date, format="YYYY-MM-DD"); use from_now/to_now for relative time.
add/subtract=rx.MomentDelta(days=2) shifts the date for display only.
tz sets the time zone; locale sets the language for this component only (default English).
With no date and interval=1000, you get a browser clock. on_change also fires on first appearance.
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.