Skip to main content

UI Components Module

Presentation layer module with ready-to-use Material 3 composables, full theming support, and MiruResourceView for declarative loading states.

implementation("io.github.wahidabd:miru-sdk-ui-components:<version>")

Theming​

Customize the entire UI library per project:

MiruTheme(
colorScheme = MiruColorScheme(
primary = Color(0xFF1E88E5),
secondary = Color(0xFFFF6F00),
background = Color(0xFFFAFAFA),
surface = Color(0xFFFFFFFF),
error = Color(0xFFD32F2F),
onPrimary = Color.White,
onBackground = Color(0xFF212121),
// ... your brand colors
),
typography = MiruTypography(
titleLarge = TextStyle(fontSize = 22.sp, fontWeight = FontWeight.Bold),
titleMedium = TextStyle(fontSize = 18.sp, fontWeight = FontWeight.SemiBold),
bodyLarge = TextStyle(fontSize = 16.sp),
bodyMedium = TextStyle(fontSize = 14.sp),
// ... your typography
)
) {
// All Miru components inherit these values
MiruButton(text = "Submit", onClick = { })
}

Access theme values anywhere inside the MiruTheme scope:

Text(
text = "Hello",
color = MiruTheme.colorScheme.primary,
style = MiruTheme.typography.titleMedium
)
tip

See Theming Guide for a complete walkthrough.

MiruResourceView​

Eliminates repetitive when (resource) boilerplate. Works with any StateFlow<Resource<T>>:

val usersResource by viewModel.users.collectAsStateWithLifecycle()

MiruResourceView(
resource = usersResource,
loadingMessage = "Loading users...",
onRetry = { viewModel.loadUsers() }
) { users ->
LazyColumn {
items(users, key = { it.id }) { user ->
UserCard(user)
}
}
}

Custom Loading & Error​

MiruResourceView(
resource = feedResource,
onRetry = { viewModel.refresh() },
onLoading = { MyCustomShimmer() },
onError = { message -> MyCustomErrorBanner(message) }
) { data ->
FeedContent(data)
}

Parameters​

ParameterTypeDescription
resourceResource<T>The resource state to render
modifierModifierOptional modifier
loadingMessageString?Message shown during loading
onRetry(() -> Unit)?Retry callback for error state
onLoading(@Composable () -> Unit)?Custom loading composable
onError(@Composable (String) -> Unit)?Custom error composable
content@Composable (T) -> UnitContent rendered on success
info

MiruResourceView is agnostic to the data source. Whether populated by collectResource, collectFlow, collectFlowResource, execute, or collect — it works the same.

Available Components​

Buttons​

MiruButton(
text = "Submit",
onClick = { },
enabled = true,
loading = false
)

Text Fields​

MiruTextField(
value = text,
onValueChange = { text = it },
label = "Email",
placeholder = "Enter your email"
)

MiruPasswordField(
value = password,
onValueChange = { password = it },
label = "Password"
)

MiruSearchField(
value = query,
onValueChange = { query = it },
onSearch = { performSearch(query) }
)

Top Bar​

MiruTopBar(
title = "Products",
onBackClick = { navController.popBackStack() }
)

MiruSearchTopBar(
query = searchQuery,
onQueryChange = { searchQuery = it },
onSearch = { performSearch() }
)

Cards​

MiruCard(onClick = { }) {
Text("Card content")
}

MiruInfoCard(
title = "Order Status",
subtitle = "Your order is being processed"
)

Dialogs​

MiruAlertDialog(
title = "Delete Item",
message = "Are you sure?",
onConfirm = { deleteItem() },
onDismiss = { }
)

MiruConfirmationDialog(
title = "Confirm Action",
onConfirm = { },
onCancel = { }
)

MiruLoadingDialog(message = "Processing...")

Bottom Sheet​

MiruBottomSheet(
visible = showSheet,
onDismiss = { showSheet = false }
) {
// Sheet content
}

Loading & Empty States​

MiruFullScreenLoading(message = "Loading...")
MiruLoadingIndicator()
MiruShimmerEffect()
MiruEmptyView(message = "No items found")
MiruErrorView(message = "Something went wrong", onRetry = { })

Images​

MiruNetworkImage(
url = "https://example.com/image.jpg",
contentDescription = "Product image"
)

Spacers​

MiruSpacer(size = 16) // Both directions
MiruVerticalSpacer(size = 8) // Vertical only
MiruHorizontalSpacer(size = 12) // Horizontal only

Component List​

ComponentDescription
MiruButtonPrimary action button with loading state
MiruTextFieldText input field
MiruPasswordFieldPassword input with visibility toggle
MiruSearchFieldSearch input with action
MiruTopBarApp bar with back navigation
MiruSearchTopBarApp bar with search functionality
MiruBottomSheetModal bottom sheet
MiruCardClickable card container
MiruInfoCardCard with title and subtitle
MiruAlertDialogAlert dialog with confirm/dismiss
MiruLoadingDialogLoading overlay dialog
MiruConfirmationDialogConfirmation dialog
MiruErrorViewError state with retry
MiruEmptyViewEmpty state message
MiruFullScreenLoadingFull screen loading indicator
MiruLoadingIndicatorInline loading indicator
MiruShimmerEffectShimmer placeholder effect
MiruNetworkImageCoil-powered network image
MiruResourceViewDeclarative Resource state renderer
MiruSpacerSpacing utility