SwiftUI Icon Bubble Component
A tinted container for an SF Symbol. The thing every settings row, feature list and empty state reinvents slightly differently.
Variants: Rounded, Circle
Install the free SwiftUI icon bubble
- Add SwiftKitUI.swift to your app once. It holds the tokens and motion curves.
- Copy SKIconBubble.swift below into your project. It needs nothing else.
Usage
Usage.swift
SKIconBubble("star.fill")
SKIconBubble("trash.fill", tone: .danger)
SKIconBubble("bolt.fill", tone: .accent, shape: .circle, size: SK.Icon.xl)Full source · 104 lines · MIT
SKIconBubble.swift
//
// SKIconBubble.swift
// Swift Kit UI
//
// Requires: SwiftKitUI.swift
//
// A tinted container for an SF Symbol. The thing every settings row, feature
// list and empty state reinvents slightly differently.
//
// Usage:
// SKIconBubble("star.fill")
// SKIconBubble("trash.fill", tone: .danger)
// SKIconBubble("bolt.fill", tone: .accent, shape: .circle, size: SK.Icon.xl)
//
import SwiftUI
public struct SKIconBubble: View {
public enum Tone: Sendable {
case neutral, accent, success, warning, danger
var foreground: Color {
switch self {
case .neutral: SK.Palette.labelSecondary
case .accent: SK.Palette.accent
case .success: SK.Palette.success
case .warning: SK.Palette.warning
case .danger: SK.Palette.danger
}
}
var background: Color {
switch self {
case .neutral: SK.Palette.fill
case .accent: SK.Palette.accentSoft
case .success: SK.Palette.successSoft
case .warning: SK.Palette.warningSoft
case .danger: SK.Palette.dangerSoft
}
}
}
public enum Shape_: Sendable { case rounded, circle }
private let systemImage: String
private let tone: Tone
private let shape: Shape_
private let size: CGFloat
public init(
_ systemImage: String,
tone: Tone = .accent,
shape: Shape_ = .rounded,
size: CGFloat = SK.Icon.md
) {
self.systemImage = systemImage
self.tone = tone
self.shape = shape
self.size = size
}
/// The container scales with the glyph so bubbles stay optically balanced
/// at any size instead of needing a second hard-coded number.
private var box: CGFloat { size * 2.1 }
public var body: some View {
Image(systemName: systemImage)
.font(SK.Icon.symbol(size))
.foregroundStyle(tone.foreground)
.frame(width: box, height: box)
.background {
switch shape {
case .rounded:
RoundedRectangle(cornerRadius: box * 0.28, style: .continuous)
.fill(tone.background)
case .circle:
Circle().fill(tone.background)
}
}
.accessibilityHidden(true)
}
}
#Preview("SKIconBubble") {
VStack(spacing: SK.Space.xl) {
HStack(spacing: SK.Space.md) {
SKIconBubble("star.fill")
SKIconBubble("checkmark", tone: .success)
SKIconBubble("exclamationmark.triangle.fill", tone: .warning)
SKIconBubble("trash.fill", tone: .danger)
SKIconBubble("gear", tone: .neutral)
}
HStack(spacing: SK.Space.md) {
SKIconBubble("bolt.fill", shape: .circle, size: SK.Icon.sm)
SKIconBubble("bolt.fill", shape: .circle, size: SK.Icon.md)
SKIconBubble("bolt.fill", shape: .circle, size: SK.Icon.lg)
SKIconBubble("bolt.fill", shape: .circle, size: SK.Icon.xl)
}
}
.padding(SK.Space.xl)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(SK.Palette.surfaceSunken)
}
Questions
- Is this SwiftUI icon bubble free for commercial apps?
- Yes. Swift Kit UI is MIT licensed, so you can use it in personal and commercial apps with no payment or sign-up. Keep the licence notice with the code.
- What does it depend on?
- SKIconBubble.swift depends only on SwiftKitUI.swift, a single foundation file with the design tokens and motion curves. There are no third-party packages.
- Which iOS versions does it support?
- iOS 17 and later, plus macOS 14.
Building a whole app? The Swift Kit adds auth, payments and onboarding, ready to ship.