Skip to content

Instantly share code, notes, and snippets.

@odrobnik
Last active March 14, 2025 21:01
Show Gist options
  • Save odrobnik/10b8f128462a4932b1b89655411a82dc to your computer and use it in GitHub Desktop.
Save odrobnik/10b8f128462a4932b1b89655411a82dc to your computer and use it in GitHub Desktop.
A generic file icon with a file name badge
import SwiftUI
struct ImagePlaceholder: View {
// MARK: - Properties
/// File extension to display (without the dot)
let fileExtension: String?
@State var badgeColor: Color?
// MARK: - Body
var body: some View {
GeometryReader { geometry in
let size = min(geometry.size.width, geometry.size.height)
let iconPadding = size * 0.2
let badgeFontSize = size * 0.12
let badgeStrokeWidth = size * 0.04
let badgeHorizontalPadding = size * 0.05
let badgeVerticalPadding = size * 0.02
ZStack {
// Background for the entire placeholder
Color.clear
// Document icon - standalone without the badge overlap
Image(systemName: "doc")
.resizable()
.aspectRatio(contentMode: .fit)
.padding(iconPadding)
.foregroundColor(.black)
// Extension badge as a standalone element
if let fileExtension = fileExtension {
Text(fileExtension.uppercased())
.font(.system(size: badgeFontSize, weight: .black))
.padding(.horizontal, badgeHorizontalPadding)
.padding(.vertical, badgeVerticalPadding)
.background(
ZStack {
// White background that extends beyond the text
RoundedRectangle(cornerRadius: 4)
.fill(badgeColor ?? .white)
.padding(-badgeStrokeWidth/2+1) // Extend slightly to prevent hairline gaps
// Border on top of background
RoundedRectangle(cornerRadius: 4)
.stroke(Color.black, lineWidth: badgeStrokeWidth)
}
)
.foregroundColor(.black)
.offset(x: badgeHorizontalPadding * 2, y: badgeVerticalPadding * 5)
}
}
}
.compositingGroup()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment