Relative time

Shows when something happened as a distance from now, with the exact time on hover and focus.

Examples

A column of times

  • Ana Marsh refunded order 4812
  • support-agent ran eval refund-policy
  • Maya Chen published prompt v14
  • Jon Reyes revoked key sk_demo_0000aaaa
  • Sam Okoye created agent billing-agent

In a sentence

Prompt v14 was last edited by Maya Chen , and the next scheduled eval starts .

Past and future

  • Eval refund-policy started
  • Key sk_demo_0000aaaa expires
  • Next retry

Format

  • shortdefault

  • long

Range

  • now

  • minutes

  • hours

  • days

  • past a week

  • future

States

  • rest

  • no hint

Usage

When to use it
Use
A row, card or message says when a run, edit or key event happened.
Use
A future moment counts down: a retry, an expiry, a scheduled eval.
Not for
The exact time is the content, like a log line or an audit export. Use Log viewer.
Not for
The date is a fixed fact the person plans around, like a release day. Write the date.

Rules

7 rules
Must
Render a moment with RelativeTime; never format "3m ago" by hand. Because a hand-made label goes stale on the page, has no exact time on hover and reads differently from the rest of the product.
Must
Pass date as a Date, an ISO string or epoch milliseconds; never a preformatted label. Because the component needs the moment to tick, to build the exact-time hint and to set dateTime on the time element.
Should
Use the default short format in rows and tables, and format="long" only inside a sentence. Because "3m ago" stays narrow and lines up on tabular figures, while "3 minutes ago" widens every row of the column.
Should
Pass now to freeze the clock in tests, docs and screenshots. Because a live clock changes the label between renders, so a snapshot never matches twice.
Should
Keep hint on unless the time sits inside a control that is already a tab stop or already shows the exact time beside it. Because the hint is the only place the exact time appears; hint={false} also removes the extra tab stop.
Never
Pass type or color classes to make a time louder; set the color on the parent. Because a time is metadata, and a heavier time in a row competes with the title and the status.
Should
Leave past a week to the component, which switches to a calendar date. Because "41d ago" is harder to place than "Sep 2", and a date answers "was that before the release".

Accessibility

4 checks
The visible label is aria-hidden; a screen reader reads the long form and the exact local time ("14 minutes ago, Oct 13, 2026, 11:46:00 AM").
The time element carries dateTime in ISO form.
With a hint it is a tab stop and shows a 2px focus outline; the hint opens on focus, and a tap toggles it on touch.
It ticks only when the label would change, and not while the tab is hidden.

Edge cases

9 edge cases
Under 45 seconds
Reads "now" in both directions.
Unit boundary
Turns to the next unit before the rounded value reaches it, so it never reads "60m ago".
Past a week
A calendar date, with the year only when it is not this year.
Invalid date
Renders "Unknown time" in text-3 with data-invalid.
Server render
Reads in UTC as a calendar date with no clock; the browser clock and zone take over after mount.
A page of 200 times
Each schedules its own next change, not a shared interval, so none wakes to render the same words.
Background tab
Stops ticking and catches up the moment the tab shows again.
Right to left
The label is English text; the box stays inline and does not wrap.
Zoom 200%
Stays on one line and grows with the text.

API

5 props
date
Date | string | number default required
format
'short' | 'long' default 'short'
now
Date | string | number
hint
boolean default true
className
string

Tokens

8 tokens
--text-3
oklch(var(--ink-c) / 0.66)
--text-2
oklch(var(--ink-c) / 0.80)
--radius-soft
6px
--line-focus
2px
--border-focus
var(--ink)
--focus-offset
2px
--surface-inverse
var(--ink)
--text-inverse
var(--paper)

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.