IconButton provides clickable icon containers with various styling options including filled, outlined, elevated, and ghost variants. Perfect for toolbars, app bars, and compact action buttons.
Usage
import com.nomanr.lumo.ui.components.IconButton
import com.nomanr.lumo.ui.components.IconButtonVariant
IconButton(
variant = IconButtonVariant.Primary,
onClick = { /* Handle click */ }
) {
Icon(Icons.Default.Add, "Add")
}
Variants
Primary Variants
// Filled primary button
IconButton(
variant = IconButtonVariant.Primary,
onClick = { }
) {
Icon(Icons.Default.Edit, "Edit")
}
// Outlined primary button
IconButton(
variant = IconButtonVariant.PrimaryOutlined,
onClick = { }
) {
Icon(Icons.Default.Edit, "Edit")
}
// Elevated primary button
IconButton(
variant = IconButtonVariant.PrimaryElevated,
onClick = { }
) {
Icon(Icons.Default.Edit, "Edit")
}
// Ghost primary button (transparent)
IconButton(
variant = IconButtonVariant.PrimaryGhost,
onClick = { }
) {
Icon(Icons.Default.Edit, "Edit")
}
Secondary Variants
// Filled secondary
IconButton(
variant = IconButtonVariant.Secondary,
onClick = { }
) {
Icon(Icons.Default.Settings, "Settings")
}
// Outlined secondary
IconButton(
variant = IconButtonVariant.SecondaryOutlined,
onClick = { }
) {
Icon(Icons.Default.Settings, "Settings")
}
// Elevated secondary
IconButton(
variant = IconButtonVariant.SecondaryElevated,
onClick = { }
) {
Icon(Icons.Default.Settings, "Settings")
}
// Ghost secondary
IconButton(
variant = IconButtonVariant.SecondaryGhost,
onClick = { }
) {
Icon(Icons.Default.Settings, "Settings")
}
Destructive Variants
For delete, remove, or other destructive actions:
// Filled destructive
IconButton(
variant = IconButtonVariant.Destructive,
onClick = { /* Delete action */ }
) {
Icon(Icons.Default.Delete, "Delete")
}
// Outlined destructive
IconButton(
variant = IconButtonVariant.DestructiveOutlined,
onClick = { }
) {
Icon(Icons.Default.Delete, "Delete")
}
// Elevated destructive
IconButton(
variant = IconButtonVariant.DestructiveElevated,
onClick = { }
) {
Icon(Icons.Default.Delete, "Delete")
}
// Ghost destructive
IconButton(
variant = IconButtonVariant.DestructiveGhost,
onClick = { }
) {
Icon(Icons.Default.Delete, "Delete")
}
Ghost Variant
Adapts to any background color:
CompositionLocalProvider(
LocalContentColor provides contentColorFor(AppTheme.colors.background)
) {
IconButton(
variant = IconButtonVariant.Ghost,
onClick = { }
) {
Icon(Icons.Default.Menu, "Menu")
}
}
Square Shape (Default)
IconButton(
variant = IconButtonVariant.Primary,
shape = IconButtonDefaults.ButtonSquareShape, // RoundedCornerShape(12.dp)
onClick = { }
) {
Icon(Icons.Default.Star, "Favorite")
}
Circle Shape
IconButton(
variant = IconButtonVariant.Primary,
shape = IconButtonDefaults.ButtonCircleShape, // RoundedCornerShape(50%)
onClick = { }
) {
Icon(Icons.Default.Person, "Profile")
}
Custom Shape
IconButton(
variant = IconButtonVariant.Primary,
shape = RoundedCornerShape(8.dp),
onClick = { }
) {
Icon(Icons.Default.Notifications, "Notifications")
}
Enabled and Disabled
var isEnabled by remember { mutableStateOf(true) }
IconButton(
variant = IconButtonVariant.Primary,
enabled = isEnabled,
onClick = { /* Only called when enabled */ }
) {
Icon(Icons.Default.Send, "Send")
}
Loading State
var isLoading by remember { mutableStateOf(false) }
IconButton(
variant = IconButtonVariant.Primary,
loading = isLoading,
onClick = {
isLoading = true
// Perform async operation
}
) {
if (isLoading) {
CircularProgressIndicator(
modifier = Modifier.size(20.dp),
strokeWidth = 2.dp
)
} else {
Icon(Icons.Default.Upload, "Upload")
}
}
Parameters
modifier
Modifier
default:"Modifier"
Modifier for the icon button
Whether the button is enabled and clickable
Whether the button is in a loading state
variant
IconButtonVariant
default:"IconButtonVariant.Primary"
The visual variant of the button (Primary, Secondary, Destructive, etc.)
shape
Shape
default:"IconButtonDefaults.ButtonSquareShape"
The shape of the button container
Callback when the button is clicked
contentPadding
PaddingValues
default:"PaddingValues(4.dp)"
Padding around the button content
Interaction source for tracking user interactions
content
@Composable () -> Unit
required
The icon content to display inside the button
Styling
Custom Padding
IconButton(
variant = IconButtonVariant.Primary,
contentPadding = PaddingValues(12.dp),
onClick = { }
) {
Icon(Icons.Default.Add, "Add")
}
With Modifier
IconButton(
variant = IconButtonVariant.Primary,
modifier = Modifier
.size(56.dp)
.padding(8.dp),
onClick = { }
) {
Icon(Icons.Default.Favorite, "Favorite")
}
Common Use Cases
App Bar Actions
TopBar(
title = { Text("My App") },
actions = {
IconButton(
variant = IconButtonVariant.Ghost,
onClick = { /* Search */ }
) {
Icon(Icons.Default.Search, "Search")
}
IconButton(
variant = IconButtonVariant.Ghost,
onClick = { /* More options */ }
) {
Icon(Icons.Default.MoreVert, "More")
}
}
)
IconButton(
variant = IconButtonVariant.PrimaryElevated,
shape = IconButtonDefaults.ButtonCircleShape,
modifier = Modifier.size(56.dp),
onClick = { /* Add new item */ }
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Add",
modifier = Modifier.size(24.dp)
)
}
var isFavorite by remember { mutableStateOf(false) }
IconButton(
variant = if (isFavorite) {
IconButtonVariant.Primary
} else {
IconButtonVariant.PrimaryOutlined
},
shape = IconButtonDefaults.ButtonCircleShape,
onClick = { isFavorite = !isFavorite }
) {
Icon(
imageVector = if (isFavorite) {
Icons.Filled.Favorite
} else {
Icons.Outlined.FavoriteBorder
},
contentDescription = if (isFavorite) "Unfavorite" else "Favorite",
tint = if (isFavorite) Color.Red else LocalContentColor.current
)
}
List Item Actions
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text("Item Title")
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
IconButton(
variant = IconButtonVariant.SecondaryGhost,
onClick = { /* Edit */ }
) {
Icon(Icons.Default.Edit, "Edit")
}
IconButton(
variant = IconButtonVariant.DestructiveGhost,
onClick = { /* Delete */ }
) {
Icon(Icons.Default.Delete, "Delete")
}
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
IconButton(
variant = IconButtonVariant.SecondaryGhost,
onClick = { /* Previous */ }
) {
Icon(Icons.Default.SkipPrevious, "Previous")
}
IconButton(
variant = IconButtonVariant.Primary,
shape = IconButtonDefaults.ButtonCircleShape,
modifier = Modifier.size(56.dp),
onClick = { /* Play/Pause */ }
) {
Icon(
imageVector = if (isPlaying) {
Icons.Default.Pause
} else {
Icons.Default.PlayArrow
},
contentDescription = if (isPlaying) "Pause" else "Play",
modifier = Modifier.size(28.dp)
)
}
IconButton(
variant = IconButtonVariant.SecondaryGhost,
onClick = { /* Next */ }
) {
Icon(Icons.Default.SkipNext, "Next")
}
}
Defaults
- Button Size: 44.dp (minimum touch target)
- Content Padding: 4.dp
- Square Shape: RoundedCornerShape(12.dp)
- Circle Shape: RoundedCornerShape(50%)
- Outline Width: 1.dp
- Elevation (Elevated variants): 2.dp
Best Practices
- Touch Targets: Maintain 44dp minimum size for accessibility
- Content Descriptions: Always provide meaningful icon descriptions
- Variant Selection: Use appropriate variants for visual hierarchy
- Destructive Actions: Always use Destructive variants for delete/remove actions
- Loading States: Show loading indicators during async operations
- Disabled State: Clearly communicate when buttons are disabled
- Consistency: Use consistent icon sizes (typically 24dp)
Accessibility
- Button role is automatically set for screen readers
- Minimum 44dp touch target is enforced by default
- Disabled state is properly communicated
- Icon content descriptions are read by screen readers
Source Reference
See the full implementation in IconButton.kt:42-65 (component) and IconButton.kt:110-124 (variants).