Expanding cards
Cards that open into an immersive detail view, with shared geometry and a drag-to-dismiss gesture.
Real SwiftUI, captured on an iPhone 17 Pro simulator. Run the native gallery
Installation
Install the native Swift CLI, then add the component to your app.
hugsy add expanding-cards
Prefer to copy it yourself? Open the complete Swift file and add it to your iOS app target in Xcode. No package dependency is required.
Usage
@State private var selected: Story.ID?
HugsyExpandingCards(items: stories, selection: $selected) { story, expanded in
VStack(alignment: .leading, spacing: 16) {
Text(story.title).font(.largeTitle.bold())
if expanded { Text(story.description) }
}
.padding(28)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(story.color.gradient)
}
Supply Identifiable items and one content builder. The builder receives the item and its expanded state. Keep card IDs stable and unique. Place the component in a container with enough vertical room for the expanded content. It is an inline expanding surface, not a system modal sheet.
API reference
| Parameter | Type & behavior | Default |
|---|---|---|
items | [Item: Identifiable]Your models, with stable and unique IDs. | Required |
selection | Binding<Item.ID?>The open card ID. Set nil to close it programmatically. | Required |
cardHeight | CGFloatCollapsed height, clamped to at least 44 points. | 180 |
expandedHeight | CGFloatOpen height, clamped to at least the card height. | 440 |
content | (Item, Bool) -> ContentA view builder receiving the model and expanded state. | Required |
Interaction
Tap a card to open its details. Drag downward to dismiss, or use the close button.
Accessibility
Native buttons expose card actions. Expanded content hides the underlying cards from VoiceOver. A labeled close button and Escape accessibility action provide alternatives to dragging. Reduce Motion removes spring interpolation.
Test with VoiceOver, Dynamic Type, and Reduce Motion on a physical device before shipping. The gallery demonstrates the interaction, not every application-specific content state.
