Skip to content

Components · Data display

RelativeTime

A localised "3 hours ago" in a <time> element, with the absolute time on hover and focus.

@rookcom/monarch-reactComponent

Relative and absolute

Edited 3 Nov 2026, 11:57
Synced 3 Nov 2026, 07:00
Renews 5 Nov 2026, 12:00
Created

Usage examples

Short, narrow and live

Server rendering

Purpose

Shows when something happened (or will happen) relative to now, in the reader’s language, while keeping the exact moment one hover or Tab away and machine-readable in datetime.

Use when

  • Activity feeds, inbox rows, comments and “last synced” labels where recency matters more than the exact time.
  • A status that should keep itself current (live), such as “Updated 2 minutes ago”.

Avoid when

  • The exact date is what the reader needs (invoices, contracts, due dates): format the date itself.
  • A countdown that must be precise to the second: build it on a timer and an aria-live policy of your own.

Design principles

  • The exact time is never only in a title: the tooltip opens on hover and on keyboard focus and is linked with aria-describedby.
  • Localised by Intl.RelativeTimeFormat and Intl.DateTimeFormat; no hand-written “ago” strings.
  • Server rendering is deterministic when you pass now; without it, the client corrects the text after hydration instead of warning.
  • Live updates are quiet: the text changes without a live region, so screen readers are not interrupted every minute.

API reference

import { RelativeTime, formatRelativeTime, relativeTimeParts } from '@rookcom/monarch-react';
ExportKindRenderingRoot class
RelativeTimecomponentclient.mn-relative-time
formatRelativeTimeutilityclient–
relativeTimePartsutilityclient–

The ref and native attributes go to the <time> element; className goes to the mn-relative-time wrapper that also holds the tooltip.

formatRelativeTime(date, options) and relativeTimeParts(date, now) are exported for places that need the string, such as table exports or aria-labels.

Generated from the TypeScript declarations of packages/react/src/components/data-display/relative-time.

Properties

date and now accept a Date, epoch milliseconds or an ISO 8601 string.

RelativeTime

A `<time datetime>` with localised relative text ("3 hours ago") and the absolute time on hover and focus.

PropTypeDescription
date requiredDateInputThe moment to describe. A Date, epoch milliseconds or an ISO 8601 string.
absoluteAfternumberShow the absolute date instead of relative text once the moment is more than this many milliseconds away, e.g. `7 * 86_400_000` for "a week".
absoluteFormatIntl.DateTimeFormatOptions`Intl.DateTimeFormat` options for the absolute time. Default `{ dateStyle: 'medium', timeStyle: 'short' }`.
classNamestring
format"long" | "short" | "narrow"Unit length: `long` "3 minutes ago", `short` "3 min. ago", `narrow` "3m ago". Default `long`.
idstring
livenumber | booleanRe-render as time passes: `true` picks an interval from the age (5 s for the first minute, then 30 s, 5 min and 1 h); a number is a fixed interval in milliseconds. Default `false`.
localestringBCP 47 locale for both the relative and the absolute text. Default: the runtime locale.
nowDateInputThe reference time. Pass it from the server (and the same value on the client) for byte-identical server rendering; without it the text is computed from the clock and corrected right after hydration.
numeric"auto" | "always"`auto` writes "yesterday" and "now"; `always` writes "1 day ago". Default `auto`.
timeZonestringIANA time zone for the absolute text, e.g. `Europe/London`. Default: the viewer's zone.
tooltipbooleanShow the absolute time in a tooltip on hover and keyboard focus. Makes the timestamp a tab stop. Default `true`; set `false` in dense lists where the absolute time is shown elsewhere.

Variants

PropValuesDescription
format'long''short''narrow'“3 minutes ago”, “3 min. ago”, “3m ago” (exact text depends on the locale).
numeric'auto''always'auto writes “yesterday” and “now”; always writes “1 day ago”.
tooltip'true''false'Absolute time on hover and focus (a tab stop), or plain text.

States

StateExposed asBehaviour
Relative–Default: the largest unit that fits, after rounding.
Absolute–Past absoluteAfter milliseconds the absolute date is shown and the tooltip is dropped.
Tooltip dismisseddata-dismissedSet by Escape while focused; cleared on blur or when the pointer leaves.
Invalid datedata-invalidAn unparseable date renders an em dash and no datetime.

Interaction behaviour

  • Hovering the text or the tooltip keeps the tooltip open; the pointer can move onto it (WCAG 1.4.13).
  • With live, the text re-renders every 5 s for the first minute, then every 30 s, 5 min and 1 h as it ages; a number sets a fixed interval.
  • Passing now freezes the reference time, which turns live off.

Keyboard support

KeysAction
TabFocuses the timestamp and shows the absolute time (when tooltip).
EscapeHides the tooltip without moving focus.

Accessibility

Role
time (with a role="tooltip" description)
Accessible name
The relative text; the absolute time is its description through aria-describedby.
  • datetime carries the ISO 8601 instant for machines and assistive technology.
  • The tooltip shows on :focus-visible, not only on hover, and can be dismissed with Escape.
  • Use tooltip={false} in dense lists to avoid a tab stop per row when the exact time is available elsewhere.

Responsive behaviour

  • The text does not wrap. The tooltip is at most 18rem wide and never wider than the viewport minus 2rem.
  • The tooltip is positioned with CSS above the text; inside a container that clips overflow it can be cut off, so give such containers room or use tooltip={false}.

Theme support

  • The tooltip uses the inverse surface tokens, like Tooltip, so it reads in light, dark and more-contrast themes.
  • The dotted underline uses the current text colour at reduced opacity.
  • The tooltip fade is removed under reduced motion.

Do and don't

Do

  • Pass the viewer’s timeZone when you know it, so the tooltip shows their local time.
  • Use absoluteAfter for old items, where “5 months ago” is less useful than the date.
  • Pass now when rendering on the server if the HTML must be identical to the hydrated result.

Don't

  • Do not put essential information only in the tooltip.
  • Do not wrap a live RelativeTime in an aria-live region; it would announce every tick.
  • Do not build “x ago” strings by hand next to it; use formatRelativeTime.
  • Tooltip: Rich supplementary content on hover and focus.
  • ActivityTimeline: Planned feed that shows a RelativeTime per event.
  • DescriptionList: Label and value pairs such as “Last updated”.
  • DatePicker: Planned input for choosing a date rather than showing one.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsNone

Testing coverage

  • Unit selection rounds before rolling over (59.6 min reads “1 hour ago”).
  • Formats with Intl.RelativeTimeFormat, including numeric, format and other locales.
  • Renders <time datetime> and an absolute tooltip linked by aria-describedby.
  • Accepts ISO strings, epoch numbers and Date objects.
  • Is a tab stop; Escape dismisses the tooltip and blur resets it.
  • tooltip={false}, absoluteAfter, timeZone and invalid dates.
  • Live updates tick with fake timers; no ticking without live.
  • Forwards the ref and calls consumer handlers.
  • Server rendering with now, and hydration with a different client clock without errors.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery; Cross-browser axe: /components/relative-time

Tests: packages/react/src/components/data-display/relative-time