-
Notifications
You must be signed in to change notification settings - Fork 0
Custom Content in Dialogs
Zahid edited this page Jun 30, 2025
·
1 revision
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.
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
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 }
)
}
}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
}
}
)
}
}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
}
)
}
}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)
)
}
}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 }
)
}
}- Keep it Focused: Custom content should serve a specific purpose
- Responsive Design: Test your content at different dialog sizes
- Accessibility: Use proper contrast and semantic elements
- Consistent Theming: Use MaterialTheme colors and typography
- Avoid Heavy Operations: Don't perform expensive calculations in dialog content
- State Management: Keep dialog state separate from main application state
- Memory Usage: Clean up resources when dialogs are dismissed
@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 }
)
}
}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 = { }
)
}- Quick Start - Basic dialog usage
Made with ❤️ | Free stuff is the best stuff