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

- Loaders
- iOS 18.0+
- beginner
- Origin
- Original work
- Found by
- loader · sf symbols · symbol effect · breathe · rotate · loading · cargador · símbolo · efecto de símbolo · respirar · rotación · carga
Description
Section titled “Description”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) }}API reference
Section titled “API reference”| Parameter | Type | Default |
|---|---|---|
systemName | String | "sparkles" |
effect | SymbolBreatheLoaderEffect | .breathe |
color | Color | .indigo |
font | Font | .largeTitle |
Copy this code into your project, or download the file.
// 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()}