Skip to content

Custom Content in Dialogs

Zahid edited this page Jun 30, 2025 · 1 revision

Custom Content in Dialogs

While Deskit dialogs come with sensible defaults, you can completely customize their content to create rich, interactive experiences. This guide shows you how to replace the default message text with custom Composable content.

Overview

Both InfoDialog and ConfirmationDialog support custom content through their content parameter. This allows you to:

  • Display complex layouts with multiple components
  • Add interactive elements like progress bars and buttons
  • Create branded dialogs with custom styling
  • Show data in tables, lists, or cards

Basic Custom Content

Simple Multi-Component Layout

Replace the default message with multiple text components:

@Composable
fun CustomInfoExample() {
    var showDialog by remember { mutableStateOf(false) }

    Button(onClick = { showDialog = true }) {
        Text("Show Custom Info")
    }

    if (showDialog) {
        InfoDialog(
            title = "System Information",
            icon = painterResource(Res.drawable.info),
            content = {
                Column(
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    Text(
                        text = "Application Status",
                        style = MaterialTheme.typography.titleMedium,
                        fontWeight = FontWeight.Bold
                    )
                    Text(
                        text = "Version: 1.3.0",
                        style = MaterialTheme.typography.bodyMedium
                    )
                    Text(
                        text = "Status: Running",
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.primary
                    )
                }
            },
            onClose = { showDialog = false }
        )
    }
}

Progress and Status Dialogs

Progress Indicator Dialog

Show progress with real-time updates:

@Composable
fun ProgressDialogExample() {
    var showDialog by remember { mutableStateOf(false) }
    var progress by remember { mutableStateOf(0f) }

    // Simulate progress
    LaunchedEffect(showDialog) {
        if (showDialog) {
            while (progress < 1f) {
                delay(100)
                progress += 0.05f
            }
        }
    }

    Button(onClick = { 
        showDialog = true
        progress = 0f
    }) {
        Text("Start Process")
    }

    if (showDialog) {
        InfoDialog(
            width = 450.dp,
            height = 300.dp,
            title = "Processing Files",
            icon = painterResource(Res.drawable.loading),
            content = {
                Column(
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.spacedBy(16.dp)
                ) {
                    Text(
                        text = "Processing your files...",
                        style = MaterialTheme.typography.bodyLarge
                    )
                    
                    LinearProgressIndicator(
                        progress = { progress },
                        modifier = Modifier.fillMaxWidth(),
                        color = MaterialTheme.colorScheme.primary,
                    )
                    
                    Text(
                        text = "${(progress * 100).toInt()}% Complete",
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                    
                    if (progress >= 1f) {
                        Text(
                            text = "✓ Processing Complete!",
                            style = MaterialTheme.typography.bodyMedium,
                            color = MaterialTheme.colorScheme.primary,
                            fontWeight = FontWeight.Bold
                        )
                    }
                }
            },
            onClose = { 
                if (progress >= 1f) {
                    showDialog = false
                }
            }
        )
    }
}

Interactive Confirmation Dialogs

Form-Based Confirmation

Create a confirmation dialog with input fields:

@Composable
fun FormConfirmationExample() {
    var showDialog by remember { mutableStateOf(false) }
    var userName by remember { mutableStateOf("") }
    var confirmed by remember { mutableStateOf(false) }

    Button(onClick = { showDialog = true }) {
        Text("Delete Account")
    }

    if (showDialog) {
        ConfirmationDialog(
            width = 500.dp,
            height = 350.dp,
            title = "Delete Account",
            icon = painterResource(Res.drawable.warning),
            iconTint = MaterialTheme.colorScheme.error,
            confirmButtonText = "Delete Account",
            cancelButtonText = "Cancel",
            content = {
                Column(
                    verticalArrangement = Arrangement.spacedBy(16.dp)
                ) {
                    Text(
                        text = "This action will permanently delete your account and all associated data.",
                        style = MaterialTheme.typography.bodyLarge,
                        color = MaterialTheme.colorScheme.error
                    )
                    
                    Text(
                        text = "To confirm, please type your username:",
                        style = MaterialTheme.typography.bodyMedium
                    )
                    
                    OutlinedTextField(
                        value = userName,
                        onValueChange = { userName = it },
                        label = { Text("Username") },
                        modifier = Modifier.fillMaxWidth(),
                        singleLine = true
                    )
                    
                    Row(
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        Checkbox(
                            checked = confirmed,
                            onCheckedChange = { confirmed = it }
                        )
                        Spacer(Modifier.width(8.dp))
                        Text(
                            text = "I understand this action cannot be undone",
                            style = MaterialTheme.typography.bodySmall
                        )
                    }
                }
            },
            onConfirm = {
                if (userName.isNotBlank() && confirmed) {
                    // Perform account deletion
                    showDialog = false
                }
            },
            onCancel = { 
                showDialog = false
                userName = ""
                confirmed = false
            }
        )
    }
}

Data Display Dialogs

Information Card Layout

Display structured information in cards:

@Composable
fun DataDisplayExample() {
    var showDialog by remember { mutableStateOf(false) }

    Button(onClick = { showDialog = true }) {
        Text("View Details")
    }

    if (showDialog) {
        InfoDialog(
            width = 600.dp,
            height = 500.dp,
            title = "File Details",
            resizable = true,
            content = {
                Column(
                    verticalArrangement = Arrangement.spacedBy(16.dp)
                ) {
                    // File Info Card
                    Card(
                        modifier = Modifier.fillMaxWidth(),
                        colors = CardDefaults.cardColors(
                            containerColor = MaterialTheme.colorScheme.surfaceVariant
                        )
                    ) {
                        Column(
                            modifier = Modifier.padding(16.dp),
                            verticalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            Text(
                                text = "File Information",
                                style = MaterialTheme.typography.titleMedium,
                                fontWeight = FontWeight.Bold
                            )
                            InfoRow("Name", "document.pdf")
                            InfoRow("Size", "2.4 MB")
                            InfoRow("Modified", "June 30, 2025")
                            InfoRow("Type", "PDF Document")
                        }
                    }
                    
                    // Permissions Card
                    Card(
                        modifier = Modifier.fillMaxWidth(),
                        colors = CardDefaults.cardColors(
                            containerColor = MaterialTheme.colorScheme.surfaceVariant
                        )
                    ) {
                        Column(
                            modifier = Modifier.padding(16.dp),
                            verticalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            Text(
                                text = "Permissions",
                                style = MaterialTheme.typography.titleMedium,
                                fontWeight = FontWeight.Bold
                            )
                            PermissionRow("Read", true)
                            PermissionRow("Write", true)
                            PermissionRow("Execute", false)
                        }
                    }
                }
            },
            onClose = { showDialog = false }
        )
    }
}

@Composable
private fun InfoRow(label: String, value: String) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        Text(
            text = label,
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant
        )
        Text(
            text = value,
            style = MaterialTheme.typography.bodyMedium,
            fontWeight = FontWeight.Medium
        )
    }
}

