- Fluent API for OS version-gated modifiers instead of nested
#availablechecks - View, ToolbarContent, and ToolbarItemPlacement extensions out of the box
- Generic
conditional()functions for any type Conditionalprotocol to add conditional support to custom typesOSVersionhelpers for clean version checks (OSVersion.iOS(17))
Important: Conditionals is for static conditions (OS versions, compile-time checks). For runtime state that changes, use standard SwiftUI patterns (
if, ternary,overlay). See When to Use for guidance.
// GOOD - OS version never changes at runtime
.conditional(if: OSVersion.iOS(17)) { view in view.fontDesign(.rounded) }
// BAD - use .foregroundStyle(isActive ? .blue : .gray) instead
.conditional(if: isActive) { view in view.foregroundStyle(.blue) }dependencies: [
.package(url: "https://github.com/aeastr/Conditionals.git", from: "1.0.0")
]import ConditionalsApply modifiers based on OS version availability:
Text("Modern UI")
.conditional { view in
if #available(iOS 26.0, *) {
view.glassEffect(.regular, in: .rect(cornerRadius: 12))
} else {
view.background(.regularMaterial, in: .rect(cornerRadius: 12))
}
}Text("Hello")
.conditional(if: OSVersion.iOS(17)) { view in
view.fontDesign(.rounded)
}Text("Hello")
.conditional(if: optionalColor) { view, color in
view.foregroundStyle(color)
}ToolbarItemGroup(
placement: .conditional(
if: OSVersion.iOS(26),
then: .bottomBar,
else: .secondaryAction
)
) {
Button("Edit") {}
}Text("Hello")
.conditional(
if: OSVersion.iOS(26),
apply: { $0.fontWeight(.bold) },
otherwise: { $0.fontWeight(.regular) }
)Text("Content")
.conditional(unless: isCompact) { view in
view.padding(.horizontal, 40)
}For inline value selection:
Text("Hello")
.foregroundStyle(
conditional(if: OSVersion.iOS(17), then: Color.red.gradient, else: Color.red)
)Add conditional support to any type with one line:
extension PresentationDetent: Conditional {}
// Now use it
.presentationDetents([
.conditional(if: OSVersion.iOS(16), then: .height(300), else: .medium)
])OSVersion.iOS(18) // Check iOS 18+
OSVersion.macOS(14) // Check macOS 14+
OSVersion.watchOS(10) // Check watchOS 10+
OSVersion.tvOS(17) // Check tvOS 17+
OS.is26 // Quick boolean check for iOS 26+Conditionals wraps the standard #available pattern in a chainable API using @ViewBuilder closures:
// Before: Verbose, breaks the chain
Group {
if #available(iOS 26.0, *) {
Text("Hello").glassEffect(.regular, in: .rect(cornerRadius: 12))
} else {
Text("Hello").background(.regularMaterial, in: .rect(cornerRadius: 12))
}
}
// After: Clean and chainable
Text("Hello")
.conditional { view in
if #available(iOS 26.0, *) {
view.glassEffect(.regular, in: .rect(cornerRadius: 12))
} else {
view.background(.regularMaterial, in: .rect(cornerRadius: 12))
}
}For iOS 26's glass effects specifically, check out UniversalGlass.
Contributions welcome. See the Contributing Guide for details.
MIT. See LICENSE for details.