Private Mode Notice

Warns before someone relies on drafts or "Remember me" in a browser that won't keep them, after testing that storage really works.

StopsDrafts vanish in incognito

Installation

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

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

Usage

private-mode-notice-usage.tsx
import { PrivateModeNotice, type StorageReport } from "@/components/ui/private-mode-notice"

<PrivateModeNotice
  report={report}
  hasUnsavedWork={notes.trim().length > 0}
  exportData={() => notes}
  exportFilename="trip-notes.txt"
  onReport={(r) =>
    real &&
    setFound(r.risk === "ok" ? "This browser keeps data normally." : `This browser: ${r.risk} (${r.confidence}).`)
  }
/>

What it catches

  • Private window that erases saved data on close
  • Site data blocked, so nothing can be saved
  • Storage nearly full, so new saves may fail
  • Unsaved work at risk: export button

Props

PrivateModeNotice props
PropTypeDefault
report

Skip detection and use this report (tests, or your own server-side signal).

StorageReport—
variant

`banner` above a form or editor; `inline` as a one-line hint under a "Remember me" box.

"banner" | "inline""banner"
hasUnsavedWork

The user has work that only exists in this window. Strengthens the message and guards closing the tab.

booleanfalse
exportData

Returns the unsaved work to download. Without it there's no Export button.

() => string | Blob—
exportFilename

File name for the export.

string"unsaved-work.txt"
onReport

Called once detection finishes.

(report: StorageReport) => void—
privateText

Banner messages per risk.

string"This is a private window. Drafts and “Remember me” are e…
blockedText

Shown when site data is blocked.

string"Your browser is blocking site storage. Drafts and “Remem…
fullText

Shown when storage is nearly full.

string"Storage for this site is nearly full. New drafts may not…
unsavedText

Appended when work is at stake.

string"Your unsaved work only exists in this window."
likelyText

Shown when the risk is inferred, not proven.

string"Detected from how your browser stores data, so it may be…
inlinePrivateText

One-line messages for the inline variant.

string"Private window: you’ll be signed out when you close it."
inlineBlockedText

Inline variant text for blocked storage.

string"Your browser blocks site storage, so this can’t be remem…
inlineFullText

Inline variant text for full storage.

string"Browser storage is full, so this may not be remembered."
exportLabel

Button text to download unsaved work.

string"Export"
exportedLabel

Button text after exporting.

string"Downloaded"
dismissLabel

Button text to dismiss the notice.

string"Got it"

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

Accessibility

  • Notice is a labelled region inside a polite live region
  • Export and dismiss are buttons; icons are aria-hidden

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

Limitations

  • Private-mode detection is sometimes inferred ("likely") when a write succeeds
  • Browsers change storage behaviour often
  • Export uses the data you pass in exportData

What it stops

Drafts vanish in incognito

Also known as

incognito · private browsing · localstorage · remember me · storage quota · drafts · cookies blocked · safari private

Dependencies

Pairs well with