Morphing sheet
A draggable surface that interpolates its height and corner radius, then settles into a compact or expanded state.

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 morphing-sheet
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 position: HugsySheetPosition = .compact
HugsyMorphingSheet(position: $position) { state in
VStack(spacing: 20) {
Text("Now playing").font(.headline)
if state == .expanded { PlayerDetails() }
}
.padding(.horizontal, 24)
}
Bind HugsySheetPosition to your screen state. Supply compact and expanded heights and content that adapts to the current position. Dragging is limited to the handle so content can keep its own gestures. Use native .sheet presentation if your app requires a modal barrier.
API reference
| Parameter | Type & behavior | Default |
|---|---|---|
position | Binding<HugsySheetPosition>Either .compact or .expanded. Drives the inline surface. | Required |
compactHeight | CGFloatCollapsed height, clamped to at least 100 points. | 200 |
expandedHeight | CGFloatExpanded height, at least 44 points above the compact height. | 430 |
content | (HugsySheetPosition) -> ContentContent that adapts to the current position. | Required |
Interaction
Drag the handle upward to expand the surface. Tap the handle to toggle without dragging.
Accessibility
The handle is a labeled native button. VoiceOver users can also adjust the surface with increment and decrement actions. Reduce Motion disables spring interpolation. This is an inline surface, not a replacement for the focus containment of a system sheet.
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.