mirror of
https://codeberg.org/secana/Forji.git
synced 2026-06-16 05:13:55 -07:00
fix: stop login button collapsing on press release
Replace the .borderedProminent + .controlSize(.large) login button with a custom FlatPrimaryButtonStyle. The system style's built-in press treatment springs/scales on release, which on iOS 26 read as the button's lower edge collapsing when the finger lifted. The flat style changes only background opacity on press — no scaleEffect, no spring — so the frame never moves. Keeps the full-width fill, the large hit target, and a ZStack label that holds the frame steady while the loading spinner is shown. Generated with Claude Opus 4.8 (1M)
This commit is contained in:
parent
d69674b3ab
commit
4547075a21
1 changed files with 38 additions and 7 deletions
|
|
@ -144,19 +144,18 @@ struct InstanceFormView: View {
|
|||
|
||||
Section {
|
||||
Button(action: handleSave) {
|
||||
HStack {
|
||||
Spacer()
|
||||
ZStack {
|
||||
Text(isAddMode ? "Login" : "Save")
|
||||
.fontWeight(.semibold)
|
||||
.opacity(isLoading ? 0 : 1)
|
||||
if isLoading {
|
||||
ProgressView()
|
||||
.progressViewStyle(.circular)
|
||||
} else {
|
||||
Text(isAddMode ? "Login" : "Save")
|
||||
.fontWeight(.semibold)
|
||||
.tint(.white)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.buttonStyle(FlatPrimaryButtonStyle())
|
||||
.disabled(
|
||||
isLoading || serverURL.isEmpty
|
||||
|| (authMode == .credentials
|
||||
|
|
@ -330,6 +329,38 @@ struct InstanceFormView: View {
|
|||
}
|
||||
}
|
||||
|
||||
/// A full-width primary button style with a large hit target.
|
||||
///
|
||||
/// Defines its own appearance instead of relying on `.borderedProminent`, whose built-in
|
||||
/// press treatment springs/scales on release — on iOS 26 that read as the button's lower
|
||||
/// edge "collapsing" when the finger lifted. This style changes only the background opacity
|
||||
/// on press, with no `scaleEffect` and no spring, so the frame never moves.
|
||||
private struct FlatPrimaryButtonStyle: ButtonStyle {
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
Background(configuration: configuration)
|
||||
}
|
||||
|
||||
private struct Background: View {
|
||||
let configuration: ButtonStyleConfiguration
|
||||
@Environment(\.isEnabled) private var isEnabled
|
||||
|
||||
var body: some View {
|
||||
configuration.label
|
||||
.font(.headline)
|
||||
.foregroundStyle(.white)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 14)
|
||||
.background(Color.accentColor.opacity(backgroundOpacity), in: .rect(cornerRadius: 14))
|
||||
.contentShape(.rect(cornerRadius: 14))
|
||||
}
|
||||
|
||||
private var backgroundOpacity: Double {
|
||||
if !isEnabled { return 0.35 }
|
||||
return configuration.isPressed ? 0.85 : 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#Preview("Add") {
|
||||
InstanceFormView(authService: .previewDefault, mode: .add)
|
||||
|
|
|
|||
Loading…
Reference in a new issue