Skip to content

Symbol Breathe Loader

A loading indicator made of an SF Symbol that uses the breathe and rotate symbol effects.

Symbol Breathe Loader, playing
Download .swift
Origin
Original work
Found by
loader · sf symbols · symbol effect · breathe · rotate · loading · cargador · símbolo · efecto de símbolo · respirar · rotación · carga

An SF Symbol that breathes, rotates or does both while something loads.

With Reduce Motion on, the symbol stays still.

struct SymbolBreatheLoaderDemo: View {
@ScaledMetric(relativeTo: .largeTitle) private var heroSize = 130
var body: some View {
VStack(spacing: 48) {
SymbolBreatheLoader(systemName: "sparkles", color: .purple, font: .system(size: heroSize))
VStack(spacing: 6) {
Text("Working on it")
.font(.system(.title, design: .rounded, weight: .bold))
Text("Breathe, rotate or both")
.font(.body)
.foregroundStyle(.secondary)
}
HStack(spacing: 40) {
SymbolBreatheLoader(systemName: "gearshape.2.fill", effect: .rotate, color: .gray)
SymbolBreatheLoader(systemName: "arrow.trianglehead.2.clockwise", effect: .rotate, color: .blue)
SymbolBreatheLoader(systemName: "heart.fill", color: .pink)
SymbolBreatheLoader(systemName: "fan.fill", effect: .both, color: .teal)
}
}
.padding(24)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
ParameterTypeDefault
systemNameString"sparkles"
effectSymbolBreatheLoaderEffect.breathe
colorColor.indigo
fontFont.largeTitle

Copy this code into your project, or download the file.

SymbolBreatheLoader.swift
// SPDX-License-Identifier: MIT
// Copyright (c) 2026 Oscar Canton and SwiftUI Blocks contributors
import SwiftUI
enum SymbolBreatheLoaderEffect {
case breathe
case rotate
case both
}
/// An SF Symbol that breathes, rotates or does both while something loads.
///
/// With Reduce Motion on, the symbol stays still.
struct SymbolBreatheLoader: View {
var systemName: String = "sparkles"
var effect: SymbolBreatheLoaderEffect = .breathe
var color: Color = .indigo
var font: Font = .largeTitle
@Environment(\.accessibilityReduceMotion) private var reduceMotion
var body: some View {
Image(systemName: systemName)
.font(font)
.symbolRenderingMode(.hierarchical)
.foregroundStyle(color)
.symbolEffect(.breathe, options: .repeat(.continuous), isActive: !reduceMotion && effect != .rotate)
.symbolEffect(.rotate, options: .repeat(.continuous), isActive: !reduceMotion && effect != .breathe)
.accessibilityLabel("Loading")
}
}
// MARK: - Demo
struct SymbolBreatheLoaderDemo: View {
@ScaledMetric(relativeTo: .largeTitle) private var heroSize = 130
var body: some View {
VStack(spacing: 48) {
SymbolBreatheLoader(systemName: "sparkles", color: .purple, font: .system(size: heroSize))
VStack(spacing: 6) {
Text("Working on it")
.font(.system(.title, design: .rounded, weight: .bold))
Text("Breathe, rotate or both")
.font(.body)
.foregroundStyle(.secondary)
}
HStack(spacing: 40) {
SymbolBreatheLoader(systemName: "gearshape.2.fill", effect: .rotate, color: .gray)
SymbolBreatheLoader(systemName: "arrow.trianglehead.2.clockwise", effect: .rotate, color: .blue)
SymbolBreatheLoader(systemName: "heart.fill", color: .pink)
SymbolBreatheLoader(systemName: "fan.fill", effect: .both, color: .teal)
}
}
.padding(24)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
#Preview {
SymbolBreatheLoaderDemo()
}