Skip to content

RelativeTime

MD, under 1950B gzipped

Live, localised relative time ("3 days ago") with the exact timestamp always available.

Category
Internationalisation
Budget
md, several states or a live subscription
Runtime deps
None

Preview

Preview language

This is the exact fixture the conformance suite renders in CI. Switch the language to see the component mirror and reformat.

Why this exists

RelativeTime

العربية

A hand-built "3 days ago" is English-only and loses the exact timestamp, which a screen reader user can never hover to recover.

What most apps ship

3 days ago

`${days} days ago`

RelativeTime

relative-time

Install

npx shadcn@latest add https://kata-ui-rho.vercel.app/r/relative-time.json

Copies the source into your project. Pulls in 3 primitives: format, locale, use-locale.

Source

"use client";

import { useEffect, useState } from "react";
import { formatRelative, dateTimeFormat } from "../lib/format";
import { useLocale } from "../lib/use-locale";

export interface RelativeTimeProps {
  value: Date | number;
  /** Re-render interval in ms, so "in 1 minute" becomes "now" on its own. */
  updateInterval?: number;
  className?: string;
}

/**
 * "3 days ago", live and in the reader's own language and calendar. The exact
 * timestamp is always available too — on hover for a mouse, and permanently
 * for assistive tech via `title`, since a screen reader does not hover.
 */
export function RelativeTime({ value, updateInterval = 60_000, className }: RelativeTimeProps) {
  const { locale, calendar } = useLocale();
  const [, forceUpdate] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => forceUpdate((n) => n + 1), updateInterval);
    return () => clearInterval(timer);
  }, [updateInterval]);

  const date = new Date(value);
  const exact = dateTimeFormat(locale, { dateStyle: "full", timeStyle: "short", calendar }).format(
    date,
  );

  return (
    <time dateTime={date.toISOString()} title={exact} className={className} suppressHydrationWarning>
      {formatRelative(date, locale)}
    </time>
  );
}

What CI checks

← All components