feat(ios): unify list cards and loading states

This commit is contained in:
chick
2026-09-10 01:35:12 +08:00
parent 995206ac23
commit c841748971
32 changed files with 1297 additions and 607 deletions
@@ -1,6 +1,8 @@
import SwiftUI
public struct AIButtonStyle: ButtonStyle {
public static let pressedScale: CGFloat = 0.97
public enum Kind: Hashable {
case primary
case secondary
@@ -30,15 +32,25 @@ public struct AIButtonStyle: ButtonStyle {
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) {
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 {
@@ -46,20 +58,29 @@ public struct AIButtonStyle: ButtonStyle {
case .compact: AITheme.compactButtonHeight
case .large: AITheme.largeButtonHeight
case .regular: AITheme.buttonHeight
case .toolbar: AITheme.toolbarButtonHeight
}
configuration.label
.font(.system(size: 16, weight: .semibold))
.labelStyle(.titleAndIcon)
.font(.system(size: size == .toolbar ? 15 : 16, weight: .semibold))
.lineLimit(1)
.foregroundStyle(kind.foregroundColor(isEnabled: isEnabled))
.frame(minWidth: minimumWidth, minHeight: height)
.padding(.horizontal, kind == .secondary ? 12 : 14)
.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)
}
.opacity(configuration.isPressed ? 0.78 : 1)
.scaleEffect(configuration.isPressed ? Self.pressedScale : 1)
.opacity(configuration.isPressed ? 0.82 : 1)
}
private var minimumWidth: CGFloat {
@@ -67,6 +88,11 @@ public struct AIButtonStyle: ButtonStyle {
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)
}
}