Skip to content
This repository was archived by the owner on Jul 7, 2025. It is now read-only.
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 207 additions & 0 deletions content/components/confirmation-dialog.mdx

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
---
title: ConfirmationDialog
description:
ConfirmationDialog is a specialized dialog component used to confirm user actions. It provides a rigid two-button
interface with a cancel and confirm action.
reactId: confirmation-dialog
figmaId: confirmation-dialog
Comment on lines +6 to +7

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ Question for reviewers: how do I validate these IDs are pointing to the correct reference outbound to the React source code or Figma URL?

tags:
- modal
- popup
---

import ComponentLayout from '~/src/layouts/component-layout'
export default ComponentLayout
import {AccessibilityLink} from '~/src/components/accessibility-link'
import {Box} from '@primer/react'
import {Caption} from '@primer/gatsby-theme-doctocat'

ConfirmationDialog is a special kind of dialog with rigid behavior that's used to confirm user actions. It always has exactly two buttons: one to cancel the action and one to confirm it. The component provides no custom rendering capabilities and focuses on consistency across confirmations.

## Anatomy

<img
width="960"
alt="Anatomy of a ConfirmationDialog showing header, body content, and action buttons"
src="https://github.com/user-attachments/assets/fb545bc1-0b21-43dd-bfb4-378ffef894a8"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 This isn't final. We'll need a "real" Anatomy here in place of this one, so it's here as a placeholder.

/>
<Caption>Anatomy of a ConfirmationDialog.</Caption>

### Header region

The **header** region contains the confirmation title and close button. The title should clearly describe the action being confirmed, typically phrased as a question (e.g., "Delete repository?", "Discard changes?").

### Body content

The **body** provides additional context about the action's consequences. This content is passed as children to the ConfirmationDialog component.

### Action buttons

The **action region** contains exactly two buttons: a cancel button (left) and a confirm button (right). The confirm button can be styled as `normal` (default), `primary`, or `danger` depending on the severity of the action.

## Usage

Use ConfirmationDialog for actions that require explicit user confirmation, especially when:

- The action is destructive or irreversible
- The action has significant consequences
- You need a standardized confirmation pattern

### When not to use

- For complex forms or multi-step processes (use [Dialog](/components/dialog) instead)
- When you need custom header or footer content
- For non-destructive actions that can be easily undone

## API

ConfirmationDialog is built on top of the Dialog component but provides a simplified, constrained API:

### Required props

```tsx
<ConfirmationDialog
title="Delete repository?"
onClose={(gesture) => {
// Handle the result
// gesture can be: 'confirm', 'cancel', 'close-button', or 'escape'
}}
>
This action cannot be undone.
</ConfirmationDialog>
```

### Optional props

```tsx
<ConfirmationDialog
title="Delete repository?"
onClose={handleClose}
cancelButtonContent="Cancel" // Default: "Cancel"
confirmButtonContent="Delete" // Default: "OK"
confirmButtonType="danger" // Options: 'normal', 'primary', 'danger'
width="medium" // Options: 'small', 'medium', 'large', 'xlarge'
height="auto" // Options: 'small', 'large', 'auto'
className="custom-class"
>
Content describing the consequences of the action.
</ConfirmationDialog>
```

## Examples

### Basic confirmation

```jsx
function DeleteExample() {
const [isOpen, setIsOpen] = useState(false)

const handleClose = (gesture) => {
if (gesture === 'confirm') {
// Perform the delete action
console.log('Confirmed!')
}
setIsOpen(false)
}

return (
<>
<Button onClick={() => setIsOpen(true)}>Delete item</Button>
{isOpen ? (
<ConfirmationDialog
title="Delete item?"
onClose={handleClose}
>
This action cannot be undone.
</ConfirmationDialog>
) : null}
</>
)
}
```

### Dangerous action

```jsx
<ConfirmationDialog
title="Delete repository?"
onClose={handleClose}
confirmButtonContent="Delete repository"
confirmButtonType="danger"
>
This will permanently delete the repository and all of its contents.
This action cannot be undone.
</ConfirmationDialog>
```

### Using the useConfirm hook

For programmatic confirmations, use the `useConfirm` hook:

```jsx
function ExampleWithHook() {
const confirm = useConfirm()

const handleAction = async () => {
const confirmed = await confirm({
title: 'Are you sure?',
content: 'This action cannot be undone.',
confirmButtonType: 'danger'
})

if (confirmed) {
// Perform the action
}
}

return <Button onClick={handleAction}>Delete</Button>
}
```

## Behavior

### Focus management

- When the confirmation is dangerous (`confirmButtonType="danger"`), focus is placed on the Cancel button
- When the confirmation is not dangerous, focus is placed on the Confirm button
- Focus returns to the triggering element when the dialog closes

### Button types

- **normal** (default): Standard button styling
- **primary**: Emphasized styling for important confirmations
- **danger**: Red styling for destructive actions

### Closing behavior

The `onClose` callback receives a gesture parameter indicating how the dialog was closed:

- `'confirm'`: User clicked the confirm button
- `'cancel'`: User clicked the cancel button
- `'close-button'`: User clicked the X close button
- `'escape'`: User pressed the Escape key

## Accessibility

<AccessibilityLink label="ConfirmationDialog" />

ConfirmationDialog follows dialog accessibility patterns and includes:

- Uses `role="alertdialog"` to indicate urgent content requiring user attention
- Proper focus management and focus trapping
- Keyboard support (Tab, Shift+Tab, Escape)
- Screen reader announcements for the confirmation content
- Clear button labeling for screen readers

### Screen reader considerations

- The title serves as the accessible name for the dialog
- Body content provides additional context
- Button labels should be descriptive and action-oriented
- The dangerous confirmation focus pattern helps prevent accidental confirmations

## Related components

- [Dialog](/components/dialog): For general modal content and custom layouts
- [Button](/components/button): For action triggers that may open confirmation dialogs
- [Banner](/components/banner): For non-modal notifications and warnings