Type to Confirm

Confirmation dialog that unlocks a destructive action only after the exact name is typed, flagging a typo as it happens.

StopsWrong repo deleted on reflex

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/type-to-confirm.json

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

Usage

type-to-confirm-usage.tsx
import { TypeToConfirm } from "@/components/ui/type-to-confirm"

<TypeToConfirm
  open={open}
  onOpenChange={setOpen}
  phrase="acme/website"
  description="This permanently deletes the repository, its wiki, issues and comments."
  confirmLabel="Delete this repository"
  onConfirm={async () => {
    await new Promise((resolve) => setTimeout(resolve, 800))
    setDeleted(true)
  }}
/>

What it catches

  • Confirming before the exact phrase is typed
  • A typo, flagged at the first mismatching character
  • Failed confirms, which keep the dialog open with the error
  • Repeat confirms while pending

Props

TypeToConfirm props
PropTypeDefault
open

Controlled open state.

boolean—
defaultOpen

Initial open state when uncontrolled.

booleanfalse
onOpenChange

Called when the dialog opens or closes.

(open: boolean) => void—
phrase* (required)

The exact phrase the user has to type, e.g. the repository name.

string—
title

Dialog title.

React.ReactNode"Are you absolutely sure?"
description

Dialog description: what will be deleted and what can't be undone.

React.ReactNode"This action cannot be undone."
onConfirm* (required)

Runs when the user confirms. Return a promise to show a pending state; a rejection keeps the dialog open with its message.

() => void | Promise<void>—
instruction

Label for the input. Receives the phrase, already styled.

(phrase: React.ReactNode) => React.ReactNode(p) => <>Type {p} to confirm.</>
mismatchHint

Shown under the input once the typing stops matching.

string"That doesn't match yet. Check for typos."
confirmLabel

Label of the confirm button.

React.ReactNode"Delete"
pendingLabel

Confirm label while onConfirm runs.

React.ReactNode"Deleting…"
cancelLabel

Label of the Cancel button.

React.ReactNode"Cancel"
errorMessage

Fallback when `onConfirm` rejects without an Error message.

string"That didn't go through. Try again."

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

Accessibility

  • Native <dialog> labelled and described by its title and description
  • Input has a <label>, autoFocus, aria-invalid and a polite hint
  • Confirm uses aria-disabled (stays discoverable) and aria-busy while pending
  • Errors use role=alert

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

Limitations

This is a UX guard rail. Enforce on the server: Authorize the destructive action server-side and confirm the target id there; the typed phrase is a UX guard only.

  • Case-sensitive exact match after trimming leading and trailing spaces
  • Typing a name proves attention, not authorization
  • Make the phrase the real target (repo, env, account) so it names what's at stake

What it stops

Wrong repo deleted on reflex

Also known as

type to confirm · delete repository · delete project · github style · confirmation dialog · modal · danger zone

Field type

Dependencies

Pairs well with