Confirmation Modal
A modal dialog for confirmations that require additional context or simple interaction.
Confirmation Modal is a convenience wrapper for confirmation flows that are more complex than a single paragraph but do not warrant a full custom dialog. It is built on top of Dialog and provides a prop-based API for consistent confirmation patterns.
Use Confirmation Modal when the user needs extra context to make a decision, such as explanatory copy, callouts, or small form elements, and the action is not so destructive that it requires typed confirmation.
If the confirmation can be expressed as a single short paragraph, use Alert Dialog. If the action is highly destructive and requires explicit typed intent, use Text Confirm Dialog. See Modality for broader guidance on choosing the appropriate pattern.
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import {
Button,
Form_Shadcn_,
FormControl_Shadcn_,
FormField_Shadcn_,
Select_Shadcn_,
SelectContent_Shadcn_,
SelectItem_Shadcn_,
SelectTrigger_Shadcn_,
SelectValue_Shadcn_,
} from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
export function ConfirmationModalDemo() {
const [visible, setVisible] = useState(false)
const form = useForm({
defaultValues: {
postgresVersion: '17.6.1.054',
},
})
return (
<>
<Button type="default" onClick={() => setVisible(!visible)}>
Show Confirmation Modal
</Button>
<ConfirmationModal
visible={visible}
size="small"
title="Resume this project"
onCancel={() => setVisible(false)}
onConfirm={() => {}}
loading={false}
confirmLabel="Resume"
confirmLabelLoading="Resuming"
cancelLabel="Cancel"
>
{/* Dialog contents */}
<div>
{/* Text content */}
<p className="block text-sm pb-4 border-b border-border-muted">
Your project’s data will be restored to when it was initially paused.
</p>
{/* Dropdown for Postgres version */}
<div className="pt-4">
<Form_Shadcn_ {...form}>
<FormField_Shadcn_
control={form.control}
name="postgresVersion"
render={({ field }) => (
<FormItemLayout layout="vertical" label="Postgres version">
<FormControl_Shadcn_>
<Select_Shadcn_ value={field.value} onValueChange={field.onChange}>
<SelectTrigger_Shadcn_>
<SelectValue_Shadcn_ />
</SelectTrigger_Shadcn_>
<SelectContent_Shadcn_>
<SelectItem_Shadcn_ value="17.6.1.054">17.6.1.054</SelectItem_Shadcn_>
<SelectItem_Shadcn_ value="17.6.1.055">17.6.1.055</SelectItem_Shadcn_>
</SelectContent_Shadcn_>
</Select_Shadcn_>
</FormControl_Shadcn_>
</FormItemLayout>
)}
/>
</Form_Shadcn_>
</div>
</div>
</ConfirmationModal>
</>
)
}Usage
'use client'
import { useState } from 'react'
import { Button } from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'export default function ConfirmationModalDemo() {
const [visible, setVisible] = useState(false)
return (
<>
<Button onClick={() => setVisible(true)}>Show Confirmation Modal</Button>
<ConfirmationModal
visible={visible}
size="small"
title="Resume this project"
confirmLabel="Resume"
confirmLabelLoading="Resuming"
cancelLabel="Cancel"
onConfirm={() => {
setVisible(false)
}}
onCancel={() => {
setVisible(false)
}}
>
This will resume the project and restart any paused processes.
</ConfirmationModal>
</>
)
}Guidelines
- Use for moderate complexity: Suitable when the confirmation requires more than a single sentence but does not need typed intent.
- Avoid critical destruction: Do not use for irreversible or high-risk actions that could benefit from stronger safeguards.
- Keep content focused: Include only the context needed to make the decision. If the dialog becomes a full flow, use a custom Dialog instead.
- Provide clear actions: Ensure confirm and cancel labels clearly describe the outcome of each choice.
Props
visible: Controls open statetitle: Dialog titledescription: Optional descriptionvariant: 'default' | 'destructive' | 'warning'loading: Loading stateonConfirm: Confirm handleronCancel: Cancel handleralert: Optional callout (see Admonition)children: Additional content