OverlayDialog
OverlayDialog is a dialog component in COUI used to display important information, collect user input, or confirm user actions. The dialog appears above the current interface and supports custom styles and content layouts.
Prerequisite
This component depends on Scaffold providing COUIPopupHost to render popup content. It must be used within Scaffold, otherwise popup content will not render correctly.
Import
import io.github.suqi8.coui.kmp.overlay.OverlayDialogBasic Usage
OverlayDialog component provides basic dialog functionality:
var showDialog by remember { mutableStateOf(false) }
Scaffold {
TextButton(
text = "Show Dialog",
onClick = { showDialog = true }
)
OverlayDialog(
title = "Dialog Title",
summary = "This is a basic dialog example that can contain various content.",
show = showDialog,
onDismissRequest = { showDialog = false } // Close dialog
) {
TextButton(
text = "Confirm",
onClick = { showDialog = false }, // Close dialog
modifier = Modifier.fillMaxWidth()
)
}
}Properties
OverlayDialog Properties
| Property Name | Type | Description | Default Value | Required |
|---|---|---|---|---|
| show | Boolean | Whether to show the dialog | - | Yes |
| modifier | Modifier | Modifier applied to the dialog | Modifier | No |
| title | String? | Dialog title | null | No |
| titleColor | Color | Title text color | DialogDefaults.titleColor() | No |
| summary | String? | Dialog summary text | null | No |
| summaryColor | Color | Summary text color | DialogDefaults.summaryColor() | No |
| backgroundColor | Color | Dialog background color | DialogDefaults.backgroundColor() | No |
| enableWindowDim | Boolean | Whether to enable dimming layer | true | No |
| onDismissRequest | (() -> Unit)? | Called when the user requests dismissal (outside tap or back) | null | No |
| onDismissFinished | (() -> Unit)? | Invoked after the hide animation completes; not invoked if the hide is cancelled mid-flight (e.g., show toggled back to true) | null | No |
| outsideMargin | DpSize | Dialog external margin | DialogDefaults.outsideMargin | No |
| insideMargin | DpSize | Margin for the built-in title/summary texts (width = horizontal padding, height = padding above the title); the content slot is unpadded | DialogDefaults.insideMargin | No |
| defaultWindowInsetsPadding | Boolean | Whether to apply default window insets padding | true | No |
| renderInRootScaffold | Boolean | Whether to render the dialog in the root (outermost) Scaffold. When true, the dialog covers the full screen. When false, it renders within the current Scaffold's bounds | true | No |
| maxWidth | Dp | Maximum width of the dialog | DialogDefaults.MaxWidth | No |
| largeScreen | Boolean? | Override for the large-screen presentation (centered scale/fade instead of bottom slide-in); when null, detected from the window size | null | No |
| cornerRadius | Dp? | Corner radius override; when null, DialogDefaults.CornerRadius is used | null | No |
| content | @Composable () -> Unit | Dialog content | - | Yes |
DialogDefaults Object
The DialogDefaults object provides default settings for the OverlayDialog component.
Properties
| Property Name | Type | Description |
|---|---|---|
| CornerRadius | Dp | Dialog panel corner radius (19.dp) |
| MaxWidth | Dp | Maximum dialog content width (392.dp) |
| outsideMargin | DpSize | Default dialog external margin (16, 24) |
| insideMargin | DpSize | Default margin for the built-in title/summary texts (24, 24); the content slot is unpadded |
| ButtonBarMinHeight | Dp | Min height of a horizontal dialog button bar (58.dp) |
| ButtonBarInsideMargin | PaddingValues | Paddings of a button in a horizontal bar (24dp horizontal, 12dp top, 22dp bottom); the panel bottom inset is carried by the buttons |
| ButtonBarDividerThickness | Dp | Thickness of the divider between horizontal bar buttons (1.dp) |
| ButtonBarDividerInsetTop | Dp | Top inset of the divider between horizontal bar buttons (17.dp) |
| ButtonBarDividerInsetBottom | Dp | Bottom inset of the divider between horizontal bar buttons (21.dp) |
Functions
| Function Name | Return Type | Description |
|---|---|---|
| titleColor() | Color | Get default title color |
| summaryColor() | Color | Get default summary color |
| backgroundColor() | Color | Get default dialog background color |
Advanced Usage
Centered Presentation (Large Screens)
On windows at least 840dp wide and 480dp tall, the dialog is automatically centered and uses scale/fade transitions instead of sliding up from the bottom. Use largeScreen to force either presentation, and cornerRadius to override the panel radius:
var showDialog by remember { mutableStateOf(false) }
Scaffold {
TextButton(
text = "Show Centered Dialog",
onClick = { showDialog = true }
)
OverlayDialog(
title = "Centered Dialog",
summary = "This dialog is always centered, regardless of window size",
show = showDialog,
largeScreen = true, // Force the centered presentation
cornerRadius = 24.dp, // Override the panel corner radius
maxWidth = 320.dp,
onDismissRequest = { showDialog = false }
) {
TextButton(
text = "Confirm",
onClick = { showDialog = false },
modifier = Modifier.fillMaxWidth()
)
}
}Custom Styled Dialog
var showDialog by remember { mutableStateOf(false) }
Scaffold {
TextButton(
text = "Show Custom Styled Dialog",
onClick = { showDialog = true }
)
OverlayDialog(
title = "Custom Style",
summary = "This dialog uses custom colors and margins",
show = showDialog,
onDismissRequest = { showDialog = false }, // Close dialog
titleColor = Color.Blue,
summaryColor = Color.Gray,
backgroundColor = Color(0xFFF5F5F5),
outsideMargin = DpSize(20.dp, 20.dp),
insideMargin = DpSize(30.dp, 30.dp)
) {
Text(
text = "Custom Content Area",
modifier = Modifier.padding(vertical = 16.dp)
)
TextButton(
text = "Close",
onClick = { showDialog = false }, // Close dialog
modifier = Modifier.fillMaxWidth()
)
}
}Creating a Confirmation Dialog
var showConfirmDialog by remember { mutableStateOf(false) }
var result by remember { mutableStateOf("") }
Scaffold {
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
TextButton(
text = "Show Confirmation Dialog",
onClick = { showConfirmDialog = true }
)
Text("Result: $result")
}
OverlayDialog(
title = "Confirm Action",
summary = "This action is irreversible, do you want to proceed?",
show = showConfirmDialog,
onDismissRequest = { showConfirmDialog = false } // Close dialog
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween
) {
TextButton(
text = "Cancel",
onClick = {
result = "User cancelled the action"
showConfirmDialog = false // Close dialog
},
modifier = Modifier.weight(1f)
)
Spacer(Modifier.width(20.dp))
TextButton(
text = "Confirm",
onClick = {
result = "User confirmed the action"
showConfirmDialog = false // Close dialog
},
modifier = Modifier.weight(1f),
colors = ButtonDefaults.textButtonColorsPrimary()
)
}
}
}Dialog with Input Field
var showDialog by remember { mutableStateOf(false) }
var textFieldValue by remember { mutableStateOf("") }
Scaffold {
TextButton(
text = "Show Input Dialog",
onClick = { showDialog = true }
)
OverlayDialog(
title = "Please Enter Content",
show = showDialog,
onDismissRequest = { showDialog = false } // Close dialog
) {
TextField(
modifier = Modifier.padding(bottom = 16.dp),
value = textFieldValue,
maxLines = 1,
onValueChange = { textFieldValue = it }
)
Row(
horizontalArrangement = Arrangement.SpaceBetween
) {
TextButton(
text = "Cancel",
onClick = { showDialog = false }, // Close dialog
modifier = Modifier.weight(1f)
)
Spacer(Modifier.width(20.dp))
TextButton(
text = "Confirm",
onClick = { showDialog = false }, // Close dialog
modifier = Modifier.weight(1f),
colors = ButtonDefaults.textButtonColorsPrimary() // Use theme color
)
}
}
}Dialog with Form
var showDialog by remember { mutableStateOf(false) }
var dropdownSelectedOption by remember { mutableStateOf(0) }
var switchState by remember { mutableStateOf(false) }
val dropdownOptions = listOf("Option 1", "Option 2")
Scaffold {
TextButton(
text = "Show Form Dialog",
onClick = { showDialog = true }
)
OverlayDialog(
title = "Form Dialog",
show = showDialog,
onDismissRequest = { showDialog = false } // Close dialog
) {
Card(
colors = CardDefaults.defaultColors(
color = COUITheme.colorScheme.secondaryContainer,
),
) {
OverlayDropdownPreference(
title = "Dropdown Selection",
items = dropdownOptions,
selectedIndex = dropdownSelectedOption,
onSelectedIndexChange = { dropdownSelectedOption = it }
)
SwitchPreference(
title = "Switch Option",
checked = switchState,
onCheckedChange = { switchState = it }
)
}
Spacer(Modifier.height(12.dp))
Row(
horizontalArrangement = Arrangement.SpaceBetween
) {
TextButton(
text = "Cancel",
onClick = { showDialog = false }, // Close dialog
modifier = Modifier.weight(1f)
)
Spacer(Modifier.width(20.dp))
TextButton(
text = "Confirm",
onClick = { showDialog = false }, // Close dialog
modifier = Modifier.weight(1f),
colors = ButtonDefaults.textButtonColorsPrimary() // Use theme color
)
}
}
}Dialog with Color Picker
var showColorDialog by remember { mutableStateOf(false) }
var selectedColor by remember { mutableStateOf(Color.Red) }
Scaffold {
TextButton(
text = "Select Color",
onClick = { showColorDialog = true }
)
OverlayDialog(
title = "Select Color",
show = showColorDialog,
onDismissRequest = { showColorDialog = false } // Close dialog
) {
Column {
ColorPicker(
initialColor = selectedColor,
onColorChanged = { selectedColor = it }
)
Spacer(modifier = Modifier.height(16.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
TextButton(
modifier = Modifier.weight(1f),
text = "Cancel",
onClick = { showColorDialog = false } // Close dialog
)
TextButton(
modifier = Modifier.weight(1f),
text = "Confirm",
colors = ButtonDefaults.textButtonColorsPrimary(), // Use theme color
onClick = {
showColorDialog = false // Close dialog
// Handle confirm logic
}
)
}
}
}
}

