MyCuppa

Jetpack Compose Components

Cuppa provides a comprehensive library of Jetpack Compose components that follow Material Design 3 guidelines while maintaining consistency across your application.

Component Library

Buttons

CuppaButton

A customizable button component with multiple variants:

import io.mycuppa.ui.components.*

@Composable
fun ButtonExamples() {
    Column(
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        // Primary button
        CuppaButton(
            text = "Primary Action",
            onClick = { handleAction() },
            variant = ButtonVariant.Primary
        )

        // Secondary button
        CuppaButton(
            text = "Secondary Action",
            onClick = { handleAction() },
            variant = ButtonVariant.Secondary
        )

        // Outlined button
        CuppaButton(
            text = "Outlined",
            onClick = { handleAction() },
            variant = ButtonVariant.Outlined
        )

        // Text button
        CuppaButton(
            text = "Text Only",
            onClick = { handleAction() },
            variant = ButtonVariant.Text
        )

        // Loading state
        CuppaButton(
            text = "Submit",
            onClick = { submit() },
            isLoading = isSubmitting
        )

        // Disabled state
        CuppaButton(
            text = "Disabled",
            onClick = { },
            enabled = false
        )
    }
}

IconButton

Button with icon support:

CuppaIconButton(
    icon = Icons.Default.Favorite,
    onClick = { toggleFavorite() },
    contentDescription = "Add to favorites"
)

Form Inputs

TextField

Text input with validation and styling:

@Composable
fun FormExample() {
    var email by remember { mutableStateOf("") }
    var name by remember { mutableStateOf("") }
    var phone by remember { mutableStateOf("") }

    Column(
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        CuppaTextField(
            value = email,
            onValueChange = { email = it },
            label = "Email",
            placeholder = "Enter your email",
            keyboardType = KeyboardType.Email,
            validation = ValidationRule.Email
        )

        CuppaTextField(
            value = name,
            onValueChange = { name = it },
            label = "Full Name",
            leadingIcon = Icons.Default.Person
        )

        CuppaTextField(
            value = phone,
            onValueChange = { phone = it },
            label = "Phone",
            keyboardType = KeyboardType.Phone
        )
    }
}

PasswordField

Password input with show/hide toggle:

var password by remember { mutableStateOf("") }

CuppaPasswordField(
    value = password,
    onValueChange = { password = it },
    label = "Password",
    placeholder = "Enter your password",
    showToggle = true
)

TextArea

Multi-line text input:

var notes by remember { mutableStateOf("") }

CuppaTextArea(
    value = notes,
    onValueChange = { notes = it },
    label = "Notes",
    placeholder = "Enter your notes",
    minLines = 3,
    maxLines = 10
)

Lists and Collections

LazyColumn

Enhanced lazy column with built-in features:

@Composable
fun ItemListScreen(
    items: List<Item>,
    onItemClick: (Item) -> Unit
) {
    CuppaLazyColumn(
        items = items,
        emptyState = {
            CuppaEmptyState(
                icon = Icons.Default.Inbox,
                title = "No Items",
                message = "Add your first item to get started"
            )
        }
    ) { item ->
        CuppaListItem(
            title = item.title,
            subtitle = item.description,
            onClick = { onItemClick(item) },
            leading = {
                Icon(Icons.Default.Circle, null)
            },
            trailing = {
                Icon(Icons.Default.ChevronRight, null)
            }
        )
    }
}

Grid

Responsive grid layout:

CuppaGrid(
    items = products,
    columns = 2,
    spacing = 16.dp
) { product ->
    ProductCard(product = product)
}

Cards

Card

Container with elevation and rounded corners:

CuppaCard(
    modifier = Modifier.padding(16.dp),
    elevation = 4.dp
) {
    Column(
        modifier = Modifier.padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        Text(
            text = "Card Title",
            style = MaterialTheme.typography.titleMedium
        )
        Text(
            text = "Card content goes here",
            style = MaterialTheme.typography.bodyMedium
        )
        HorizontalDivider()
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            CuppaButton(
                text = "Action",
                onClick = { },
                modifier = Modifier.weight(1f)
            )
            CuppaButton(
                text = "Cancel",
                onClick = { },
                variant = ButtonVariant.Secondary,
                modifier = Modifier.weight(1f)
            )
        }
    }
}

Dialogs and Sheets

BottomSheet

Modal bottom sheet:

@Composable
fun ScreenWithBottomSheet() {
    var showSheet by remember { mutableStateOf(false) }

    Column {
        CuppaButton(
            text = "Show Sheet",
            onClick = { showSheet = true }
        )
    }

    if (showSheet) {
        CuppaBottomSheet(
            onDismiss = { showSheet = false }
        ) {
            Column(
                modifier = Modifier.padding(16.dp),
                verticalArrangement = Arrangement.spacedBy(16.dp)
            ) {
                Text(
                    text = "Bottom Sheet",
                    style = MaterialTheme.typography.titleLarge
                )
                Text("Content goes here")
                CuppaButton(
                    text = "Close",
                    onClick = { showSheet = false }
                )
            }
        }
    }
}

Dialog

Alert dialog:

CuppaAlertDialog(
    isOpen = showDialog,
    onDismiss = { showDialog = false },
    title = "Confirm Action",
    message = "Are you sure you want to proceed?",
    confirmButton = {
        CuppaButton(
            text = "Confirm",
            onClick = {
                confirmAction()
                showDialog = false
            }
        )
    },
    dismissButton = {
        CuppaButton(
            text = "Cancel",
            onClick = { showDialog = false },
            variant = ButtonVariant.Text
        )
    }
)

Navigation

BottomNavigationBar

Bottom navigation with icons and labels:

@Composable
fun MainScreen() {
    var selectedTab by remember { mutableStateOf(0) }

    Scaffold(
        bottomBar = {
            CuppaBottomNavigationBar(
                selectedIndex = selectedTab,
                onTabSelected = { selectedTab = it },
                tabs = listOf(
                    BottomNavTab(
                        label = "Home",
                        icon = Icons.Default.Home
                    ),
                    BottomNavTab(
                        label = "Search",
                        icon = Icons.Default.Search
                    ),
                    BottomNavTab(
                        label = "Profile",
                        icon = Icons.Default.Person
                    )
                )
            )
        }
    ) { paddingValues ->
        // Screen content
    }
}

TopAppBar

Top app bar with navigation and actions:

CuppaTopAppBar(
    title = "Screen Title",
    navigationIcon = {
        IconButton(onClick = { navigateBack() }) {
            Icon(Icons.Default.ArrowBack, "Back")
        }
    },
    actions = {
        IconButton(onClick = { openSettings() }) {
            Icon(Icons.Default.Settings, "Settings")
        }
    }
)

Indicators

LoadingSpinner

Activity indicator:

// Circular spinner
CuppaLoadingSpinner(
    size = 48.dp,
    color = MaterialTheme.colorScheme.primary
)

// Linear progress
CuppaLinearProgress(
    progress = 0.7f,
    modifier = Modifier.fillMaxWidth()
)

Snackbar

Temporary notification:

@Composable
fun ScreenWithSnackbar() {
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()

    Scaffold(
        snackbarHost = { SnackbarHost(snackbarHostState) }
    ) { paddingValues ->
        CuppaButton(
            text = "Show Snackbar",
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar(
                        message = "Action completed",
                        actionLabel = "Undo",
                        duration = SnackbarDuration.Short
                    )
                }
            }
        )
    }
}

Media

AsyncImage

Image loading with placeholders:

CuppaAsyncImage(
    url = imageUrl,
    contentDescription = "Product image",
    placeholder = {
        CircularProgressIndicator()
    },
    error = {
        Icon(
            Icons.Default.BrokenImage,
            contentDescription = null
        )
    },
    modifier = Modifier
        .size(200.dp)
        .clip(RoundedCornerShape(12.dp))
)

Theming

Apply custom themes:

@Composable
fun MyApp() {
    CuppaTheme(
        colorScheme = customColorScheme,
        typography = customTypography,
        shapes = customShapes
    ) {
        // App content
    }
}

val customColorScheme = lightColorScheme(
    primary = Color(0xFF6200EE),
    secondary = Color(0xFF03DAC6),
    background = Color(0xFFFFFBFE)
)

Modifiers

Cuppa provides custom modifiers for common patterns:

// Card styling with shadow
myContent
    .cuppaCard(
        cornerRadius = 12.dp,
        elevation = 4.dp
    )

// Shimmer loading effect
myContent
    .cuppaShimmer(isLoading = isLoading)

// Clickable with ripple
myContent
    .cuppaClickable(
        onClick = { },
        rippleEnabled = true
    )

Accessibility

All Cuppa components include built-in accessibility support:

CuppaButton(
    text = "Submit",
    onClick = { submit() },
    modifier = Modifier.semantics {
        contentDescription = "Submit form button"
        role = Role.Button
    }
)

Next Steps