@Composable
private fun PermissionRow(permission: String, granted: Boolean) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            text = permission,
            style = MaterialTheme.typography.bodyMedium
        )
        Icon(
            imageVector = if (granted) Icons.Default.Check else Icons.Default.Close,
            contentDescription = if (granted) "Granted" else "Denied",
            tint = if (granted) MaterialTheme.colorScheme.primary 
                   else MaterialTheme.colorScheme.error,
            modifier = Modifier.size(20.dp)
        )
    }
}

List and Selection Dialogs

Selectable List Dialog

Create a dialog with selectable items:

@Composable
fun SelectionDialogExample() {
    var showDialog by remember { mutableStateOf(false) }
    var selectedItems by remember { mutableStateOf(setOf<String>()) }
    
    val items = listOf("Option 1", "Option 2", "Option 3", "Option 4", "Option 5")

    Button(onClick = { showDialog = true }) {
        Text("Select Items")
    }

    if (showDialog) {
        ConfirmationDialog(
            width = 450.dp,
            height = 400.dp,
            title = "Select Options",
            confirmButtonText = "Apply",
            cancelButtonText = "Cancel",
            content = {
                Column {
                    Text(
                        text = "Choose the options you want to enable:",
                        style = MaterialTheme.typography.bodyMedium,
                        modifier = Modifier.padding(bottom = 16.dp)
                    )
                    
                    LazyColumn(
                        verticalArrangement = Arrangement.spacedBy(8.dp)
                    ) {
                        items(items) { item ->
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .clickable {
                                        selectedItems = if (item in selectedItems) {
                                            selectedItems - item
                                        } else {
                                            selectedItems + item
                                        }
                                    }
                                    .padding(vertical = 4.dp),
                                verticalAlignment = Alignment.CenterVertically
                            ) {
                                Checkbox(
                                    checked = item in selectedItems,
                                    onCheckedChange = { checked ->
                                        selectedItems = if (checked) {
                                            selectedItems + item
                                        } else {
                                            selectedItems - item
                                        }
                                    }
                                )
                                Spacer(Modifier.width(8.dp))
                                Text(
                                    text = item,
                                    style = MaterialTheme.typography.bodyMedium
                                )
                            }
                        }
                    }
                }
            },
            onConfirm = {
                // Apply selected options
                showDialog = false
            },
            onCancel = { showDialog = false }
        )
    }
}

Best Practices

Content Guidelines

  1. Keep it Focused: Custom content should serve a specific purpose
  2. Responsive Design: Test your content at different dialog sizes
  3. Accessibility: Use proper contrast and semantic elements
  4. Consistent Theming: Use MaterialTheme colors and typography

Performance Tips

  1. Avoid Heavy Operations: Don't perform expensive calculations in dialog content
  2. State Management: Keep dialog state separate from main application state
  3. Memory Usage: Clean up resources when dialogs are dismissed

Example: Optimized Custom Content

@Composable
fun OptimizedCustomDialog() {
    var showDialog by remember { mutableStateOf(false) }
    
    // Prepare data outside of dialog
    val dialogData = remember {
        // Expensive computation here
        generateDialogData()
    }

    if (showDialog) {
        InfoDialog(
            title = "Optimized Content",
            content = {
                // Light content that uses pre-computed data
                DisplayData(data = dialogData)
            },
            onClose = { showDialog = false }
        )
    }
}

Styling and Theming

Custom Theme Integration

Make your custom content consistent with your app's theme:

@Composable
fun ThemedCustomContent() {
    InfoDialog(
        title = "Themed Dialog",
        content = {
            Column(
                verticalArrangement = Arrangement.spacedBy(12.dp)
            ) {
                Text(
                    text = "Primary Text",
                    color = MaterialTheme.colorScheme.primary,
                    style = MaterialTheme.typography.titleMedium
                )
                
                Text(
                    text = "Secondary Text",
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                    style = MaterialTheme.typography.bodyMedium
                )
                
                HorizontalDivider(
                    color = MaterialTheme.colorScheme.outline
                )
                
                Surface(
                    color = MaterialTheme.colorScheme.surfaceVariant,
                    shape = MaterialTheme.shapes.medium
                ) {
                    Text(
                        text = "Surface content",
                        modifier = Modifier.padding(16.dp)
                    )
                }
            }
        },
        onClose = { }
    )
}

Related Topics

Clone this wiki locally