Undo & Confirmation Components for shadcn/ui – SureUI

Create delete-project dialogs with exact phrase matching, consequence lists, async states, and editable Base UI components.

SureUI is a UI component library for shadcn/ui that adds confirmation gestures and Undo to actions that change or delete data.

An archive action can wait for Undo, while a workspace deletion can require its exact name and show what will be removed.

The components use Base UI and install as editable local files through the shadcn CLI.

Features

  • Click, second-click, hold, and slide confirmation gestures.
  • Timed or manual Undo windows before an action executes.
  • Exact-phrase confirmation with optional acknowledgements and consequence lists.
  • Pending indicators, retry labels, and error callbacks for async actions.
  • Confirmation controls for buttons, dropdown menus, popovers, dialogs, and switches.
  • AI SDK tool approvals with low, medium, high, and critical risk settings.
  • 10 editable application blocks for account settings, file management, subscriptions, and agent approvals.

How To Use It

Install SureUI

Start with a shadcn/ui project configured for Base UI. For a project that has not initialized shadcn/ui, run:

npx shadcn@latest init

Choose Base UI if the initializer prompts for a component library. Install the confirmation button, which includes the shared confirmation.ts hook:

npx shadcn@latest add @sureui/confirm-button

Basic Usage: Undo and Second-Click Confirmation

In Next.js App Router, use a client component for callbacks. undo defers onConfirm until its five-second window closes. gesture="click-again" arms on the first click and confirms on the next, with a three-second timeout by default. Create components/project-actions.tsx:

"use client";
import { ConfirmButton } from "@/components/ui/sureui/confirm-button";
type ProjectActionsProps = {
  archiveProject: () => Promise<void>;
  deleteProject: () => Promise<void>;
};
export function ProjectActions({
  archiveProject,
  deleteProject,
}: ProjectActionsProps) {
  return (
    <div className="flex flex-wrap gap-3">
      <ConfirmButton undo onConfirm={archiveProject}>
        Archive project
      </ConfirmButton>
      <ConfirmButton
        gesture="click-again"
        variant="destructive"
        onConfirm={deleteProject}
      >
        Delete project
      </ConfirmButton>
    </div>
  );
}

Typed Confirmation for Workspace Deletion

Install the alert dialog and its consequence list:

npx shadcn@latest add @sureui/confirm-dialog
npx shadcn@latest add @sureui/consequences

phrase matches case and surrounding spaces exactly by default. acknowledgements accepts required checkbox statements. For irreversible actions, the dialog starts with focus on Cancel, or on the first input when a phrase is present. Create components/delete-workspace.tsx:

"use client";
import { Button } from "@/components/ui/button";
import { ConfirmDialog } from "@/components/ui/sureui/confirm-dialog";
import { Consequences } from "@/components/ui/sureui/consequences";
type DeleteWorkspaceProps = {
  workspaceName: string;
  projectCount: number;
  apiKeyCount: number;
  deleteWorkspace: () => Promise<void>;
};
export function DeleteWorkspace({
  workspaceName,
  projectCount,
  apiKeyCount,
  deleteWorkspace,
}: DeleteWorkspaceProps) {
  return (
    <ConfirmDialog
      title={`Delete ${workspaceName}?`}
      description="This action permanently deletes the workspace and its data."
      phrase={workspaceName}
      confirmLabel="Delete workspace"
      variant="destructive"
      consequences={
        <Consequences
          title="This deletes"
          items={[
            { label: "Projects", count: projectCount },
            { label: "API keys", count: apiKeyCount },
          ]}
        />
      }
      onConfirm={deleteWorkspace}
    >
      <Button variant="outline">Delete workspace</Button>
    </ConfirmDialog>
  );
}

Add a Toast That Waits for Undo

Use undoToast when the trigger disappears after the operation, such as a file row that leaves the current list.

npx shadcn@latest add @sureui/undo-toast

SureUI uses the Sonner Toaster for this utility. If components/ui/sonner.tsx does not exist, install it:

npx shadcn@latest add sonner

Place <Toaster /> inside the existing app/layout.tsx body, once for the application:

import { Toaster } from "@/components/ui/sonner";
export default function RootLayout({
  children,
}: Readonly<{ children: React.ReactNode }>) {
  return (
    <html lang="en">
      <body>
        {children}
        <Toaster />
      </body>
    </html>
  );
}

undoToast() returns Promise<boolean>: true after the toast closes and false on Undo. The default window lasts five seconds. Pass { duration: "manual" } as the second argument for an explicit dismissal or Undo action. Create a client component for the operation:

"use client";
import { Button } from "@/components/ui/button";
import { undoToast } from "@/components/ui/sureui/undo-toast";
export function TrashFilesButton({
  moveFilesToTrash,
}: {
  moveFilesToTrash: () => Promise<void>;
}) {
  async function handleTrash() {
    // The mutation only runs if the Undo window closes without cancellation.
    const confirmed = await undoToast("Move selected files to trash?");
    if (confirmed) {
      await moveFilesToTrash();
    }
  }
  return <Button onClick={handleTrash}>Move to trash</Button>;
}

Available Components and Utilities

Component or UtilityFunction
ConfirmButtonClick, second-click, hold, or slide confirmation with optional Undo.
ConfirmMenuItemSecond-click or hold confirmation in dropdown and context menus.
ConfirmSwitchImmediate switch movement, with an Undo window before the change commits.
TypeToConfirmInline confirmation after an exact phrase and optional acknowledgements.
ConfirmDialogAlert dialog with button, gesture, or phrase confirmation.
ConfirmPopoverShort confirmation message beside a trigger.
ConsequencesCounts and item names for data deleted or changed.
undoToastPromise-based Sonner toast with a delayed action and Undo.
UndoableCollapsible row with Undo before removal commits.
useUnsavedChangesConfirmation for dirty forms, navigation, and dialog dismissal.
ToolApprovalAI SDK approval or denial with risk-specific confirmation.
useConfirmationCore gesture and Undo hook for custom triggers.

Available Blocks

BlockIncluded Workflow
Danger ZonePause deployments, transfer ownership, and delete a project.
API KeysCreate an API key and revoke keys through a hold.
Delete AccountReview affected data, type an email, and acknowledge account deletion.
Team MembersRemove a member and confirm ownership changes.
File ManagerTrash files with Undo, restore files, and empty trash after confirmation.
InboxArchive or delete messages from a list or reading pane.
Agent ApprovalReview AI tool calls using risk-specific approval controls.
Bulk ActionsIncrease confirmation requirements as selected item counts rise.
Settings Save BarSave, discard, or confirm leaving with unsaved settings.
Cancel SubscriptionShow cancellation consequences and an alternative plan action.

Install a Complete Block

The CLI installs each block as editable local React code and writes any referenced SureUI controls. Install the project settings danger zone:

npx shadcn@latest add @sureui/danger-zone-01

Alternatives and Related Resources

Aidan McAlister

Aidan McAlister

Developer Advocate. TypeScript ecosystem.

Leave a Reply

Your email address will not be published. Required fields are marked *