A list of SwiftUI Bottom Sheet components
ManySheets has a list of custom SwiftUI Bottom Sheet components.
- DefaultBottomSheet: A dynamic bottom sheet that scales based on content height inside.
- ScaffoldBottomSheet: A scaffolding bottom sheet with three positions (top, middle, bottom).
See below for examples and customization.
- iOS 14.0+
- Xcode 13+
- Swift 5+
In Xcode, select: File > Swift Packages > Add Package Dependency.
Paste the package github url in the search bar https://github.com/GlennBrann/ManySheets and press next and follow instructions given via Xcode to complete installation.
You can then add ManySheets to your file by adding import ManySheets.
Or
Add this project on your Package.swift
import PackageDescription
let package = Package(
dependencies: [
.Package(url: "https://https://github.com/GlennBrann/ManySheets.git", from: "1.2.0")
]
)The DefaultBottomSheet is a basic bottom sheet that scales automatically depending on the content size within. You can add it directly into your view like so
DefaultBottomSheet(isOpen: style: options: content:)or via the modifier
View().defaultBottomSheet(isOpen: style: options: content:)isOpen- A binding used to display the bottom sheet.style- A property containing all bottom sheet stylingDefaultBottomSheetStyleoptions- An array that contains the bottom sheet optionsDefaultBottomSheetOptions.Optionscontent- A ViewBuilder used to set the content of the bottom sheet.
import SwiftUI
import ManySheets
struct DefaultBottomSheetExample: View {
@State var showSheet: Bool = false
let bottomSheetStyle = DefaultBottomSheetStyle(backgroundColor: .white)
var body: some View {
ZStack {
VStack {
Button(action: { showSheet.toggle() },
label: { Text("Show Default Sheet") })
}
DefaultBottomSheet(
isOpen: $showSheet,
style: bottomSheetStyle,
options: [.enableHandleBar, .tapAwayToDismiss, .swipeToDismiss]
) {
VStack(alignment: .leading) {
HStack(alignment: .top) {
Image(systemName: "info.circle")
Text("Photos attached must be of cats and cats only")
.fixedSize(horizontal: false, vertical: true)
}
.padding(.bottom, 4)
Button(
action: { },
label: {
HStack {
Image(systemName: "camera")
.foregroundColor(Color.blue)
Text("Take a photo")
}
}
)
.frame(height: 44)
Button(
action: { },
label: {
HStack {
Image(systemName: "photo.on.rectangle")
.foregroundColor(Color.blue)
Text("Choose a photo")
}
}
)
.frame(height: 44)
}
.padding()
.padding(.bottom, 16)
.buttonStyle(PlainButtonStyle())
}
}
}
}The ScaffoldBottomSheet is a bottom sheet that has three positions top, middle, and bottom. This bottom sheet can scroll content when fully open. This can be disabled by adding the .disableScroll option.
ScaffoldBottomSheet(isOpen: style: options: positions: defaultPosition: headerContent: bodyContent:)or via the modifier
View().scaffoldBottomSheet(isOpen: style: options: positions: defaultPosition: headerContent: bodyContent:)isOpen- A binding used to display the scaffold bottom sheet.style- A property containing all scaffold bottom sheet stylingScaffoldBottomSheetStyleoptions- An array that contains the bottom sheet optionsScaffoldBottomSheet.Optionspositions- AScaffoldBottomSheetPositionsstruct containing thetop,middle, andbottomheight percentages. Note: these values must be decimal representations of percentages i.e ((middle: 0.5) = 50% height)defaultPosition- The default position the scaffold bottom sheet will be in when isOpen from a closed state.headerContent- An optional header content view builderbodyContent- A ViewBuilder used to set the body content of the scaffold bottom sheet.
import SwiftUI
import ManySheets
struct ContentView: View {
@State var showSheet: Bool = false
let bottomSheetStyle = ScaffoldBottomSheetStyle(backgroundColor: .white)
let positions = ScaffoldBottomSheetPositions(top: 1, middle: 0.5, bottom: 0.13)
var body: some View {
ZStack {
VStack {
Button(action: { showSheet.toggle() },
label: { Text("Show Scaffold Sheet") })
}
ScaffoldBottomSheet(
isOpen: $showSheet,
style: bottomSheetStyle,
options: [.enableHandleBar, .tapAwayToDismiss, .swipeToDismiss],
positions: positions,
defaultPosition: .bottom,
headerContent: {
VStack(alignment: .leading) {
HStack {
Image("image")
.resizable()
.frame(width: 32, height: 32)
VStack(alignment: .leading) {
Text("Hello world")
.font(.caption)
.fontWeight(.bold)
Text("4:20pm")
.font(.caption2)
}
Spacer()
Button(action: { },
label: {
Image(systemName: "xmark.circle.fill")
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(Color.gray.opacity(0.5))
})
}
.padding(.horizontal)
.padding(.bottom, 4)
Divider()
}
.buttonStyle(PlainButtonStyle())
},
bodyContent: {
HStack {
RoundedRectangle(cornerRadius: 10)
.fill(Color.gray.opacity(0.12))
.frame(width: 64, height: 64)
.overlay(Image(systemName: "camera").foregroundColor(Color.blue))
RoundedRectangle(cornerRadius: 10)
.fill(Color.gray.opacity(0.12))
.frame(width: 64, height: 64)
.overlay(Image(systemName: "sun.max.fill").foregroundColor(Color.yellow))
RoundedRectangle(cornerRadius: 10)
.fill(Color.gray.opacity(0.12))
.frame(width: 64, height: 64)
.overlay(Image(systemName: "photo").foregroundColor(Color.red))
RoundedRectangle(cornerRadius: 10)
.fill(Color.gray.opacity(0.12))
.frame(width: 64, height: 64)
.overlay(Image(systemName: "trash").foregroundColor(Color.green))
RoundedRectangle(cornerRadius: 10)
.fill(Color.gray.opacity(0.12))
.frame(width: 64, height: 64)
.overlay(Image(systemName: "snow").foregroundColor(Color.orange))
Spacer()
}
.padding()
ForEach(["Hello", "World", "Nice", "Bottom", "Sheet", "Many", "Sheets"], id: \.self) { text in
VStack {
HStack {
Text(text)
Spacer()
Image(systemName: "camera")
}
.frame(height: 32)
.padding(.horizontal, 24)
Divider()
}
}
Text("This is a description with a lot of text that should wrap and fill properly repeating.This is a description with a lot of text that should wrap and fill properly repeating.This is a description with a lot of text that should wrap and fill properly repeating.This is a description with a lot of text that should wrap and fill properly repeating.")
.padding()
})
}
}
}(No major rhyme or reason to these releases)
- 1.0.0
- CHANGE: Added DefaultBottomSheet and ScaffoldBottomSheet
- 1.0.1
- CHANGE: Setting minimum iOS version to iOS 14. More stable
- 1.0.2
- CHANGE: Bug fix for compiler error and Color.black.opacity()
- 1.1.0
- CHANGE: XC 13 minimum + other things
- 1.2.1
- CHANGE: Compiles against iOS 14 + ExampleApp workspace
ManySheets is available under the MIT license. See the LICENSE file for more info.

