Unsave Popup

A popup component to confirm before discarding changes. Inspired by Discord, it will shake when the user tries to leave without saving.

Playground

Open in

Installation

pnpm dlx shadcn@latest add 'https://karrix.dev/r/unsave-popup'

Usage Examples

Default Usage

// Default usage
<UnsavePopup 
  show={hasUnsavedChanges} 
  onSave={handleSave} 
  onReset={handleReset}
>
  You have unsaved changes
</UnsavePopup>

When using compound components:

  • UnsavePopupDescription
  • UnsavePopupAction
  • UnsavePopupDismiss

You must include all three components together. Using them individually will throw an error.

Customized Usage

// Customized usage with compound components
<UnsavePopup show={hasUnsavedChanges} className="w-full">
  <UnsavePopupDescription>
    🔴 You have unsaved changes
  </UnsavePopupDescription>
  <UnsavePopupDismiss onClick={handleReset}>
    Reset
  </UnsavePopupDismiss>
  <UnsavePopupAction onClick={handleSave}>
    Save Changes
  </UnsavePopupAction>
</UnsavePopup>

Props

<UnsavePopup />

showboolean

Controls the visibility of the popup

childrenReact.ReactNode

The content to be displayed in the popup. Can be plain text for default usage, or compound components for custom usage

onSave() => Promise<void>

Callback function when save button is clicked (used in default mode)

onReset() => void

Callback function when reset button is clicked (used in default mode)

shouldBlockFn() => boolean

Function to determine if the popup should trigger the block animation

classNamestring

Additional CSS classes to apply to the popup container

<UnsavePopupDescription />

childrenReact.ReactNode

The content to be displayed in the description area

<UnsavePopupAction />

childrenReact.ReactNode

The content of the action button

isLoadingboolean

Controls the loading state of the button

onClick() => Promise<void>

Callback function when the action button is clicked

<UnsavePopupDismiss />

childrenReact.ReactNode

The content of the dismiss button

onClick() => void

Callback function when the dismiss button is clicked