MyCuppa

SwiftUI Components

Cuppa provides a comprehensive library of SwiftUI components that follow iOS Human Interface Guidelines while maintaining consistency across your application.

Component Library

Buttons

CuppaButton

A customizable button component with multiple styles:

import CuppaUI

struct ButtonExamples: View {
    var body: some View {
        VStack(spacing: 16) {
            // Primary button
            CuppaButton(
                title: "Primary Action",
                style: .primary,
                action: { handleAction() }
            )

            // Secondary button
            CuppaButton(
                title: "Secondary Action",
                style: .secondary,
                action: { handleAction() }
            )

            // Destructive button
            CuppaButton(
                title: "Delete",
                style: .destructive,
                action: { confirmDelete() }
            )

            // Loading state
            CuppaButton(
                title: "Submit",
                style: .primary,
                isLoading: isSubmitting,
                action: { submit() }
            )

            // Disabled state
            CuppaButton(
                title: "Disabled",
                style: .primary,
                isDisabled: true,
                action: { }
            )
        }
        .padding()
    }
}

IconButton

Button with icon support:

CuppaIconButton(
    icon: Image(systemName: "heart.fill"),
    style: .primary,
    action: { toggleFavorite() }
)

Form Inputs

TextField

Text input with validation and styling:

struct FormExample: View {
    @State private var email = ""
    @State private var name = ""
    @State private var phone = ""

    var body: some View {
        Form {
            CuppaTextField(
                text: $email,
                placeholder: "Email",
                keyboardType: .emailAddress,
                autocapitalization: .none,
                validation: .email
            )

            CuppaTextField(
                text: $name,
                placeholder: "Full Name",
                leadingIcon: Image(systemName: "person")
            )

            CuppaTextField(
                text: $phone,
                placeholder: "Phone",
                keyboardType: .phonePad,
                format: .phone
            )
        }
    }
}

SecureField

Password input field:

@State private var password = ""

CuppaSecureField(
    text: $password,
    placeholder: "Password",
    showToggle: true,  // Show/hide password toggle
    validation: .password
)

TextEditor

Multi-line text input:

@State private var notes = ""

CuppaTextEditor(
    text: $notes,
    placeholder: "Enter your notes",
    minHeight: 100,
    maxHeight: 300
)

Lists and Collections

CuppaList

Enhanced list component with built-in features:

struct ItemListView: View {
    let items: [Item]
    @State private var selectedItem: Item?

    var body: some View {
        CuppaList(
            items,
            selection: $selectedItem,
            emptyState: {
                EmptyStateView(
                    icon: "tray",
                    title: "No Items",
                    message: "Add your first item to get started"
                )
            }
        ) { item in
            ItemRow(item: item)
        }
        .refreshable {
            await refreshItems()
        }
        .searchable(text: $searchText)
    }
}

Grid

Responsive grid layout:

CuppaGrid(
    items: products,
    columns: 2,
    spacing: 16
) { product in
    ProductCard(product: product)
}

Cards

Card

Container with elevation and rounded corners:

CuppaCard {
    VStack(alignment: .leading, spacing: 12) {
        Text("Card Title")
            .font(.headline)
        Text("Card content goes here")
            .font(.body)
        Divider()
        HStack {
            CuppaButton(title: "Action", style: .primary) { }
            Spacer()
            CuppaButton(title: "Cancel", style: .secondary) { }
        }
    }
    .padding()
}

Modals and Sheets

BottomSheet

Sliding bottom sheet:

struct ContentView: View {
    @State private var showSheet = false

    var body: some View {
        VStack {
            CuppaButton(title: "Show Sheet", style: .primary) {
                showSheet = true
            }
        }
        .cuppaBottomSheet(isPresented: $showSheet) {
            SheetContent()
        }
    }
}

struct SheetContent: View {
    var body: some View {
        VStack(spacing: 20) {
            Text("Bottom Sheet")
                .font(.headline)
            Text("Content goes here")
            CuppaButton(title: "Close", style: .secondary) {
                // Close sheet
            }
        }
        .padding()
    }
}

Modal

Full-screen or custom modal:

.cuppaModal(isPresented: $showModal) {
    ModalContent()
}

Alert

Custom alert dialog:

CuppaAlert(
    isPresented: $showAlert,
    title: "Confirm Action",
    message: "Are you sure you want to proceed?",
    primaryButton: .default("Confirm") {
        confirmAction()
    },
    secondaryButton: .cancel()
)

Navigation

TabBar

Bottom tab navigation:

CuppaTabView {
    HomeView()
        .cuppaTab(title: "Home", icon: "house")

    SearchView()
        .cuppaTab(title: "Search", icon: "magnifyingglass")

    ProfileView()
        .cuppaTab(title: "Profile", icon: "person")
}

NavigationBar

Custom navigation bar:

CuppaNavigationStack {
    ContentView()
        .cuppaNavigationBar(title: "Home")
        .cuppaNavigationBarItems(
            leading: {
                Button("Menu") { showMenu = true }
            },
            trailing: {
                Button("Settings") { showSettings = true }
            }
        )
}

Indicators

Loading

Activity indicators:

// Spinner
CuppaLoadingSpinner(style: .large)

// Progress bar
CuppaProgressBar(progress: 0.7)

// Skeleton loader
CuppaSkeletonView {
    VStack {
        CuppaSkeletonLine(width: 200)
        CuppaSkeletonLine(width: 150)
        CuppaSkeletonCircle(size: 60)
    }
}

Toast

Temporary notification:

struct ContentView: View {
    @State private var showToast = false

    var body: some View {
        VStack {
            CuppaButton(title: "Show Toast", style: .primary) {
                showToast = true
            }
        }
        .cuppaToast(
            isPresented: $showToast,
            message: "Action completed successfully",
            type: .success,
            duration: 3
        )
    }
}

Media

Image

Enhanced image component with loading states:

CuppaAsyncImage(
    url: imageURL,
    placeholder: {
        ProgressView()
    },
    error: {
        Image(systemName: "photo")
            .foregroundColor(.gray)
    }
)
.aspectRatio(contentMode: .fill)
.frame(width: 200, height: 200)
.clipShape(RoundedRectangle(cornerRadius: 12))

Video Player

Video playback component:

CuppaVideoPlayer(
    url: videoURL,
    autoplay: true,
    controls: true
)

Theming

Apply custom themes to components:

struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .cuppaTheme(
                    CuppaTheme(
                        primaryColor: .blue,
                        secondaryColor: .purple,
                        fontFamily: "SF Pro",
                        cornerRadius: 12,
                        spacing: 16
                    )
                )
        }
    }
}

Component Modifiers

Cuppa provides custom view modifiers for common patterns:

// Rounded corners with shadow
myView
    .cuppaCard(cornerRadius: 12, shadow: .medium)

// Shimmer loading effect
myView
    .cuppaShimmer(isLoading: isLoading)

// Haptic feedback on tap
myButton
    .cuppaHaptic(.light)

Accessibility

All Cuppa components include built-in accessibility support:

CuppaButton(
    title: "Submit",
    style: .primary,
    accessibilityLabel: "Submit form",
    accessibilityHint: "Double tap to submit the form"
) {
    submit()
}

Next Steps