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 stylingDefaultBottomSheetStyle
options
- An array that contains the bottom sheet optionsDefaultBottomSheetOptions.Options
content
- 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 stylingScaffoldBottomSheetStyle
options
- An array that contains the bottom sheet optionsScaffoldBottomSheet.Options
positions
- AScaffoldBottomSheetPositions
struct containing thetop
,middle
, andbottom
height 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.