Skip to content

Instantly share code, notes, and snippets.

@mireabot
Created February 8, 2025 16:47
Show Gist options
  • Save mireabot/fbfaacf084e44e75c024a2044a0dd5d5 to your computer and use it in GitHub Desktop.
Save mireabot/fbfaacf084e44e75c024a2044a0dd5d5 to your computer and use it in GitHub Desktop.
Banking Widgets UI
import SwiftUI
// MARK: - BankingSnippet View
struct BankingSnippet: View {
var body: some View {
VStack {
// Header
header(amount: 16500)
// Widget 1
bankingWidget()
// Widget 2
investmentWidget()
Button(action: {}, label: {
HStack {
Image(systemName: "plus")
.font(.system(.footnote, weight: .regular))
Text("Add category")
.font(.system(.headline, weight: .regular))
}
})
.buttonStyle(PrimaryButtonStyle())
}
.padding(.horizontal, 16)
}
// MARK: - Subviews
@ViewBuilder
func header(amount: Double) -> some View {
VStack(alignment: .leading, spacing: 12, content: {
VStack(alignment: .leading, spacing: 4, content: {
HStack {
Text("Net worth")
.font(.system(.callout, weight: .medium))
.foregroundColor(.secondary)
Spacer()
Button(action: {}, label: {
Image(systemName: "ellipsis")
.font(.system(.headline, weight: .regular))
.foregroundColor(.secondary)
})
}
Text("\(amount, specifier: "%.2f")")
.font(.system(.largeTitle, weight: .bold))
.foregroundColor(.primary)
HStack(spacing: 4) {
Image(systemName: "arrow.triangle.2.circlepath")
Text("Balance with pending")
}
.font(.system(.callout))
.foregroundColor(.secondary)
})
Button(action: {}, label: {
HStack {
Text("All transactions")
.font(.system(.headline, weight: .regular))
Image(systemName: "chevron.right")
.font(.system(.footnote, weight: .regular))
}
})
.buttonStyle(PrimaryButtonStyle())
})
.padding(.vertical, 12)
.padding(.horizontal, 16)
.background(Color(hex: "#1018181B"))
.cornerRadius(10)
}
@ViewBuilder
func bankingWidget() -> some View {
VStack(spacing: 10) {
HStack {
Text("Banking")
.font(.system(.subheadline, weight: .medium))
.foregroundColor(.secondary)
Spacer()
HStack(spacing: 10) {
Button(action: {}, label: {
Image(systemName: "plus")
.font(.system(.headline, weight: .regular))
.foregroundColor(.secondary)
})
Button(action: {}, label: {
Image(systemName: "ellipsis")
.font(.system(.headline, weight: .regular))
.foregroundColor(.secondary)
})
}
}
.padding(.top, 12)
.padding(.horizontal, 16)
VStack(spacing: 4) {
widgetCell(leftIcon: Image(systemName: "building.columns"), name: "CityBank", amount: 0)
.cornerRadius(8, corners: [.topLeft, .topRight])
widgetCell(leftIcon: Image(systemName: "dollarsign"), name: "Cash", amount: 12500)
widgetCell(leftIcon: Image(systemName: "building.columns"), name: "American Express", amount: 7900)
.cornerRadius(8, corners: [.bottomLeft, .bottomRight])
}
.padding(.horizontal, 4)
.padding(.bottom, 4)
}
.background(Color(hex: "#1018181B"))
.cornerRadius(10)
}
@ViewBuilder
func investmentWidget() -> some View {
VStack(spacing: 10) {
HStack {
Text("Investments")
.font(.system(.subheadline, weight: .medium))
.foregroundColor(.secondary)
Spacer()
HStack(spacing: 10) {
Button(action: {}, label: {
Image(systemName: "plus")
.font(.system(.headline, weight: .regular))
.foregroundColor(.secondary)
})
Button(action: {}, label: {
Image(systemName: "ellipsis")
.font(.system(.headline, weight: .regular))
.foregroundColor(.secondary)
})
}
}
.padding(.top, 12)
.padding(.horizontal, 16)
VStack(spacing: 4) {
widgetCell(leftIcon: Image(systemName: "chart.line.uptrend.xyaxis"), name: "Stocks", amount: 1500)
.cornerRadius(8, corners: [.topLeft, .topRight])
widgetCell(leftIcon: Image(systemName: "bitcoinsign"), name: "Crypto", amount: 10228)
.cornerRadius(8, corners: [.bottomLeft, .bottomRight])
}
.padding(.horizontal, 4)
.padding(.bottom, 4)
}
.background(Color(hex: "#1018181B"))
.cornerRadius(10)
}
@ViewBuilder
func widgetCell(leftIcon: Image, name: String, amount: Double) -> some View {
HStack {
HStack(alignment: .center, spacing: 6) {
leftIcon
.foregroundColor(Color(hex: "#52525B"))
.frame(width: 20, height: 20)
Text(name)
}
.font(.system(.headline, weight: .regular))
Spacer()
HStack(alignment: .center, spacing: 6) {
Text("$\(amount, specifier: "%.2f")")
.foregroundColor(amount > 0 ? .primary : .secondary)
Image(systemName: "chevron.right")
.font(.system(.caption, weight: .regular))
.foregroundColor(.secondary)
}
}
.padding(.horizontal, 12)
.padding(.vertical, 10)
.background(.white)
}
}
#Preview {
BankingSnippet()
}
// MARK: Button Styles
struct PrimaryButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.frame(maxWidth: .infinity, alignment: .center)
.padding(.vertical, 12)
.padding(.horizontal, 0)
.background(Color(hex: "#1218181B"))
.cornerRadius(10)
}
}
// MARK: - Extensions
extension Color {
init(hex: String) {
let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int: UInt64 = 0
Scanner(string: hex).scanHexInt64(&int)
let a, r, g, b: UInt64
switch hex.count {
case 3: // RGB (12-bit)
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
case 6: // RGB (24-bit)
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
case 8: // ARGB (32-bit)
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
default:
(a, r, g, b) = (255, 0, 0, 0)
}
self.init(
.sRGB,
red: Double(r) / 255,
green: Double(g) / 255,
blue: Double(b) / 255,
opacity: Double(a) / 255
)
}
}
extension View {
func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
clipShape(RoundedCorner(radius: radius, corners: corners))
}
}
// Custom RoundedCorner shape
struct RoundedCorner: Shape {
var radius: CGFloat = .infinity
var corners: UIRectCorner = .allCorners
func path(in rect: CGRect) -> Path {
let path = UIBezierPath(
roundedRect: rect,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius)
)
return Path(path.cgPath)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment