Skip to content

Instantly share code, notes, and snippets.

@cedricbahirwe
Created September 13, 2021 08:02
Show Gist options
  • Save cedricbahirwe/09fb12334d2dd91a4604c95c562bcd21 to your computer and use it in GitHub Desktop.
Save cedricbahirwe/09fb12334d2dd91a4604c95c562bcd21 to your computer and use it in GitHub Desktop.
A Simple Top SideBar View in SwiftUI
import SwiftUI
struct TopSideBarView: View {
private enum Constants {
static let foregrounColor = Color(.systemBackground)
static let backgroundColor = Color(.label).opacity(0.9)
static let avatarMinSize: CGFloat = 60
static let avatarMaxSize: CGFloat = .infinity
static let avatarCornerRadius = avatarMinSize / 2
static let maxHeight: CGFloat = 260
}
@State var isExpanded = false
private var scaledBackground: some View {
Rectangle()
.fill(Constants.backgroundColor)
.frame(maxWidth: isExpanded ? Constants.avatarMaxSize : Constants.avatarMinSize)
.frame(maxHeight: isExpanded ? Constants.maxHeight : Constants.avatarMinSize)
.cornerRadius(isExpanded ? 0 : Constants.avatarMinSize)
}
var body: some View {
ZStack(alignment: .top) {
VStack {
HStack {
if !isExpanded { Spacer() }
ZStack {
scaledBackground
if !isExpanded {
Image(systemName: "person.fill")
.resizable()
.frame(width: Constants.avatarMinSize-20,
height: Constants.avatarMinSize-20)
.clipShape(Circle())
.padding(3)
.foregroundColor(Constants.foregrounColor)
.onTapGesture {
withAnimation {
isExpanded.toggle()
}
}
}
}
.ignoresSafeArea(.all, edges: isExpanded ? .top : .init())
}
Spacer()
}
VStack(spacing: 15) {
if isExpanded {
HStack {
Image(systemName: "person.fill")
.resizable()
.frame(width: Constants.avatarMinSize-15,
height: Constants.avatarMinSize-15)
.clipShape(Circle())
.padding(3)
.allowsHitTesting(false)
.foregroundColor(Constants.foregrounColor)
VStack(alignment: .leading) {
Text("Cédric Bahirwe")
.lineLimit(1)
.minimumScaleFactor(0.8)
.font(.body.weight(.semibold))
Text("@cedricbahirwe")
}
Spacer()
}
menuButton(image: "arrow.uturn.left.circle.fill", title: "Log Out"){}
menuButton(image: "gear", title: "Settings") { }
Image(systemName: "plus")
.resizable()
.frame(width: Constants.avatarMinSize/2,
height: Constants.avatarMinSize/2)
.rotationEffect(.degrees(isExpanded ? 45 : 0))
.foregroundColor(Constants.foregrounColor)
.padding(5)
.onTapGesture {
withAnimation {
isExpanded.toggle()
}
}
}
}
.padding(10)
.foregroundColor(Constants.foregrounColor)
}
.preferredColorScheme(.dark)
.gesture (
DragGesture()
.onChanged { value in
if value.predictedEndTranslation.height < -100 || value.translation.height < -100 {
withAnimation {
isExpanded = false
}
}
}
.onEnded { value in
if value.predictedEndTranslation.height < -100 || value.translation.height < -100 {
withAnimation {
isExpanded = false
}
}
}
)
}
private func menuButton(image: String, title: String,
action: @escaping() -> ()) -> some View {
Button(action: action) {
Image(systemName: image).font(.title)
Text(title).font(.title)
}
}
}
struct TopSideBarView_Previews: PreviewProvider {
static var previews: some View {
TopSideBarView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment