<!-- Protocore Design System — RelativeTime -->
# RelativeTime

- **Category:** Data Display (`data-display`)
- **Slug:** `data-display/relative-time`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { RelativeTime } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/data-display/relative-time

> An auto-updating "3m ago" timestamp on a real <time> element, with an absolute UTC tooltip.

## When to use it

**RelativeTime** is for any "when" a user reads at a glance — last deploy, message age, block time, activity feeds. The relative label conveys recency instantly, while the absolute UTC value sits in the tooltip (and in `timeStyle="both"`) for precision.

Because the relative part depends on "now", it is hydration-suppressed and only appears after the client clock is available — the server renders the absolute value, so there's no mismatch. Use `"absolute"` when the exact instant matters more than recency (audit logs, legal timestamps). Pair it with **Timeline** for a vertical event history.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `className` | `string` | no | — | — |
| `style` | `CSSProperties` | no | — | Standard inline style, forwarded to the `<time>` element. |
| `timeStyle` | `enum` | no | `relative` | Which representation(s) to render: relative label, absolute UTC timestamp, or both side by side. |
| `value` | `string \| number \| Date` | yes | — | The instant to describe — ISO string, epoch milliseconds, or a `Date`. |

## Examples

### Basics

Pass a `value` — an ISO string, epoch milliseconds, or a `Date`. It renders a relative label (`3m ago`) that ticks every 30 seconds so it never goes stale, inside a semantic `<time dateTime>` element.

```tsx
import { RelativeTime } from "@protocore/pds";

export default function RelativeTimeBasics() {
  // Instants relative to a fixed reference; the label ticks live once mounted.
  const now = Date.now();
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8, alignItems: "flex-start" }}>
      <RelativeTime value={now - 45 * 1000} />
      <RelativeTime value={now - 8 * 60 * 1000} />
      <RelativeTime value={now - 5 * 60 * 60 * 1000} />
      <RelativeTime value={now - 3 * 24 * 60 * 60 * 1000} />
    </div>
  );
}
```

### Time styles

`timeStyle` picks the representation: `"relative"` (default), `"absolute"` for the fixed UTC timestamp, or `"both"` side by side. The absolute form always renders on the server; the relative label swaps in after mount so hydration stays clean.

```tsx
import { RelativeTime } from "@protocore/pds";

export default function RelativeTimeStyles() {
  const deployedAt = "2026-06-28T14:05:00Z";
  return (
    <table style={{ borderCollapse: "collapse", fontSize: 13 }}>
      <tbody>
        <tr>
          <td style={{ padding: "4px 16px 4px 0", opacity: 0.6 }}>relative</td>
          <td>
            <RelativeTime value={deployedAt} timeStyle="relative" />
          </td>
        </tr>
        <tr>
          <td style={{ padding: "4px 16px 4px 0", opacity: 0.6 }}>absolute</td>
          <td>
            <RelativeTime value={deployedAt} timeStyle="absolute" />
          </td>
        </tr>
        <tr>
          <td style={{ padding: "4px 16px 4px 0", opacity: 0.6 }}>both</td>
          <td>
            <RelativeTime value={deployedAt} timeStyle="both" />
          </td>
        </tr>
      </tbody>
    </table>
  );
}
```

## Usage

**Do**

- Pass a machine value (ISO/epoch/Date) and let the component format it.
- Use the default relative style for feeds and "last updated" affordances.
- Use `"absolute"` or `"both"` where the exact instant is legally or operationally important.
- Trust it in server components — the absolute value renders SSR-safe.

**Don't**

- Don't pre-format the date to a string and pass that — it can't tick or tooltip.
- Don't assume local time; the absolute form is fixed to UTC by design.
- Don't use relative-only for timestamps that must be unambiguous in an export.
- Don't wrap it in your own `<time>` — it already renders one.

## Accessibility

**Notes**

- Renders a semantic `<time>` with a machine-readable `dateTime` (ISO) attribute.
- The absolute UTC value is always available via the `title` attribute, even in relative mode.
- The live-ticking relative label uses `suppressHydrationWarning` so SSR and client agree; an unparseable value renders the literal input with an explanatory `title`.

## Related

`money-amount`, `metric-delta`, `timeline`, `numbered-row`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
