import SwiftUI public struct AIButtonStyle: ButtonStyle { public static let pressedScale: CGFloat = 0.97 public enum Kind: Hashable { case primary case secondary case danger var foregroundColor: Color { foregroundColor(isEnabled: true) } var backgroundColor: Color { backgroundColor(isEnabled: true) } func foregroundColor(isEnabled: Bool) -> Color { switch self { case .primary, .danger: return .white.opacity(isEnabled ? 1 : 0.72) case .secondary: return isEnabled ? AITheme.ink : AITheme.muted } } func backgroundColor(isEnabled: Bool) -> Color { switch self { case .primary: return isEnabled ? AITheme.primary : AITheme.primary.opacity(0.35) case .secondary: return isEnabled ? AITheme.surface : AITheme.canvas case .danger: return isEnabled ? AITheme.danger : AITheme.danger.opacity(0.30) } } } public enum Size: Hashable { case compact case regular case large case toolbar } private let kind: Kind private let size: Size private let fixedWidthRequest: CGFloat? let fillsWidth: Bool @Environment(\.isEnabled) private var isEnabled public init( kind: Kind = .secondary, size: Size = .regular, fixedWidth: CGFloat? = nil, fillsWidth: Bool = false ) { self.kind = kind self.size = size self.fixedWidthRequest = fixedWidth self.fillsWidth = fillsWidth } public func makeBody(configuration: Configuration) -> some View { let height: CGFloat = switch size { case .compact: AITheme.compactButtonHeight case .large: AITheme.largeButtonHeight case .regular: AITheme.buttonHeight case .toolbar: AITheme.toolbarButtonHeight } configuration.label .labelStyle(.titleAndIcon) .font(.system(size: size == .toolbar ? 15 : 16, weight: .semibold)) .lineLimit(1) .foregroundStyle(kind.foregroundColor(isEnabled: isEnabled)) .frame( minWidth: (!fillsWidth && fixedWidth == nil) ? minimumWidth : 0, minHeight: height ) .frame(maxWidth: fillsWidth ? .infinity : nil) .padding(.horizontal, fixedWidth == nil ? (kind == .secondary ? 12 : 14) : 0) .frame(width: fixedWidth) .background(kind.backgroundColor(isEnabled: isEnabled)) .clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius)) .overlay { RoundedRectangle(cornerRadius: AITheme.buttonRadius) .strokeBorder(kind == .secondary || !isEnabled ? AITheme.line : .clear) } .scaleEffect(configuration.isPressed ? Self.pressedScale : 1) .opacity(configuration.isPressed ? 0.82 : 1) } private var minimumWidth: CGFloat { switch size { case .compact: return AITheme.compactButtonMinWidth case .regular: return AITheme.regularButtonMinWidth case .large: return 92 case .toolbar: return AITheme.toolbarButtonMinWidth } } private var fixedWidth: CGFloat? { fixedWidthRequest ?? (size == .toolbar ? AITheme.toolbarButtonWidth : nil) } }