On this page
Import
import { ConfirmDialog } from '@envsemble/envui';
Usage
A ConfirmDialog opens from its trigger, such as a Button. Its title asks the question, such as “Delete Northwind launch?”, its description says what confirming does and whether it can be undone, and confirmLabel names the consequence, such as Delete project.
cancelLabelnames the cancel button.childrenholds more content between the heading and the actions, such as the one field a confirmation holds, where Enter confirms.confirmDisableddisables the confirm button, and Enter in a field doesn't confirm, such as until a typed name matches.- A press outside doesn't close it.
import { useState } from 'react';
import { Button, ConfirmDialog, Column, Text } from '@envsemble/envui';
export default function DeleteProject() {
const [result, setResult] = useState('');
return (
<Column gap={4} align="start">
<ConfirmDialog
trigger={<Button variant="secondary">Delete project</Button>}
tone="danger"
title="Delete Northwind launch?"
description="This deletes the project and its files for everyone. It can’t be undone."
confirmLabel="Delete project"
onConfirm={() => setResult('Northwind launch deleted')}
/>
<Text role="status">{result}</Text>
</Column>
);
}Tone
tone is neutral, the default, where focus starts on the confirm button, or danger, for an action that deletes or ends something: the confirm button is a danger one and focus starts on Cancel, so a hurried Enter doesn't confirm.
<ConfirmDialog
tone="danger"
trigger={<Button tone="danger">Delete project</Button>}
title="Delete Northwind launch?"
description="This deletes the project and its files for everyone. It can’t be undone."
confirmLabel="Delete project"
onConfirm={deleteProject}
/>
An action that can fail
onConfirm runs the action, once per opening: further presses, such as a double-click's second, are ignored until it fails.
- The dialog closes when it returns; when it returns a promise, the confirm button is pending, with
aria-busy, nothing dismisses the dialog, and it closes once the promise resolves. - A rejected promise or a thrown error keeps it open and goes to
reportError; show what went wrong witherror, a danger Alert above the actions that is announced. - The dialog is a form, so hold no form of your own in it; use Dialog for one.
<ConfirmDialog
trigger={<Button variant="secondary">Archive project</Button>}
title="Archive Northwind launch?"
confirmLabel="Archive project"
error={error || undefined}
onConfirm={() => {
setError('');
return archive(); // A promise; a rejected one keeps the dialog open.
}}
/>
From a menu
Without a trigger, open it with open and onOpenChange, which receives the requested state and why: from the trigger, Esc, Cancel or after onConfirm finishes. defaultOpen opens an uncontrolled one on the first render. finalFocus sets where focus goes on closing, such as the menu's button, since the menu item is gone; by default it returns to the trigger.
<Menu.Item onClick={() => setOpen(true)}>Delete project…</Menu.Item>
<ConfirmDialog
open={open}
onOpenChange={setOpen}
finalFocus={menuButton}
tone="danger"
title="Delete Northwind launch?"
confirmLabel="Delete project"
onConfirm={deleteProject}
/>
Customize
A ConfirmDialog is an alert dialog with Dialog's parts: the surface, env-dialog, the question, env-dialog-title, the description, env-dialog-description, and the actions, env-dialog-actions, with Cancel first and the confirm button last. The error is an Alert, env-alert, above the actions. Its surface looks as Dialog's does.
Accessibility
You provide
- A
titlethat asks the question, and aconfirmLabelthat names the consequence. finalFocuswhere the trigger is gone or something other thantriggeropened the dialog.
envUI provides
role="alertdialog", named bytitleand described bydescription.- Focus trapped inside, and returned on close.
aria-busywhile the action runs, and theerrorannounced as an alert.
Props
ConfirmDialog
Asks people to confirm an action whose consequence needs a sentence, such as deleting a project: an alert dialog with a question, a description, Cancel and a confirm button that names the consequence. It waits for onConfirm's promise, pending, and stays open when it fails. className, style, ref and data attributes go to the dialog's surface.
| Prop | Type | Description |
|---|---|---|
open | boolean | Whether the dialog is open, for a dialog the application controls with onOpenChange. |
defaultOpenDefault false | boolean | Whether a dialog the application doesn't control is open on the first render. |
onOpenChange | ( | Called with the requested state, and why, when the dialog opens or closes: from the trigger, Escape, Cancel, or after onConfirm finishes. Not called for a dismissal that a running onConfirm blocks. |
trigger | ReactElement | The element that opens the dialog, such as a Button. Omit it for a dialog the application opens with open, such as from a menu item. |
titlerequired | ReactNode | The question, which names the dialog, such as “Delete Northwind launch?”. |
description | ReactNode | What confirming does and whether it can be undone; it describes the dialog. |
children | ReactNode | More content between the heading and the actions, such as what else the action affects, or the one field a confirmation holds, such as a typed name. The dialog is a form: Enter in a field confirms as the confirm button does, through onConfirm. Hold no form here; use Dialog for one. |
confirmLabelrequired | string | The confirm button's label: a verb that names the consequence, such as Delete project. |
cancelLabelDefault 'Cancel', or EnvUIProvider's messages.confirmDialog.cancel | string | The cancel button's label. |
toneDefault 'neutral' | 'neutral''danger' | danger for an action that deletes or ends something: the confirm button is a danger one and focus starts on Cancel, so a hurried Enter doesn't confirm. neutral starts focus on the confirm button. |
onConfirmrequired | ( | Runs the action when the confirm button is pressed, or Enter is pressed in a field in the dialog. The dialog closes when it returns, or, when it returns a promise, once the promise resolves; while it runs, the confirm button is pending and nothing dismisses the dialog. It runs once per opening: further presses, such as the second click of a double-click, are ignored until it fails or the dialog opens again. A rejected promise or a thrown error keeps it open and is passed to reportError, so show what went wrong with error. |
confirmDisabledDefault false | boolean | Whether the confirm button is disabled, and Enter in a field doesn't confirm, such as for a confirmation that waits on a typed name. |
error | ReactNode | What went wrong, shown as a danger Alert above the actions and announced. |
finalFocus | DialogFocusTarget | The element to focus when the dialog closes, such as the menu button whose item opened it: its ref, or a function of how the dialog was opened that returns it, as on Dialog. By default focus returns to the trigger, or to the element that had focus when it opened. |
Also accepts the native props of <div>, such as ref, className and aria-* attributes.
Part names
Each part's class and state attributes are public and versioned, for an application's CSS to style.
env-confirm-dialog-form- The form that holds the dialog's fields and its confirming action.
Strings
EnvUIProvider's messages overrides each, and a component's own label prop wins over it.
messages.confirmDialog.cancel"Cancel"The button that closes the dialog without confirming.
Changelog
- 1.0.0
ConfirmDialog, an alert dialog with a neutral or danger tone that waits for its action and stays open when it fails.
- 1.0.0-prerelease.6
The dialog fades in with
--env-motion-ease-enter, so it shows from its first frames rather than late, while it rises into place as before.confirmDisableddisables the confirm button, such as for a confirmation that waits on a typed name.- 1.0.0-prerelease.5
The dialog takes the popups' color and soft shadow, with no outline edge, as Dialog does.