# Dialog

> A modal window for a decision or a small task that needs the user's attention.

- Category: Containment
- API status: Stable
- Compose APIs: `AlertDialog`, `BasicAlertDialog`, `AlertDialogDefaults`
- Interactive page: https://m3e.ljzapps.app/#components/dialog

## When to use

Dialogs interrupt the flow, so reserve them for important choices such as confirming a destructive action. Use AlertDialog for the standard icon, title, text and two buttons, and BasicAlertDialog for custom content such as a list of choices.

Buttons are text buttons. The confirming action goes on the right and uses a verb that names the result.

## Playground

The interactive page has a playground with live property controls for this component and generated code.

## Examples

### Confirmation

Standard AlertDialog.

```kotlin
var open by rememberSaveable { mutableStateOf(false) }

Button(onClick = { open = true }) { Text("Delete draft") }

if (open) {
    AlertDialog(
        onDismissRequest = { open = false },
        icon = { Icon(Icons.Rounded.Delete, contentDescription = null) },
        title = { Text("Delete this draft?") },
        text = { Text("The draft and its attachments are removed. This cannot be undone.") },
        confirmButton = { TextButton(onClick = { open = false }) { Text("Delete") } },
        dismissButton = { TextButton(onClick = { open = false }) { Text("Cancel") } },
    )
}
```

### Single choice

BasicAlertDialog with custom content.

```kotlin
var open by rememberSaveable { mutableStateOf(false) }
val options = listOf("Phone ringtone", "Alarm", "Silent")
var selected by rememberSaveable { mutableStateOf(options.first()) }

Button(onClick = { open = true }) { Text("Notification sound") }

if (open) {
    BasicAlertDialog(onDismissRequest = { open = false }) {
        Surface(shape = MaterialTheme.shapes.extraLarge, tonalElevation = 6.dp) {
            Column(Modifier.padding(24.dp)) {
                Text("Notification sound", style = MaterialTheme.typography.headlineSmall)
                Column(Modifier.selectableGroup().padding(vertical = 16.dp)) {
                    options.forEach { option ->
                        Row(
                            Modifier
                                .fillMaxWidth()
                                .selectable(option == selected, onClick = { selected = option }, role = Role.RadioButton),
                            verticalAlignment = Alignment.CenterVertically,
                        ) {
                            RadioButton(selected = option == selected, onClick = null)
                            Text(option, Modifier.padding(start = 16.dp, top = 12.dp, bottom = 12.dp))
                        }
                    }
                }
                Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {
                    TextButton(onClick = { open = false }) { Text("Cancel") }
                    TextButton(onClick = { open = false }) { Text("OK") }
                }
            }
        }
    }
}
```

## Parameters

| Name | Type | Default | Description |
|---|---|---|---|
| `onDismissRequest` | `() -> Unit` |  | Called on scrim click, back or Escape. |
| `confirmButton` | `@Composable () -> Unit` |  | The affirmative action. |
| `dismissButton` | `@Composable (() -> Unit)?` | `null` | The neutral or negative action. |
| `icon / title / text` | `@Composable (() -> Unit)?` | `null` | Optional content slots. |
| `properties` | `DialogProperties` | `DialogProperties()` | Dismiss on back and outside click, platform behavior. |

## Guidelines

Do:
- Ask one question per dialog.
- Name the confirming action with a verb.

Don't:
- Do not open a dialog from another dialog.
- Do not use a dialog for information that is not actionable.

## Accessibility

- Focus moves into the dialog when it opens and returns to the trigger when it closes.
- The title is announced first. Without a title, make the text self explanatory.
- Escape and the scrim dismiss the dialog. Do not remove both without offering a visible way out.

## Related components

- [Snackbar](https://m3e.ljzapps.app/docs/components/snackbar.md)
- [Bottom sheet](https://m3e.ljzapps.app/docs/components/bottom-sheet.md)
- [Buttons](https://m3e.ljzapps.app/docs/components/button.md)
