|
import SwiftUI |
|
|
|
/// A button style designed to highlight key actions with a pill-shaped appearance |
|
/// |
|
/// To apply this style to a button, use the `buttonStyle(_:)` modifier. |
|
/// For example: |
|
/// ```swift |
|
/// Button("Action") { |
|
/// // Button action |
|
/// } |
|
/// .buttonStyle(.pill) // Applies the pill button style |
|
/// ``` |
|
public struct PillButtonStyle: PrimitiveButtonStyle { |
|
/// Creates a pill button style. |
|
public init() {} |
|
|
|
/// Creates a view that represents the body of a button. |
|
/// |
|
/// The system calls this method for each ``Button`` instance in a view |
|
/// hierarchy where this style is the current button style. |
|
/// |
|
/// - Parameter configuration: The properties of the button. |
|
/// - Returns: A view that represents the body of the button. |
|
public func makeBody(configuration: Configuration) -> some View { |
|
Button(role: configuration.role, action: configuration.trigger) { |
|
configuration.label |
|
.labeledContentStyle(.compact) |
|
.lineLimit(1) |
|
} |
|
.buttonStyle(.bordered) |
|
.buttonBorderShape(.capsule) |
|
.overlay { Capsule().stroke(.tint).opacity(0.5) } |
|
.applyTintIfDestructive(configuration.role) |
|
} |
|
} |
|
|
|
private extension View { |
|
/// Applies a red tint to the button if its role is `.destructive`. |
|
/// |
|
/// - Parameter role: The role of the button which determines if the |
|
/// tint should be applied. |
|
/// - Returns: A view that either has a red tint applied or remains unchanged. |
|
@ViewBuilder |
|
func applyTintIfDestructive(_ role: ButtonRole?) -> some View { |
|
if role == .destructive { |
|
tint(.red) |
|
} else { |
|
self |
|
} |
|
} |
|
} |
|
|
|
public extension PrimitiveButtonStyle where Self == PillButtonStyle { |
|
/// A pill button style that applies a pill-shaped border around the button |
|
/// and conditionally tints it based on the button's role. |
|
/// |
|
/// You can also use `PillButtonStyle()` to construct this style. |
|
static var pill: PillButtonStyle { |
|
PillButtonStyle() |
|
} |
|
} |
|
|
|
#Preview(traits: .sizeThatFitsLayout) { |
|
Group { |
|
Button("Extra Large") {} |
|
.buttonStyle(.pill) |
|
.controlSize(.extraLarge) |
|
|
|
Button("Default") {} |
|
.buttonStyle(.pill) |
|
|
|
Button("Mini") {} |
|
.buttonStyle(.pill) |
|
.controlSize(.mini) |
|
|
|
Button("Accent") {} |
|
.buttonStyle(.pill) |
|
.tint(.accentColor) |
|
|
|
Button("Green") {} |
|
.buttonStyle(.pill) |
|
.tint(.green) |
|
|
|
Button("Orange") {} |
|
.buttonStyle(.pill) |
|
.tint(.orange) |
|
|
|
Button("Delete", role: .destructive) {} |
|
.buttonStyle(.pill) |
|
|
|
Button("Disabled") {} |
|
.buttonStyle(.pill) |
|
.disabled(true) |
|
} |
|
} |