feat(ios): refine native ui controls

This commit is contained in:
chick
2026-09-09 11:14:39 +08:00
parent c568e496b2
commit 995206ac23
18 changed files with 397 additions and 212 deletions
@@ -6,18 +6,22 @@ public struct AIButtonStyle: ButtonStyle {
case secondary
case danger
var foregroundColor: Color {
var foregroundColor: Color { foregroundColor(isEnabled: true) }
var backgroundColor: Color { backgroundColor(isEnabled: true) }
func foregroundColor(isEnabled: Bool) -> Color {
switch self {
case .primary, .danger: return .white
case .secondary: return AITheme.ink
case .primary, .danger: return .white.opacity(isEnabled ? 1 : 0.72)
case .secondary: return isEnabled ? AITheme.ink : AITheme.muted
}
}
var backgroundColor: Color {
func backgroundColor(isEnabled: Bool) -> Color {
switch self {
case .primary: return AITheme.primary
case .secondary: return AITheme.surface
case .danger: return AITheme.danger
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)
}
}
}
@@ -30,6 +34,7 @@ public struct AIButtonStyle: ButtonStyle {
private let kind: Kind
private let size: Size
@Environment(\.isEnabled) private var isEnabled
public init(kind: Kind = .secondary, size: Size = .regular) {
self.kind = kind
@@ -43,17 +48,25 @@ public struct AIButtonStyle: ButtonStyle {
case .regular: AITheme.buttonHeight
}
configuration.label
.font(.system(size: 15, weight: .semibold))
.foregroundStyle(kind.foregroundColor)
.frame(minWidth: 44, minHeight: height)
.padding(.horizontal, 14)
.background(kind.backgroundColor)
.clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius))
.overlay {
RoundedRectangle(cornerRadius: AITheme.buttonRadius)
.strokeBorder(kind == .secondary ? AITheme.line : .clear)
}
configuration.label
.font(.system(size: 16, weight: .semibold))
.foregroundStyle(kind.foregroundColor(isEnabled: isEnabled))
.frame(minWidth: minimumWidth, minHeight: height)
.padding(.horizontal, kind == .secondary ? 12 : 14)
.background(kind.backgroundColor(isEnabled: isEnabled))
.clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius))
.overlay {
RoundedRectangle(cornerRadius: AITheme.buttonRadius)
.strokeBorder(kind == .secondary || !isEnabled ? AITheme.line : .clear)
}
.opacity(configuration.isPressed ? 0.78 : 1)
}
private var minimumWidth: CGFloat {
switch size {
case .compact: return AITheme.compactButtonMinWidth
case .regular: return AITheme.regularButtonMinWidth
case .large: return 92
}
}
}
@@ -39,6 +39,58 @@ public struct AITag: View {
}
}
public struct AIFieldStyle: TextFieldStyle {
public init() {}
public func _body(configuration: TextField<Self._Label>) -> some View {
configuration
.padding(.horizontal, 12)
.frame(minHeight: AITheme.buttonHeight)
.background(AITheme.canvas)
.clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius))
.overlay {
RoundedRectangle(cornerRadius: AITheme.buttonRadius)
.strokeBorder(AITheme.line)
}
}
}
public struct AISearchField: View {
private let placeholder: String
@Binding private var text: String
private var onSubmit: (() -> Void)?
public init(
_ placeholder: String,
text: Binding<String>,
onSubmit: (() -> Void)? = nil
) {
self.placeholder = placeholder
self._text = text
self.onSubmit = onSubmit
}
public var body: some View {
HStack(spacing: 8) {
Image(systemName: "magnifyingglass")
.foregroundStyle(AITheme.muted)
TextField(placeholder, text: $text)
.textFieldStyle(.plain)
.onSubmit {
onSubmit?()
}
}
.padding(.horizontal, 12)
.frame(minHeight: AITheme.buttonHeight)
.background(AITheme.surface)
.clipShape(RoundedRectangle(cornerRadius: AITheme.buttonRadius))
.overlay {
RoundedRectangle(cornerRadius: AITheme.buttonRadius)
.strokeBorder(AITheme.line)
}
}
}
public struct AIBrandBar: View {
public init() {}
@@ -12,10 +12,12 @@ public enum AITheme {
public static let warning = Color(red: 0.722, green: 0.471, blue: 0.067)
public static let success = Color(red: 0.082, green: 0.584, blue: 0.439)
public static let buttonHeight: CGFloat = 38
public static let compactButtonHeight: CGFloat = 34
public static let largeButtonHeight: CGFloat = 42
public static let iconButtonSize: CGFloat = 40
public static let buttonRadius: CGFloat = 10
public static let cardRadius: CGFloat = 14
public static let buttonHeight: CGFloat = 44
public static let compactButtonHeight: CGFloat = 40
public static let largeButtonHeight: CGFloat = 50
public static let iconButtonSize: CGFloat = 44
public static let buttonRadius: CGFloat = 12
public static let cardRadius: CGFloat = 16
public static let compactButtonMinWidth: CGFloat = 58
public static let regularButtonMinWidth: CGFloat = 76
}