Skip to content

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

kotlin
import io.github.suqi8.coui.kmp.overlay.OverlayDialog

Basic Usage

OverlayDialog component provides basic dialog functionality:

kotlin
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 NameTypeDescriptionDefault ValueRequired
showBooleanWhether to show the dialog-Yes
modifierModifierModifier applied to the dialogModifierNo
titleString?Dialog titlenullNo
titleColorColorTitle text colorDialogDefaults.titleColor()No
summaryString?Dialog summary textnullNo
summaryColorColorSummary text colorDialogDefaults.summaryColor()No
backgroundColorColorDialog background colorDialogDefaults.backgroundColor()No
enableWindowDimBooleanWhether to enable dimming layertrueNo
onDismissRequest(() -> Unit)?Called when the user requests dismissal (outside tap or back)nullNo
onDismissFinished(() -> Unit)?Invoked after the hide animation completes; not invoked if the hide is cancelled mid-flight (e.g., show toggled back to true)nullNo
outsideMarginDpSizeDialog external marginDialogDefaults.outsideMarginNo
insideMarginDpSizeMargin for the built-in title/summary texts (width = horizontal padding, height = padding above the title); the content slot is unpaddedDialogDefaults.insideMarginNo
defaultWindowInsetsPaddingBooleanWhether to apply default window insets paddingtrueNo
renderInRootScaffoldBooleanWhether 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 boundstrueNo
maxWidthDpMaximum width of the dialogDialogDefaults.MaxWidthNo
largeScreenBoolean?Override for the large-screen presentation (centered scale/fade instead of bottom slide-in); when null, detected from the window sizenullNo
cornerRadiusDp?Corner radius override; when null, DialogDefaults.CornerRadius is usednullNo
content@Composable () -> UnitDialog content-Yes

DialogDefaults Object

The DialogDefaults object provides default settings for the OverlayDialog component.

Properties

Property NameTypeDescription
CornerRadiusDpDialog panel corner radius (19.dp)
MaxWidthDpMaximum dialog content width (392.dp)
outsideMarginDpSizeDefault dialog external margin (16, 24)
insideMarginDpSizeDefault margin for the built-in title/summary texts (24, 24); the content slot is unpadded
ButtonBarMinHeightDpMin height of a horizontal dialog button bar (58.dp)
ButtonBarInsideMarginPaddingValuesPaddings of a button in a horizontal bar (24dp horizontal, 12dp top, 22dp bottom); the panel bottom inset is carried by the buttons
ButtonBarDividerThicknessDpThickness of the divider between horizontal bar buttons (1.dp)
ButtonBarDividerInsetTopDpTop inset of the divider between horizontal bar buttons (17.dp)
ButtonBarDividerInsetBottomDpBottom inset of the divider between horizontal bar buttons (21.dp)

Functions

Function NameReturn TypeDescription
titleColor()ColorGet default title color
summaryColor()ColorGet default summary color
backgroundColor()ColorGet 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:

kotlin
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

kotlin
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

kotlin
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

kotlin
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

kotlin
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

kotlin
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
                    }
                )
            }
        }
    }
}

Changelog

Released under the Apache-2.0 License