Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Relative Time Text for React

A moment said relative to now, such as 5 minutes ago or in 3 days, kept true as time passes, each change fading in. For React with Base UI, when a timestamp reads better as how long ago it was.

Framework

Relative Time Text says a moment the way people do: now, then 12 seconds ago, 5 minutes ago, yesterday, last month; and ahead, in 3 days or next year. It keeps itself true as time passes, and each change fades in. Hovering shows the full date and time.

Use it for a chat message, a "last updated" line, an activity feed, a comment, or a renewal date. For the time of day, use Clock Text; for a live countdown to a moment, Countdown Text. The words come from Intl.RelativeTimeFormat, in any locale, and a small timer wakes only when they would change: every second in the first minute, then each minute, then each hour. The fade is a CSS transition, with no animation library.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { RelativeTimeText } from "@/components/ui/relative-time-text";
<RelativeTimeText timestamp={comment.createdAt} />

Demos

Live

A moment that just happened reads now, then counts the seconds, then the minutes. Here, each save sets timestamp to that moment.

Preview width

Future

A moment still to come reads in 8 months, next week or tomorrow, and turns into the past once it's gone. timestamp can be a Date, a timestamp in milliseconds, or a date string.

Preview width

Format

format is how long the words are: long, the default, short or narrow. numeric="always" says 1 day ago rather than yesterday. The words are in locale, en-US by default.

Preview width

Accessibility

It renders a <time> element whose dateTime is the moment itself, so the words and the exact date travel together, and its title gives the full date and time. Screen readers read the words as they are when reached; changes aren't announced, which is right for a timestamp. The text keeps its own direction on a right-to-left page. With reduced motion new words fade in without moving.

FAQ

Why does it show a date first?

How long ago something was depends on the visitor's clock, which the server can't know. So the server renders the date itself, in UTC, which reads the same everywhere and is what a page without JavaScript shows; the words replace it as soon as the page runs, and the server and the browser render the same markup.

How often does it update?

Only when the words would change: each second for the first minute, then at each new minute, then each hour, and at most once a day after that. Between changes it does nothing.

Which unit does it pick?

The largest that fits: seconds under a minute, then minutes, hours, days, weeks after seven days, months after thirty, and years after 365. The count is whole units, rounded down, so 1 hour 50 minutes ago reads 1 hour ago.

What about moments in the future?

They read in 5 minutes, tomorrow, next month, and change to the past once they've gone by.

Can it speak my visitors' language?

Pass locale, such as fr-FR for il y a 5 minutes; the words come from the browser's own Intl.RelativeTimeFormat. It's fixed to en-US by default so the date shown first is written the same on the server and in the browser.

What happens with reduced motion?

New words fade in without rising.

API Reference

RelativeTimeText

<time> data-slot="relative-time-text"

PropType
timestampDate | number | string

The moment it describes, past or future: a Date, a timestamp in milliseconds or a date string.

Type
Date | number | string
format?Length

How long the words are: 5 minutes ago, 5 min. ago or 5m ago. @default "long".

Default
"long"
locale?string

The locale it's written in. Fixed by default, so the server and the browser write the date it shows first the same way.

Default
"en-US"
numeric?"auto" | "always"

Whether it says yesterday, now and next week, or always a number (1 day ago).

Type
"auto" | "always"
Default
"auto"
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

All 97 text effects