Update Available

Tells people a new version is out without losing work: it never refreshes over unsaved changes and offers "Refresh after I save".

StopsDeploy refresh wiped unsaved work

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/update-available.json

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

Usage

update-available-usage.tsx
import { UpdateAvailable } from "@/components/ui/update-available"

<UpdateAvailable
  currentVersion={running}
  latestVersion="2026.10.13"
  dirty={dirty}
  whatsNew="Fixes rounding on invoice totals."
  onRefresh={() => setRunning("2026.10.13")}
/>

What it catches

  • A newer build than the one running
  • Unsaved changes, which hold the refresh until saved
  • "Later" applied to one build only

Props

UpdateAvailable props
PropTypeDefault
currentVersion* (required)

The build this page is running, baked in at build time.

string—
latestVersion

The deployed build, if you learn it yourself (websocket, service worker). Wins over `versionUrl`.

string—
versionUrl

Endpoint to poll for the deployed build id, e.g. "/version.json".

string—
pollInterval

How often to poll `versionUrl`, in ms.

number—
dirty

There are unsaved changes. The banner never refreshes while this is true.

booleanfalse
onRefresh

Loads the new version. Defaults to `location.reload()`.

() => void() => location.reload()
whatsNew

One line on what's new, e.g. "Fixes rounding on invoice totals."

React.ReactNode—
message

Main banner text.

string"A new version is available."
explainText

What refreshing does, shown before anyone presses it.

string"Refreshing reloads this page in about a second. You stay…
dirtyText

Shown when unsaved changes hold the refresh.

string"You have unsaved changes, so it won't refresh yet. Refre…
armedText

Shown once refresh-after-save is armed.

string"Will refresh as soon as your changes are saved."
refreshLabel

Label of the Refresh button.

string"Refresh"
refreshAfterSaveLabel

Label of the refresh-after-I-save button.

string"Refresh after I save"
cancelLabel

Label of the cancel-armed button.

string"Cancel"
laterLabel

Label of the Later button.

string"Later"
regionLabel

Accessible name of the banner.

string"Update available"

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

Accessibility

  • Banner is a region with an aria-label; message in a polite live region
  • Actions are labelled buttons; icons are aria-hidden

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

Limitations

  • Polling interval and endpoint are yours; nothing is pushed
  • Dirty state comes from your dirty prop

What it stops

Deploy refresh wiped unsaved work

Also known as

update available · new version · refresh · deploy · service worker · chunkloaderror · version polling · release banner

Dependencies

Pairs well with