Reset Preview

Shows only the settings a reset would actually change, current → default, so a reset to defaults doesn't wipe customisations unseen.

StopsReset to defaults wiped customizations

Installation

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

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

Usage

reset-preview-usage.tsx
import { ResetPreview, type ResetSetting } from "@/components/ui/reset-preview"

<ResetPreview
  key={run}
  settings={settings}
  undoFor={8000}
  onExport={(data) => setExported(`Saved ${Object.keys(data).length} customizations to settings-backup.json`)}
  onReset={(keys) =>
    new Promise<void>((resolve) =>
      setTimeout(() => {
        setSettings((all) => all.map((s) => (keys.includes(s.key) ? { ...s, value: s.defaultValue } : s)))
        resolve()
      }, 500),
    )
  }
  onUndo={(previous) => setSettings((all) => all.map((s) => (s.key in previous ? { ...s, value: previous[s.key] } : s)))}
/>

What it catches

  • Customised settings that a reset would change, grouped by section
  • Settings to keep, excluded from the reset
  • No export saved yet, with a one-tap export
  • Settings already at default, counted rather than listed
  • Reset regret, with a timed Undo

Props

ResetPreview props
PropTypeDefault
settings* (required)

Settings the user changed, with current and default values.

ResetSetting[]—
onReset* (required)

Resets the listed keys. Return a promise to show a pending state; a rejection is caught.

(keys: string[]) => void | Promise<void>—
onUndo

Puts back the values that were reset. Shown as Undo for `undoFor` ms after a reset.

(previous: Record<string, unknown>) => void—
onExport

Overrides the built-in download of the customizations as JSON.

(customizations: Record<string, unknown>) => void—
undoFor

How long Undo stays available, in ms.

number10_000
exportFileName

File name for the built-in export.

string"settings-backup.json"
format

Formats a value for display.

(value: unknown, setting: ResetSetting) => stringformatSettingValue
title

Heading for the number of changed settings.

(count: number) => string(n) => `Reset ${n} customized ${n === 1 ? "setting" : "se…
atDefaultText

Says how many settings are already at their default.

(count: number) => string(n) => `${n} other ${n === 1 ? "setting is" : "settings a…
keepLabel

Accessible label prefix of each keep checkbox.

string"Keep"
noExportText

Shown until the user exports. Gets the Undo window in seconds, or null without Undo.

(undoSeconds: number | null) => string(s) => `No copy saved. ${s ? `Once Undo ends (${s} s) the…
exportLabel

Label of the export button.

string"Export first"
exportedText

Shown once a copy has been exported.

string"Copy saved."
resetLabel

Reset button label, given how many reset and how many are kept.

(resetting: number, keeping: number) => string(n, kept) => (kept ? `Reset ${n}, keep ${kept}` : `Reset …
pendingLabel

Reset button label while onReset runs.

string"Resetting…"
nothingText

Shown when nothing differs from the defaults.

string"Everything is already at its default."
doneText

Shown after reset, with the count.

(count: number) => string(n) => `${n} ${n === 1 ? "setting" : "settings"} reset to…
undoLabel

Label of the Undo button.

string"Undo"

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

Accessibility

  • Preview is a group labelled by its title; each section has an aria-label
  • Keep checkboxes have descriptive aria-labels; arrow icon has an aria-label ("resets to")
  • Export warning in a polite live region; reset button sets aria-busy while pending
  • After reset, a role=status message with Undo

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

Limitations

  • Undo relies on your onUndo and lasts undoFor ms
  • Value display uses a simple formatter; pass format for complex values

What it stops

Reset to defaults wiped customizations

Also known as

reset to defaults · restore defaults · settings · preferences · export settings · factory reset · config

Dependencies

Pairs well with