Introducing swift-components
I’ve open sourced swift-components, a Swift package of reusable SwiftUI components for iOS, macOS, and watchOS.
It’s the natural counterpart to @f-ewald/components, my web component library: the same idea of pulling recurring UI pieces out of individual apps and into a shared, documented package, just for native Apple platforms instead of the browser. I kept running into the same handful of needs across my iOS and macOS apps — a tip-of-the-day card, a feedback form, an onboarding wizard — and rewriting each one slightly differently every time. swift-components is where those pieces now live.
The package targets iOS 18+, macOS 15+, and watchOS 11+, built with Swift 6.2. It’s split into two libraries. SharedComponents is platform-agnostic and covers things like TipOfTheDayView and its companion TipOfTheDayService, which syncs bundled JSON tips through SwiftData and tracks which ones have already been shown; CloudSettings/CloudStorage for syncing app settings through iCloud key-value storage; HeroView for empty-state layouts; RatingsView and AppLaunchState, which prompt for an App Store review after a configurable number of launches; LogoVersionView for showing app branding alongside version/build info; StatusBannerView for inline error and info banners in lists; an error alert view modifier; and PowerUserView, a small easter-egg animation for users who’ve stuck around.
UIComponents adds iOS/macOS-specific pieces that don’t make sense on watchOS: FeedbackView and FeedbackService for an in-app feedback form with HTTP submission, shake-gesture detection on iOS, and WizardView/WizardService for multi-step onboarding flows defined in bundled JSON that track which steps are new per app version — useful for surfacing “what’s new” prompts without re-showing onboarding a user has already completed.
Installation is a standard Swift Package Manager dependency — add https://github.com/f-ewald/swift-components.git from version 1.0.0 in Package.swift, then pull in whichever of the two libraries a target needs. Both ship with swift build/swift test support and no other runtime dependencies.
Like the web component library, the goal here isn’t to build something exhaustive — it’s to stop re-solving the same small problems in every new app and instead have a single, tested place to fix them once.