SwiftAwesomeButton is the SwiftUI package for expressive 3D-style buttons,
themed variants, progress states, text transitions, auto-width sizing, and
placeholder loading states.
The library exports:
AwesomeButtonThemedButtongetTheme- UIKit wrappers:
AwesomeButtonControlandThemedButtonControl - typed Swift models such as
AwesomeButtonStyle,AwesomeButtonThemeData,ThemeName,ButtonVariant,ButtonSize,ThemeButtonStyle,ThemeSizeStyle,ThemeDefinition, andRegisteredThemeDefinition
swift-demo-github.mp4
Add the package in Xcode through File > Add Package Dependencies...:
https://github.com/rcaferati/swift-awesome-button.git
Then add the SwiftAwesomeButton product to your iOS app target.
Current Swift support:
- Swift 5.10
- iOS 16.0+
- SwiftUI
import SwiftAwesomeButton
import SwiftUI
struct SaveButton: View {
var body: some View {
AwesomeButton(
child: "Save",
onPress: { _ in
print("Pressed")
}
)
}
}AwesomeButton supports both plain string labels and arbitrary SwiftUI labels.
AwesomeButton(
onPress: { _ in
print("Pressed")
}
) {
Label("Continue", systemImage: "arrow.right")
}
|
|
|
animateSize is enabled by default.
- fixed
width/heightchanges animate with the package size animation ThemedButtonsize preset changes animate because they resolve to fixed width and height updates- auto-width string labels grow and shrink when their measured target width changes
- with
textTransitionplus auto width, wider labels animate text while growing and narrower labels start text first, then shrink width after the text transition begins animateSize: falsekeeps size changes instant- fixed-to-auto and auto-to-fixed changes remain instant
Swift keeps auto-width target measurement inside the package renderer. The hidden measurement path is internal and does not intercept input.
import SwiftAwesomeButton
import SwiftUI
struct SizeExample: View {
let isLong: Bool
var body: some View {
let label = isLong ? "Open analytics dashboard" : "Open"
VStack(spacing: 12) {
ThemedButton(
child: label,
name: .basic,
autoWidth: true,
textTransition: true
)
ThemedButton(
child: label,
name: .basic,
autoWidth: true,
animateSize: false
)
}
}
}When progress is enabled, onPress receives an
AwesomeButtonProgressHandle?. Call it when your work is done to complete the
progress animation and release the button.
import SwiftAwesomeButton
import SwiftUI
struct SubmitButton: View {
var body: some View {
AwesomeButton(
child: "Submit",
progress: true,
onPress: { next in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
next?()
}
}
)
}
}Progress uses the typed completion contract:
public typealias AwesomeButtonPressCallback = (AwesomeButtonProgressHandle?) -> Void
public final class AwesomeButtonProgressHandle {
public func callAsFunction(_ callback: (() -> Void)? = nil)
}import SwiftAwesomeButton
import SwiftUI
struct ThemeExample: View {
var body: some View {
VStack(spacing: 12) {
ThemedButton(
child: "Rick Primary",
name: .rick,
type: .primary
)
ThemedButton(
child: "Rick Secondary",
name: .rick,
type: .secondary
)
}
}
}If you need the full registered theme object, use getTheme.
import SwiftAwesomeButton
import SwiftUI
struct ThemeConfigExample: View {
var body: some View {
let theme = getTheme(index: 0)
ThemedButton(
child: theme.title,
config: theme,
type: .anchor
)
}
}getTheme() safely falls back to the default basic theme if the provided
index or name is invalid.
Use before and after for inline content rendered inside the button face,
and extra for content rendered behind the active/content layers.
import SwiftAwesomeButton
import SwiftUI
struct ButtonContentExample: View {
var body: some View {
AwesomeButton(
before: AnyView(Image(systemName: "arrow.left").foregroundStyle(.white)),
after: AnyView(Image(systemName: "arrow.right").foregroundStyle(.white)),
extra: AnyView(
LinearGradient(
colors: [
Color(red: 0.30, green: 0.39, blue: 0.82),
Color(red: 0.74, green: 0.19, blue: 0.51),
Color(red: 0.96, green: 0.44, blue: 0.20),
Color(red: 1.00, green: 0.84, blue: 0.46),
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
),
style: AwesomeButtonStyle(
foregroundColor: .white
)
) {
Text("Continue")
.fontWeight(.bold)
.foregroundStyle(.white)
}
}
}transparent is supported on ThemedButton. It removes the visible shell
layers while preserving the content, hit target, and active/progress feedback.
import SwiftAwesomeButton
import SwiftUI
struct TransparentExample: View {
var body: some View {
ThemedButton(
child: "Transparent",
name: .bruce,
type: .anchor,
transparent: true
)
}
}basicbojackcartmanmysterionc137ricksummerbruce
primarysecondaryanchordangerdisabledflatxmessengerfacebookgithublinkedinwhatsappredditpinterestyoutube
iconsmallmediumlarge
The public surface is typed through AwesomeButton, ThemedButton, and their
UIKit wrappers.
| Parameter | Type | Default | Description |
|---|---|---|---|
child |
String? |
nil |
Plain string label. String labels support textTransition. |
onPress |
AwesomeButtonPressCallback? |
nil |
Main press callback. In progress mode it receives the completion handle. |
onLongPress |
(() -> Void)? |
nil |
Optional long-press callback. |
disabled |
Bool |
false |
Disables interactions. |
width |
CGFloat? |
nil |
Fixed width, or leave nil for auto width. Pair with stretch for full width. |
height |
CGFloat |
52 |
Face height before the raise layer is added. |
paddingHorizontal |
CGFloat? |
16 resolved |
Horizontal content padding. |
before |
AnyView? |
nil |
Content rendered before the main label inside the button face. |
after |
AnyView? |
nil |
Content rendered after the main label inside the button face. |
extra |
AnyView? |
nil |
Content rendered behind the active/content layers. |
stretch |
Bool |
false |
Makes the button fill the available horizontal space. |
style |
AwesomeButtonStyle? |
nil |
Visual override surface for colors, border, raise, animation, and typography. |
activeOpacity |
Double |
1 |
Opacity applied while the non-progress button is pressed. |
debouncedPressTime |
TimeInterval |
0 |
Debounces onPress dispatch. |
progress |
Bool |
false |
Enables the progress-button flow. |
showProgressBar |
Bool |
true |
Shows or hides the loading bar during progress. |
progressLoadingTime |
TimeInterval |
3 |
Duration of the loading bar travel in progress mode. |
animateSize |
Bool |
true |
Animates fixed-size geometry changes and auto-width string-label changes. |
textTransition |
Bool |
false |
Enables the built-in scramble/reveal animation when a plain string label changes. |
animatedPlaceholder |
Bool |
true |
Enables the shimmer loop when the button has no child. |
hapticOnPress |
Bool |
true |
Enables iOS haptic feedback on press. |
| Parameter | Type | Default | Description |
|---|---|---|---|
config |
ThemeDefinition? |
nil |
Explicit theme object. When provided, it takes precedence over name and index. |
index |
Int? |
nil |
Theme index used by getTheme(index:) when config and name are not provided. |
name |
ThemeName? |
nil |
Named built-in theme selector. |
type |
ButtonVariant |
.primary |
Built-in variant to resolve from the selected theme. |
size |
ButtonSize |
.medium |
Built-in theme size preset. |
flat |
Bool |
false |
Requests the flat theme variant when available. |
transparent |
Bool |
false |
Makes the visible shell layers transparent while keeping content, press, and progress feedback active. |
autoWidth |
Bool |
false |
Requests measured auto width instead of the size preset width. |
Primary package quality gate:
xcodebuild -scheme swift-awesome-button -destination 'platform=iOS Simulator,name=iPhone 17 Pro' testTo validate the demo app:
xcodebuild -project Examples/IOSAwesomeButtonDemoApp/IOSAwesomeButtonDemoApp.xcodeproj -scheme IOSAwesomeButtonDemoApp -destination 'generic/platform=iOS Simulator' buildPlain swift test is not the supported validation command for this repository.
The package is intentionally iOS-only, and that command attempts to compile the
SwiftUI target for macOS. Use the iOS Simulator xcodebuild test command above
for release validation.
The manual acceptance app lives in Examples/IOSAwesomeButtonDemoApp.
The app includes:
Themedtab with nested theme navigation and the full themed showcaseProgresstab with dedicated progress-button demosSocialtab with social-button demosSize Changestab for text and geometry transition demos
Open it in Xcode from the repository root:
open Examples/IOSAwesomeButtonDemoApp/IOSAwesomeButtonDemoApp.xcodeprojBuild it from the repository root:
xcodebuild -project Examples/IOSAwesomeButtonDemoApp/IOSAwesomeButtonDemoApp.xcodeproj -scheme IOSAwesomeButtonDemoApp -destination 'generic/platform=iOS Simulator' buildRafael Caferati
Website: https://caferati.dev
LinkedIn: https://linkedin.com/in/rcaferati
Instagram: https://instagram.com/rcaferati
MIT. See LICENSE. Third-party asset notices are listed in NOTICE.md.


