Stale Data Notice

Tells people when the numbers on screen may be out of date, after time away or past a max age, with a one-tap refresh.

StopsActing on out-of-date numbers

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/stale-data-notice.json

The files land in your project. They're yours to edit.

Usage

stale-data-notice-usage.tsx
import { StaleDataNotice } from "@/components/ui/stale-data-notice"

<StaleDataNotice
  updatedAt={updatedAt}
  maxAge={10 * 60_000}
  consequence="Prices may have changed."
  onRefresh={() =>
    new Promise<void>((resolve) =>
      setTimeout(() => {
        setUpdatedAt(Date.now())
        resolve()
      }, 800),
    )
  }
/>

What it catches

  • Data older than maxAge
  • Returning to the tab after being away longer than awayAfter
  • Refresh failures, with an error

Props

StaleDataNotice props
PropTypeDefault
maxAge

Data older than this (ms) counts as stale.

number—
awayAfter

Coming back to the tab after being away longer than this (ms) counts as stale.

number—
updatedAt* (required)

When the data on screen was fetched.

Date | number | string—
onRefresh* (required)

Fetch fresh data. Return a promise to show progress; the notice hides once `updatedAt` moves.

() => void | Promise<void>—
message

Headline; `{age}` becomes "18 minutes".

string"This page is {age} old."
consequence

What could be wrong now, e.g. "Prices may have changed."

string"Some details may have changed."
refreshLabel

Label of the refresh button.

string"Refresh"
refreshingLabel

Label while refreshing.

string"Refreshing…"
dismissLabel

Accessible label of the dismiss button.

string"Dismiss and keep the current data"
errorText

Shown when `onRefresh` rejects.

string"Couldn't refresh. Try again."

* required. Also accepts the native props of <div> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Notice is role=status; errors use role=alert
  • Refresh button disables while refreshing; dismiss has an aria-label
  • Icons are aria-hidden

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

  • Age comes from the updatedAt you pass
  • Does not refresh by itself; onRefresh does

What it stops

Acting on out-of-date numbers

Also known as

stale data · refresh · last updated · dashboard · cache · max age · visibilitychange · swr

Field type

Dependencies

Pairs well with