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("com.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