refactor: move rule editor actions into the navigation bar
- Both editor modes commit via a checkmark confirmation button (role: .confirm) in the navigation bar — accessibility labels 'Add Rule' (create) and 'Done' (edit); replaces the bottom 'Add Rule' button, so nothing floats over the form anymore - Edit mode gains an ellipsis 'Rule Actions' menu next to the checkmark holding Disable/Enable Rule and destructive Delete Rule; the red form rows are removed - Tests pin the checkmark to the navigation bar with its label and drive disable/delete through the menu; the swipe-to-reach workarounds are gone. 95 passing - Spec §6 updated Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -6,9 +6,9 @@
|
||||
import SwiftUI
|
||||
|
||||
/// The rule editor as a plain Form, always pushed inside a NavigationStack
|
||||
/// (New Rule flow and detail editing both push it). Creation commits with a
|
||||
/// prominent "Add Rule" button; editing uses a toolbar Done plus red
|
||||
/// Disable/Delete rows.
|
||||
/// (New Rule flow and detail editing both push it). Both modes commit via a
|
||||
/// checkmark confirmation button in the navigation bar; edit mode adds an
|
||||
/// ellipsis "Rule Actions" menu (Disable/Enable, Delete) next to it.
|
||||
struct RuleEditorView: View {
|
||||
enum Mode: Equatable {
|
||||
case create
|
||||
@@ -27,20 +27,6 @@ struct RuleEditorView: View {
|
||||
Form {
|
||||
nameSection
|
||||
sections
|
||||
if case .edit(let isEnabled) = mode {
|
||||
Section {
|
||||
Button(isEnabled ? "Disable Rule" : "Enable Rule") {
|
||||
onToggleEnabled?()
|
||||
}
|
||||
.foregroundStyle(.red)
|
||||
.accessibilityIdentifier("toggleEnabledButton")
|
||||
|
||||
Button("Delete Rule", role: .destructive) {
|
||||
onDelete?()
|
||||
}
|
||||
.accessibilityIdentifier("deleteRuleButton")
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
@@ -50,32 +36,41 @@ struct RuleEditorView: View {
|
||||
.lineLimit(1)
|
||||
.accessibilityIdentifier("ruleEditorTitle")
|
||||
}
|
||||
if case .edit = mode {
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button("Done") {
|
||||
onCommit(draft.sanitized())
|
||||
if case .edit(let isEnabled) = mode {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Menu {
|
||||
Button(isEnabled ? "Disable Rule" : "Enable Rule") {
|
||||
onToggleEnabled?()
|
||||
}
|
||||
Button("Delete Rule", role: .destructive) {
|
||||
onDelete?()
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "ellipsis")
|
||||
}
|
||||
.accessibilityIdentifier("doneButton")
|
||||
.accessibilityLabel("Rule Actions")
|
||||
.accessibilityIdentifier("ruleActionsMenu")
|
||||
}
|
||||
}
|
||||
}
|
||||
.safeAreaInset(edge: .bottom) {
|
||||
if mode == .create {
|
||||
Button {
|
||||
onCommit(draft.sanitized())
|
||||
} label: {
|
||||
Text("Add Rule")
|
||||
.frame(maxWidth: .infinity)
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
switch mode {
|
||||
case .create:
|
||||
Button(role: .confirm) {
|
||||
onCommit(draft.sanitized())
|
||||
} label: {
|
||||
Image(systemName: "checkmark")
|
||||
}
|
||||
.accessibilityLabel("Add Rule")
|
||||
.accessibilityIdentifier("commitRuleButton")
|
||||
case .edit:
|
||||
Button(role: .confirm) {
|
||||
onCommit(draft.sanitized())
|
||||
} label: {
|
||||
Image(systemName: "checkmark")
|
||||
}
|
||||
.accessibilityLabel("Done")
|
||||
.accessibilityIdentifier("doneButton")
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.controlSize(.large)
|
||||
.accessibilityIdentifier("commitRuleButton")
|
||||
.padding(.horizontal)
|
||||
.padding(.vertical, 10)
|
||||
.frame(maxWidth: .infinity)
|
||||
// Bar material so scrolling form content doesn't collide
|
||||
// with the floating button.
|
||||
.background(.bar)
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingAppPicker) {
|
||||
|
||||
Reference in New Issue
Block a user