Skip to contentSkip to navigationSkip to topbar
Paste assistant Assistant
Figma
Star

Delete

Design assets pendingPeer review pending

The Delete pattern allows the user to destroy an existing object and communicates any critical consequences of that action.


Ingredients

Ingredients page anchor

Button

// import all ingredients for the delete patterns

import {​ Button } from "@twilio-paste/core/button";
import { AlertDialog } from "@twilio-paste/core/alert-dialog";
import { Input } from "@twilio-paste/core/input";
import { Label } from "@twilio-paste/core/label";
import { HelpText } from "@twilio-paste/core/help-text;
import { Toast } from "@twilio-paste/core/toast";

General

General page anchor

The delete pattern should be used when a user is destroying an object. It is critical to communicate delete actions to our users in a consistent way, considering deletions come with significant consequences and often cannot be undone.

The delete action should:

  • Be initiated by a destructive Button.
  • Rarely be the primary action on the page. There are many variants of differing visual prominence to choose from to achieve the correct hierarchy for the delete action trigger.
  • Follow guidelines based on the severity of the deletion.

Medium and high severity delete confirmations are displayed using an Alert Dialog, since it requires the user to interact with the component.

Delete messages should follow the Confirmation pattern.

Avoid using negative contractions like can't or won't, since user comprehension can suffer in stressful scenarios.

A deletion is considered low-severity when users can easily undo the deletion or recreate the deleted data.

Warning or confirmation messages are not necessary for low-severity deletions.

Component preview theme
const LowSeverityDelete = () => {
return (
<Button variant="destructive_link">Remove</Button>
)
}
render(
<LowSeverityDelete />
)

A deletion is considered medium-severity if either of the following are true:

  • The user action cannot undo the deletion or easily recreate the data.
  • The user is performing a bulk deletion of low- or medium-severity.

Show a confirmation message that explains what is being deleted and the consequences of the deletion.

Component preview theme
const MediumSeverityDelete = () => {
const [isOpen, setIsOpen] = React.useState(false);
const handleOpen = () => setIsOpen(true);
const handleClose = () => setIsOpen(false);
return (
<>
<Button variant="destructive" onClick={handleOpen}>Delete</Button>
<AlertDialog
heading="Delete from regulatory bundle?"
isOpen={isOpen}
onConfirm={handleClose}
onConfirmLabel="Delete"
onDismiss={handleClose}
onDismissLabel="Cancel"
destructive
>
You're about to delete "Plan A Productions, LLC" from this regulatory bundle. This does not impact any other regulatory bundles.
</AlertDialog>
</>
)
}
render(
<MediumSeverityDelete />
)

A deletion is considered high-severity if any of the following are true:

  • The user action cannot undo the action and recreating the deleted data would be highly time consuming or impossible.
  • The user is deleting a large a large amount of data that is not recoverable.
  • The deletion will have significant downstream impact.

Show a confirmation message that explains what is being deleted and the consequences of the deletion, and have the user manually confirm the deletion by entering the name of the object they are deleting.

Component preview theme
const HighSeverityDelete = () => {
const [isDisabled, setIsDisabled] = React.useState(true);
const [isOpen, setIsOpen] = React.useState(false);
const [inputString, setInputString] = React.useState('');
const [inputHasError, setInputHasError] = React.useState(false);
const handleOpen = () => {
if (inputString !== '') setIsDisabled(false);
setIsOpen(true);
};
const handleDismiss = () => {
setIsDisabled(true)
setIsOpen(false)
};
const handleConfirm = () => {
if (inputString === 'Toyota TCB Automobile (Gevelsberg)') {
setIsOpen(false)
setInputString('')
setInputHasError(false)
}
else {
setInputHasError(true)
}
};
const handleChange = (e) => {
setInputString(e.target.value)
if (e.target.value !== '') setIsDisabled(false);
else setIsDisabled(true);
};
return (
<>
<Button variant="destructive" onClick={handleOpen}>Delete</Button>
<AlertDialog
heading="Delete regulatory bundle?"
isOpen={isOpen}
onConfirm={handleConfirm}
onConfirmLabel="Delete"
onDismiss={handleDismiss}
onDismissLabel="Cancel"
destructive
onConfirmDisabled={isDisabled}
>
You're about to delete "Toyota TCB Automobile (Gevelsberg)" and all associated data. The bundle will be deleted immediately. You cannot undo this action.
<Box display="flex" flexDirection="column" rowGap="space30" marginY="space50">
<Label htmlFor="delete-input" required>
Regulatory bundle name
</Label>
<Input type="text" id="delete-input" required aria-describedby="delete-help-text" onChange={(e) => handleChange(e)} hasError={inputHasError} value={inputString}/>
<HelpText id="delete-help-text" variant={inputHasError ? 'error' : 'default'}>
Enter the name of the bundle being deleted. Entries are case-sensitive.
</HelpText>
</Box>
</AlertDialog>
</>
)
}
render(
<HighSeverityDelete />
)

After the user deletes the object, navigate them to the original page where they can see a list of all remaining objects.

If the delete is successful, show a success Toast. If the user can undo the deletion, give the user the option to do so in the toast and remove any automatic time out settings. If the undo option is time-bound, tell the user how long they have to undo the deletion.

If the deletion fails, display an error Toast that follows the error state pattern.

Component preview theme
const MediumSeverityDelete = () => {
const [isOpen, setIsOpen] = React.useState(false);
const handleOpen = () => setIsOpen(true);
const handleDismiss = () => setIsOpen(false);
const toaster = useToaster();
const handleConfirm = () => {
setIsOpen(false)
toaster.push({
message: '"Plan A Productions, LLC" was deleted. To undo deletion, return to the regulatory bundle overview.',
variant: 'success',
})
}
return (
<>
<Button variant="destructive" onClick={handleOpen}>Delete</Button>
<AlertDialog
heading="Delete from regulatory bundle?"
isOpen={isOpen}
onConfirm={handleConfirm}
onConfirmLabel="Delete"
onDismiss={handleDismiss}
onDismissLabel="Cancel"
destructive
>
You're about to delete "Plan A Productions, LLC" from this regulatory bundle. This does not impact any other regulatory bundles.
</AlertDialog>
<Toaster left={['space40', 'unset', 'unset']} {...toaster} />
</>
)
}
render(
<MediumSeverityDelete />
)
Do

Use an Alert Dialog for deletion confirmations.

Don't

Don't use a Modal for deletion confirmations.

Do

Show confirmations for deletions that can't be undone, are bulk actions, or involve objects that would be hard to recreate.

Don't

Don't make the user confirm low-severity deletions that can be easily reversed.

Do

Use the Confirmation pattern to structure deletion message content.