Card

A flexible card component for grouping related content with optional headers, footers, and interactive states.

Import

import PrettyUI

Basic Usage

PCard {
    Text("This is card content.")
}

Variants

PCard supports 3 visual variants:

// Standard - subtle shadow (default)
PCard {
    Text("Standard card")
}.variant(.standard)

// Elevated - larger shadow for floating appearance
PCard {
    Text("Elevated card")
}.variant(.elevated)

// Flat - no shadow, border only
PCard {
    Text("Flat card")
}.variant(.flat)
VariantShadowBorderBest For
.standardSmallOptionalMost use cases
.elevatedLargeNoneFeatured content, floating elements
.flatNoneYesSubtle grouping, forms

With Header

Add a title and optional description:

PCard {
    Text("Your card content here...")
} header: {
    PCardTitle("Settings", description: "Manage your preferences")
}

Custom Header

PCard {
    Text("Content...")
} header: {
    HStack {
        Image(systemName: "star.fill")
            .foregroundColor(.yellow)
        Text("Featured")
            .font(.headline)
        Spacer()
        PIconButton("ellipsis") {}
    }
}

Add action buttons or supplementary content:

PCard {
    VStack(alignment: .leading, spacing: 8) {
        Text("Email")
            .font(.caption)
            .foregroundColor(.gray)
        Text("john@example.com")
    }
} header: {
    PCardTitle("Account")
} footer: {
    HStack {
        Spacer()
        PButton("Cancel").variant(.ghost)
        PButton("Save").variant(.primary)
    }
}

Pressable Cards

Make cards interactive with tap gestures:

PCard {
    HStack {
        VStack(alignment: .leading, spacing: 4) {
            Text("Main Wallet")
                .font(.headline)
            Text("0x1234...5678")
                .font(.caption)
                .foregroundColor(.gray)
        }
        Spacer()
        Text("$10,234.56")
            .font(.title2)
            .fontWeight(.semibold)
    }
}
.pressable {
    print("Wallet tapped!")
}

Selected State

Highlight selected cards with a border:

PCard {
    HStack {
        Image(systemName: "checkmark.circle.fill")
            .foregroundColor(.green)
        Text("Premium Plan")
        Spacer()
        Text("$9.99/mo")
    }
}
.selected(isSelected)

// With custom border color
.selected(isSelected, borderColor: .purple)

Custom Padding

Control padding independently:

// Both horizontal and vertical
PCard {
    Text("Content")
}
.padding(horizontal: .xl, vertical: .sm)

// Individual axis
PCard {
    Text("Content")
}
.paddingHorizontal(.lg)
.paddingVertical(.xs)

Real-World Examples

Wallet Card

PCard {
    HStack {
        VStack(alignment: .leading, spacing: 4) {
            Text("Main Wallet")
                .font(.headline)
            Text("0x1234...5678")
                .font(.caption)
                .foregroundColor(.gray)
        }
        Spacer()
        Text("$10,234.56")
            .font(.title2)
            .fontWeight(.semibold)
    }
}
.variant(.elevated)
.pressable {
    openWallet()
}

Settings Card

PCard {
    VStack(spacing: 0) {
        SettingsRow(icon: "bell", title: "Notifications")
        Divider()
        SettingsRow(icon: "lock", title: "Privacy")
        Divider()
        SettingsRow(icon: "paintbrush", title: "Appearance")
    }
} header: {
    PCardTitle("Preferences")
}
.paddingVertical(.xs)

Selection Card

ForEach(plans) { plan in
    PCard {
        HStack {
            VStack(alignment: .leading) {
                Text(plan.name).font(.headline)
                Text(plan.description).font(.caption)
            }
            Spacer()
            Text(plan.price)
        }
    }
    .selected(selectedPlan == plan.id)
    .pressable {
        selectedPlan = plan.id
    }
}

API Reference

Initializers

// Content only
PCard(
    radius: RadiusSize? = nil,
    shadow: ShadowSize? = nil,
    padding: SpacingSize? = nil,
    @ViewBuilder content: () -> Content
)

// With header
PCard(
    @ViewBuilder content: () -> Content,
    @ViewBuilder header: () -> Header
)

// With header and footer
PCard(
    @ViewBuilder content: () -> Content,
    @ViewBuilder header: () -> Header,
    @ViewBuilder footer: () -> Footer
)

Modifiers

ModifierTypeDescription
.variant(_:)PCardVariantVisual style
.pressable(_:)() -> VoidMake card tappable
.selected(_:borderColor:)Bool, Color?Selection state
.paddingHorizontal(_:)SpacingSizeHorizontal padding
.paddingVertical(_:)SpacingSizeVertical padding
.padding(horizontal:vertical:)SpacingSizeBoth axes

Enums

PCardVariant

  • .standard — Default with subtle shadow
  • .elevated — Large shadow, floating appearance
  • .flat — Border only, no shadow

Helper Components

PCardTitle

PCardTitle(_ title: String, description: String? = nil)

Styled title with optional description for card headers.

PCardHeader

PCardHeader {
    // Custom header content
}

Wrapper with proper styling for custom headers.

PCardFooter

PCardFooter {
    // Custom footer content
}

Wrapper with muted styling for footer content.

Accessibility

PCard automatically:

  • Groups content logically for VoiceOver
  • Announces pressable cards as buttons
  • Shows visual feedback for selected state