Skip to content

sonmbol/Shimmer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Shimmer

Swift Platforms License

A lightweight, dependency-free shimmer loading effect built entirely with SwiftUI.

Shimmer preserves the layout of your real interface, applies native placeholder redaction, and animates an adaptive highlight across the rendered content. It supports composite view hierarchies, light and dark appearances, and loading representations for controls that SwiftUI does not redact automatically.

Demo

Screen.Recording.2026-07-09.at.10.21.17.AM.mov

Preview video

Add the package preview recording here.

Features

  • One-line integration on any SwiftUI view hierarchy.
  • Native placeholder redaction with no duplicate content model.
  • Smooth diagonal highlight animation.
  • Automatic light and dark appearance blending.
  • Loading-specific ToggleStyle and ProgressViewStyle.
  • Full-width shimmer rendering for wide cards and containers.
  • Interaction disabled automatically while loading.
  • Dynamic text wrapping and existing layout dimensions preserved.
  • No external dependencies.
  • DEBUG-only interactive preview gallery.

Requirements

Platform Minimum version
iOS 17.0
macOS 14.0
tvOS 17.0
watchOS 10.0
Swift 6.0

Installation

Xcode

  1. Open your project in Xcode.
  2. Select File > Add Package Dependencies.
  3. Enter the repository URL:
https://github.com/sonmbol/Shimmer.git
  1. Add the Shimmer product to your application target.

Package.swift

Add Shimmer to your package dependencies:

dependencies: [
    .package(
        url: "https://github.com/sonmbol/Shimmer.git",
        from: "1.0.0"
    )
]

Then add it to the dependencies of your target:

.target(
    name: "YourTarget",
    dependencies: [
        .product(name: "Shimmer", package: "Shimmer")
    ]
)

Quick Start

Import Shimmer, provide a loading binding, and apply the modifier to the content that should become a placeholder:

import Shimmer
import SwiftUI

struct ProfileView: View {
    @State private var isLoading = true

    var body: some View {
        HStack(alignment: .top, spacing: 12) {
            Image(systemName: "person.crop.circle.fill")
                .resizable()
                .scaledToFit()
                .frame(width: 56, height: 56)

            VStack(alignment: .leading, spacing: 6) {
                Text("Ahmed Suliman")
                    .font(.headline)

                Text("Senior iOS Engineer")
                    .font(.subheadline)

                ProgressView(value: 0.65)
            }

            Spacer()
        }
        .shimmer(if: $isLoading)
        .task {
            try? await Task.sleep(for: .seconds(2))
            isLoading = false
        }
    }
}

When isLoading is true, Shimmer keeps the hierarchy's natural layout and renders its loading representation. When the value becomes false, the original content is restored.

Controls

SwiftUI's native placeholder redaction primarily targets text and images. Controls such as switches and progress indicators retain their normal chrome. Shimmer installs private loading-only styles inside the modifier to provide consistent placeholders:

  • Toggle preserves its label and replaces the switch with a placeholder capsule.
  • ProgressView preserves optional labels and renders a full-width placeholder track.
  • Buttons retain their existing shape while their content is redacted and neutralized.

The original styles return automatically as soon as loading finishes.

Interaction

The modified hierarchy does not accept pointer or touch input while loading:

.allowsHitTesting(false)

This prevents placeholder buttons, toggles, links, and other controls from performing actions before their content is ready.

Appearance

The highlight adapts to the active ColorScheme:

  • Light appearance uses a clear-to-white highlight.
  • Dark appearance uses a translucent white highlight with screen blending.

Control tint and saturation are neutralized only during loading, producing a consistent skeleton appearance without altering the loaded interface.

Preview Gallery

The package includes ShimmerModifier+Preview.swift, which demonstrates:

  • Single-line and multiline text.
  • Images and labels.
  • Buttons, toggles, and progress indicators.
  • Composite cards.
  • Repeated collection rows.
  • Loading-state toggling.
  • Light and dark appearance switching.

The entire preview file is guarded by #if DEBUG, so preview code is excluded from release builds.

Public API

View extension

public extension View {
    func shimmer(if isLoading: Binding<Bool>) -> some View
}

Modifier

public struct ShimmerModifier: ViewModifier {
    public init(isLoading: Binding<Bool>)
}

The extension is the recommended integration:

content.shimmer(if: $isLoading)

The modifier can also be applied directly:

content.modifier(ShimmerModifier(isLoading: $isLoading))

Design Notes

Shimmer operates on the composed SwiftUI hierarchy and does not inspect private view internals. It relies on native redaction for standard content and public control-style APIs for controls requiring explicit loading geometry.

The package intentionally avoids runtime reflection, private SwiftUI APIs, and recursive subview traversal. This keeps rendering predictable and suitable for production applications.

Contributing

Issues and pull requests are welcome. Please include:

  • A concise description of the behavior.
  • The affected platform and OS version.
  • A minimal reproduction or preview when reporting a visual issue.

Before opening a pull request, verify both configurations:

swift build
swift build -c release

License

Shimmer is released under the MIT License.

About

A lightweight, dependency-free SwiftUI shimmer loading effect with adaptive control placeholders and dark mode support.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages